From 182a2d134410b925202645d827cb78cb7998bb87 Mon Sep 17 00:00:00 2001 From: John Gibbon Date: Mon, 16 Nov 2020 21:38:55 +0100 Subject: [PATCH] ChatInfoPage as attached page fixes #150: Now basically everything is inside a loader; ChatInformationPage is added to ChatPage with pageStack.pushAttached fixes #166: Replaces the clunky VisualItemModel in tab view and doesn't initialize multiple times. --- harbour-fernschreiber.pro | 1 + .../ChatInformationPageContent.qml | 459 ++++++++++++++++++ .../ChatInformationTabItemBase.qml | 9 +- .../ChatInformationTabItemMembersGroups.qml | 35 +- .../ChatInformationTabItemSettings.qml | 4 +- .../ChatInformationTabView.qml | 66 +-- qml/pages/ChatInformationPage.qml | 442 ++--------------- qml/pages/ChatPage.qml | 4 +- translations/harbour-fernschreiber-de.ts | 104 ++-- translations/harbour-fernschreiber-en.ts | 104 ++-- translations/harbour-fernschreiber-es.ts | 104 ++-- translations/harbour-fernschreiber-fi.ts | 104 ++-- translations/harbour-fernschreiber-hu.ts | 92 ++-- translations/harbour-fernschreiber-it.ts | 106 ++-- translations/harbour-fernschreiber-pl.ts | 92 ++-- translations/harbour-fernschreiber-ru.ts | 96 ++-- translations/harbour-fernschreiber-sv.ts | 104 ++-- translations/harbour-fernschreiber-zh_CN.ts | 104 ++-- translations/harbour-fernschreiber.ts | 92 ++-- 19 files changed, 1089 insertions(+), 1033 deletions(-) create mode 100644 qml/components/chatInformationPage/ChatInformationPageContent.qml diff --git a/harbour-fernschreiber.pro b/harbour-fernschreiber.pro index bcd8333..f72d480 100644 --- a/harbour-fernschreiber.pro +++ b/harbour-fernschreiber.pro @@ -51,6 +51,7 @@ DISTFILES += qml/harbour-fernschreiber.qml \ qml/components/PhotoTextsListItem.qml \ qml/components/WebPagePreview.qml \ qml/components/chatInformationPage/ChatInformationEditArea.qml \ + qml/components/chatInformationPage/ChatInformationPageContent.qml \ qml/components/chatInformationPage/ChatInformationProfilePicture.qml \ qml/components/chatInformationPage/ChatInformationProfilePictureList.qml \ qml/components/chatInformationPage/ChatInformationTabItemBase.qml \ diff --git a/qml/components/chatInformationPage/ChatInformationPageContent.qml b/qml/components/chatInformationPage/ChatInformationPageContent.qml new file mode 100644 index 0000000..d69fa2b --- /dev/null +++ b/qml/components/chatInformationPage/ChatInformationPageContent.qml @@ -0,0 +1,459 @@ +/* + Copyright (C) 2020 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Fernschreiber is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fernschreiber. If not, see . +*/ +import QtQuick 2.6 +import Sailfish.Silica 1.0 +import "./chatInformationPage" +import "../js/twemoji.js" as Emoji +import "../js/functions.js" as Functions + + +SilicaFlickable { + id: pageContent + property alias membersList: membersList + + function initializePage() { + console.log("[ChatInformationPage] Initializing chat info page..."); + membersList.clear(); + var chatType = chatInformation.type["@type"]; + switch(chatType) { + case "chatTypePrivate": + chatInformationPage.isPrivateChat = true; + chatInformationPage.chatPartnerGroupId = chatInformationPage.chatInformation.type.user_id.toString(); + if(!chatInformationPage.privateChatUserInformation.id) { + chatInformationPage.privateChatUserInformation = tdLibWrapper.getUserInformation(chatInformationPage.chatPartnerGroupId); + } + tdLibWrapper.getUserFullInfo(chatInformationPage.chatPartnerGroupId); + tdLibWrapper.getUserProfilePhotos(chatInformationPage.chatPartnerGroupId, 100, 0); + break; + case "chatTypeBasicGroup": + chatInformationPage.isBasicGroup = true; + chatInformationPage.chatPartnerGroupId = chatInformation.type.basic_group_id.toString(); + if(!chatInformationPage.groupInformation.id) { + chatInformationPage.groupInformation = tdLibWrapper.getBasicGroup(chatInformationPage.chatPartnerGroupId); + } + tdLibWrapper.getGroupFullInfo(chatInformationPage.chatPartnerGroupId, false); + break; + case "chatTypeSupergroup": + chatInformationPage.isSuperGroup = true; + chatInformationPage.chatPartnerGroupId = chatInformation.type.supergroup_id.toString(); + if(!chatInformationPage.groupInformation.id) { + chatInformationPage.groupInformation = tdLibWrapper.getSuperGroup(chatInformationPage.chatPartnerGroupId); + } + + tdLibWrapper.getGroupFullInfo(chatInformationPage.chatPartnerGroupId, true); + chatInformationPage.isChannel = chatInformationPage.groupInformation.is_channel; + break; + } + console.log("is set up", chatInformationPage.isPrivateChat, chatInformationPage.isBasicGroup, chatInformationPage.isSuperGroup, chatInformationPage.chatPartnerGroupId) + if(!chatInformationPage.isPrivateChat) { + updateGroupStatusText(); + } + + + tabViewLoader.active = true; + } + 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) { + chatInformationPage.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); + } + chatInformationPage.groupInformation.member_count = groupFullInfo.members.length + updateGroupStatusText(); + } + } + function updateGroupStatusText() { + if (chatOnlineMemberCount > 0) { + headerItem.description = qsTr("%1 members, %2 online").arg(Functions.getShortenedCount(chatInformationPage.groupInformation.member_count)).arg(Functions.getShortenedCount(chatInformationPage.chatOnlineMemberCount)); + } else { + if (isChannel) { + headerItem.description = qsTr("%1 subscribers").arg(Functions.getShortenedCount(chatInformationPage.groupInformation.member_count)); + } else { + headerItem.description = qsTr("%1 members").arg(Functions.getShortenedCount(chatInformationPage.groupInformation.member_count)); + } + } + } + + Connections { + target: tdLibWrapper + + onChatOnlineMemberCountUpdated: { + if ((chatInformationPage.isSuperGroup || chatInformationPage.isBasicGroup) && chatInformationPage.chatInformation.id.toString() === chatId) { + chatInformationPage.chatOnlineMemberCount = chatInformationPage.onlineMemberCount; + updateGroupStatusText(); + } + } + onSupergroupFullInfoReceived: { + console.log("onSupergroupFullInfoReceived", chatInformationPage.isSuperGroup, chatInformationPage.chatPartnerGroupId, groupId) + if(chatInformationPage.isSuperGroup && chatInformationPage.chatPartnerGroupId === groupId) { + chatInformationPage.groupFullInformation = groupFullInfo; + } + } + onSupergroupFullInfoUpdated: { + console.log("onSupergroupFullInfoUpdated", chatInformationPage.isSuperGroup, chatInformationPage.chatPartnerGroupId, groupId) + if(chatInformationPage.isSuperGroup && chatInformationPage.chatPartnerGroupId === groupId) { + chatInformationPage.groupFullInformation = groupFullInfo; + } + } + onBasicGroupFullInfoReceived: { + if(chatInformationPage.isBasicGroup && chatInformationPage.chatPartnerGroupId === groupId) { + handleBasicGroupFullInfo(groupFullInfo) + } + } + + onBasicGroupFullInfoUpdated: { + if(chatInformationPage.isBasicGroup && chatInformationPage.chatPartnerGroupId === groupId) { + handleBasicGroupFullInfo(groupFullInfo) + } + } + onUserFullInfoReceived: { + if(chatInformationPage.isPrivateChat && userFullInfo["@extra"] === chatInformationPage.chatPartnerGroupId) { + chatInformationPage.chatPartnerFullInformation = userFullInfo; + } + } + onUserFullInfoUpdated: { + if(chatInformationPage.isPrivateChat && userId === chatInformationPage.chatPartnerGroupId) { + chatInformationPage.chatPartnerFullInformation = userFullInfo; + } + } + + onUserProfilePhotosReceived: { + if(chatInformationPage.isPrivateChat && extra === chatInformationPage.chatPartnerGroupId) { + chatInformationPage.chatPartnerProfilePhotos = photos; + } + } + onChatPermissionsUpdated: { + if (chatInformationPage.chatInformation.id.toString() === chatId) { + // set whole object to trigger change + var newInformation = chatInformation; + newInformation.permissions = permissions + chatInformationPage.chatInformation = newInformation + } + } + onChatTitleUpdated: { + if (chatInformationPage.chatInformation.id.toString() === chatId) { + // set whole object to trigger change + var newInformation = chatInformation; + newInformation.title = title + chatInformationPage.chatInformation = newInformation + } + } + } + + + + Component.onCompleted: { + console.log("completed chatinformationpage"); + initializePage(); + } + + + + ListModel { + id: membersList + } + + AppNotification { + id: infoNotification + } + PullDownMenu { + MenuItem { + visible: (chatPage.isSuperGroup || chatPage.isBasicGroup) && groupInformation && groupInformation.status["@type"] !== "chatMemberStatusBanned" + text: chatInformationPage.userIsMember ? qsTr("Leave Chat") : qsTr("Join Chat") + onClicked: { + // ensure it's done even if the page is closed: + if (chatInformationPage.userIsMember) { + 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)} )); + }; + }(chatInformationPage.chatInformation.id))) + } else { + tdLibWrapper.joinChat(chatInformationPage.chatInformation.id); + } + + + } + } + MenuItem { + visible: chatInformationPage.userIsMember + onClicked: { + var newNotificationSettings = chatInformationPage.chatInformation.notification_settings; + if (newNotificationSettings.mute_for > 0) { + newNotificationSettings.mute_for = 0; + } else { + newNotificationSettings.mute_for = 6666666; + } + newNotificationSettings.use_default_mute_for = false; + tdLibWrapper.setChatNotificationSettings(chatInformationPage.chatInformation.id, newNotificationSettings); + } + text: chatInformation.notification_settings.mute_for > 0 ? qsTr("Unmute Chat") : qsTr("Mute Chat") + } + // MenuItem { //TODO Implement + // visible: !userIsMember + // onClicked: { + // tdLibWrapper.joinChat(chatInformationPage.chatInformation.id); + // } + // text: qsTr("Join Chat") + // } + } + // header + PageHeader { + id: headerItem + z: 5 + Item { + id: imageContainer + property bool hasImage: typeof chatInformationPage.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 ? chatInformationPage.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 + optimizeImageSize: false + } + Loader { + id: profilePictureLoader + active: imageContainer.hasImage + asynchronous: true + anchors.fill: chatPictureThumbnail + source: chatInformationPage.isPrivateChat + ? "../components/chatInformationPage/ChatInformationProfilePictureList.qml" + : "../components/chatInformationPage/ChatInformationProfilePicture.qml" + } + } + // PageHeader changes the html base path: + property url emojiBase: "../js/emoji/" + leftMargin: imageContainer.minDimension + Theme.horizontalPageMargin + Theme.paddingMedium + title: chatInformationPage.chatInformation.title !== "" ? Emoji.emojify(chatInformationPage.chatInformation.title, Theme.fontSizeLarge, emojiBase) : qsTr("Unknown") + description: chatInformationPage.isPrivateChat ? ("@"+(chatInformationPage.privateChatUserInformation.username || chatInformationPage.chatPartnerGroupId)) : "" + } + + SilicaFlickable { + id: contentFlickable + contentHeight: groupInfoItem.height + tabViewLoader.height + clip: true + interactive: true//groupInfoItem.height > pageContent.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: chatInformationPage.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 ? chatInformationPage.groupFullInformation.invite_link : "" + width: parent.width - inviteLinkButton.width + } + IconButton { + id: inviteLinkButton + icon.source: "image://theme/icon-m-clipboard" + anchors.verticalCenter: inviteLinkItem.verticalCenter + onClicked: { + Clipboard.text = chatInformationPage.groupFullInformation.invite_link + infoNotification.show(qsTr("The Invite Link has been copied to the clipboard.")); + } + } + } + + 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: false + anchors { + left: parent.left + right: parent.right + top: groupInfoItem.bottom + } + sourceComponent: Component { + ChatInformationTabView { + id: tabView + height: tabView.count > 0 ? chatInformationPage.height - headerItem.height : 0 + } + } + } + } +} diff --git a/qml/components/chatInformationPage/ChatInformationTabItemBase.qml b/qml/components/chatInformationPage/ChatInformationTabItemBase.qml index a3472c4..0ebdea4 100644 --- a/qml/components/chatInformationPage/ChatInformationTabItemBase.qml +++ b/qml/components/chatInformationPage/ChatInformationTabItemBase.qml @@ -30,15 +30,12 @@ Item { property alias loadingVisible: loadingColumn.loadingVisible property string loadingText - property int tabIndex: tabItem.VisualItemModel.index - property bool active: tabItem.ListView.isCurrentItem + property int tabIndex: index + property bool active: index === tabView.currentIndex default property alias _data: contentItem.data - - width: parent.width - height: tabView.maxHeight//Math.max(contentItem.height, loadingColumn.height) - opacity: active ? 1.0 : 0.0 + opacity: active ? 1.0 : 0.2 Behavior on opacity { PropertyAnimation {duration: 300}} Column { diff --git a/qml/components/chatInformationPage/ChatInformationTabItemMembersGroups.qml b/qml/components/chatInformationPage/ChatInformationTabItemMembersGroups.qml index a1212d1..8e86e2d 100644 --- a/qml/components/chatInformationPage/ChatInformationTabItemMembersGroups.qml +++ b/qml/components/chatInformationPage/ChatInformationTabItemMembersGroups.qml @@ -27,8 +27,6 @@ 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) && !chatInformationPage.isChannel loadingVisible: loading && membersView.count === 0 @@ -37,7 +35,7 @@ ChatInformationTabItemBase { SilicaListView { id: membersView - model: isPrivateChat ? (chatPartnerCommonGroupsIds.length > 0 ? delegateModel : null) : chatInformationPage.membersList + model: chatInformationPage.isPrivateChat ? (chatPartnerCommonGroupsIds.length > 0 ? delegateModel : null) : pageContent.membersList clip: true height: tabBase.height width: tabBase.width @@ -46,9 +44,9 @@ ChatInformationTabItemBase { function handleScrollIntoView(force){ if(!tabBase.loading && !dragging && !quickScrollAnimating ) { if(!atYBeginning) { - chatInformationPage.scrollDown() + pageContent.scrollDown() } else { - chatInformationPage.scrollUp(force); + pageContent.scrollUp(force); } } } @@ -59,8 +57,9 @@ ChatInformationTabItemBase { handleScrollIntoView() } onAtYEndChanged: { - if(tabBase.active && !tabBase.loading && chatInformationPage.isSuperGroup && (groupInformation.member_count > membersView.count) && membersView.atYEnd) { + if(tabBase.active && !tabBase.loading && chatInformationPage.isSuperGroup && (chatInformationPage.groupInformation.member_count > membersView.count) && membersView.atYEnd) { tabBase.loading = true; + console.log("LOAD MEMBERS BECAUSE ATYEND") fetchMoreMembersTimer.start() } } @@ -78,7 +77,7 @@ ChatInformationTabItemBase { } width: parent.width - // chat title isPrivateChat ? () : + // chat title primaryText.text: Emoji.emojify(Functions.getUserName(user), primaryText.font.pixelSize, "../js/emoji/") // last user prologSecondaryText.text: "@"+(user.username !== "" ? user.username : user_id) + (user_id === chatInformationPage.myUserId ? " " + qsTr("You") : "") @@ -100,7 +99,7 @@ ChatInformationTabItemBase { } footer: Component { Item { - property bool active: tabBase.active && chatInformationPage.isSuperGroup && (groupInformation.member_count > membersView.count) + property bool active: tabBase.active && chatInformationPage.isSuperGroup && (chatInformationPage.groupInformation.member_count > membersView.count) width: tabBase.width height: active ? Theme.itemSizeLarge : Theme.paddingMedium @@ -174,9 +173,9 @@ ChatInformationTabItemBase { interval: 600 property int fetchLimit: 50 onTriggered: { - if(isSuperGroup && !isChannel) { + if(chatInformationPage.isSuperGroup && !chatInformationPage.isChannel && (chatInformationPage.groupInformation.member_count > membersView.count)) { // tabBase.loading = true - tdLibWrapper.getSupergroupMembers(chatInformationPage.chatPartnerGroupId, fetchLimit, membersList.count); + tdLibWrapper.getSupergroupMembers(chatInformationPage.chatPartnerGroupId, fetchLimit, pageContent.membersList.count); fetchLimit = 200 interval = 400 } @@ -187,20 +186,20 @@ ChatInformationTabItemBase { target: tdLibWrapper onChatMembersReceived: { - if (isSuperGroup && chatInformationPage.chatPartnerGroupId === extra) { - if(members && members.length > 0) { + if (chatInformationPage.isSuperGroup && chatInformationPage.chatPartnerGroupId === extra) { + if(members && members.length > 0 && chatInformationPage.groupInformation.member_count > membersView.count) { 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); + pageContent.membersList.append(memberData); } - groupInformation.member_count = totalMembers + chatInformationPage.groupInformation.member_count = totalMembers updateGroupStatusText(); - if(membersList.count < totalMembers) { +// if(pageContent.membersList.count < totalMembers) { // fetchMoreMembersTimer.start() - } +// } } // if we set it directly, the views start scrolling loadedTimer.start(); @@ -224,9 +223,9 @@ ChatInformationTabItemBase { } Component.onCompleted: { - if(isPrivateChat) { + if(chatInformationPage.isPrivateChat) { tdLibWrapper.getGroupsInCommon(chatInformationPage.chatPartnerGroupId, 200, 0); // we only use the first 200 - } else if(isSuperGroup) { + } else if(chatInformationPage.isSuperGroup) { fetchMoreMembersTimer.start(); } } diff --git a/qml/components/chatInformationPage/ChatInformationTabItemSettings.qml b/qml/components/chatInformationPage/ChatInformationTabItemSettings.qml index 9b189ba..30315a1 100644 --- a/qml/components/chatInformationPage/ChatInformationTabItemSettings.qml +++ b/qml/components/chatInformationPage/ChatInformationTabItemSettings.qml @@ -27,8 +27,8 @@ import "../../js/functions.js" as Functions ChatInformationTabItemBase { id: tabBase - title: qsTr("Settings", "Button: Chat Settings") - image: "image://theme/icon-m-developer-mode" +// title: qsTr("Settings", "Button: Chat Settings") +// image: "image://theme/icon-m-developer-mode" SilicaFlickable { height: tabBase.height diff --git a/qml/components/chatInformationPage/ChatInformationTabView.qml b/qml/components/chatInformationPage/ChatInformationTabView.qml index e399401..e4779fe 100644 --- a/qml/components/chatInformationPage/ChatInformationTabView.qml +++ b/qml/components/chatInformationPage/ChatInformationTabView.qml @@ -54,22 +54,21 @@ Item { width: parent.width columns: tabView.count Repeater { - model: tabView.count + model: tabModel delegate: BackgroundItem { id: headerItem - property bool loaded: tabItem.image !== "" && tabItem.title !== "" + property bool loaded: image !== "" && 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 + property bool itemIsActive: tabView.currentIndex === itemIndex Icon { id: headerIcon - source: headerItem.tabItem.image + source: image highlighted: headerItem.pressed || headerItem.itemIsActive anchors { top: parent.top @@ -77,7 +76,7 @@ Item { } } Label { - text: headerItem.tabItem.title + text: title width: parent.width horizontalAlignment: Text.AlignHCenter anchors.top: headerIcon.bottom @@ -85,7 +84,7 @@ Item { font.pixelSize: Theme.fontSizeTiny } onClicked: { - chatInformationPage.scrollDown() + pageContent.scrollDown() tabView.openTab(itemIndex) } } @@ -105,7 +104,6 @@ Item { highlightMoveDuration: 500 property int maxHeight: tabViewItem.height - tabViewHeader.height - anchors { top: tabViewHeader.bottom left: parent.left @@ -116,51 +114,33 @@ Item { function openTab(index) { currentIndex = index; } - model: VisualItemModel { + model: ListModel { id: tabModel } - } - Component { - id: membersGroupComponent - ChatInformationTabItemMembersGroups{ + delegate: Loader { width: tabView.width + height: tabView.maxHeight + asynchronous: true + source: Qt.resolvedUrl(tab+".qml") } } - Component { - id: settingsComponent - ChatInformationTabItemSettings { - width: tabView.width - } - } - Component { - id: debugComponent - ChatInformationTabItemDebug { - width: tabView.width - } - } - property var tabItems: { - var items = []; + Component.onCompleted: { if(!(isPrivateChat && chatPartnerGroupId === myUserId.toString())) { - items.push(membersGroupComponent); + tabModel.append({ + tab:"ChatInformationTabItemMembersGroups", + title: chatInformationPage.isPrivateChat ? qsTr("Groups", "Button: groups in common (short)") : qsTr("Members", "Button: Group Members"), + image: "image://theme/icon-m-people" + }); } if(!isPrivateChat && (groupInformation.status.can_restrict_members || groupInformation.status["@type"] === "chatMemberStatusCreator")) { - items.push(settingsComponent); + tabModel.append({ + tab:"ChatInformationTabItemSettings", + title: qsTr("Settings", "Button: Chat Settings"), + image: "image://theme/icon-m-developer-mode" + }); } -// items.push(debugComponent); +// tabModel.append({tab:"ChatInformationTabItemDebug"}); - 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/pages/ChatInformationPage.qml b/qml/pages/ChatInformationPage.qml index cd1f060..0a1ff0c 100644 --- a/qml/pages/ChatInformationPage.qml +++ b/qml/pages/ChatInformationPage.qml @@ -1,3 +1,21 @@ +/* + Copyright (C) 2020 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Fernschreiber is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fernschreiber. If not, see . +*/ import QtQuick 2.6 import Sailfish.Silica 1.0 import "../components" @@ -36,427 +54,27 @@ Page { property var groupInformation: ({}); property var groupFullInformation: ({}); - property alias membersList: membersList +// 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); + onStatusChanged: { + switch(status) { + case PageStatus.Activating: + console.log("activating Loader") + mainContentLoader.active = true 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; + case PageStatus.Active: 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 + Loader { + id: mainContentLoader + active: false + asynchronous: true anchors.fill: parent - - PullDownMenu { - MenuItem { - visible: (chatPage.isSuperGroup || chatPage.isBasicGroup) && groupInformation && groupInformation.status["@type"] !== "chatMemberStatusBanned" - text: userIsMember ? qsTr("Leave Chat") : qsTr("Join Chat") - onClicked: { - // ensure it's done even if the page is closed: - if (userIsMember) { - 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))) - } else { - tdLibWrapper.joinChat(chatInformation.id); - } - - - } - } - MenuItem { - visible: userIsMember - onClicked: { - var newNotificationSettings = chatInformation.notification_settings; - if (newNotificationSettings.mute_for > 0) { - newNotificationSettings.mute_for = 0; - } else { - newNotificationSettings.mute_for = 6666666; - } - newNotificationSettings.use_default_mute_for = false; - 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 - optimizeImageSize: false - } - Loader { - id: profilePictureLoader - active: imageContainer.hasImage - asynchronous: true - anchors.fill: chatPictureThumbnail - source: chatInformationPage.isPrivateChat - ? "../components/chatInformationPage/ChatInformationProfilePictureList.qml" - : "../components/chatInformationPage/ChatInformationProfilePicture.qml" - } - } - // PageHeader changes the html base path: - property url emojiBase: "../js/emoji/" - leftMargin: imageContainer.minDimension + Theme.horizontalPageMargin + Theme.paddingMedium - title: chatInformation.title !== "" ? Emoji.emojify(chatInformation.title, Theme.fontSizeLarge, emojiBase) : 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: { - Clipboard.text = groupFullInformation.invite_link - infoNotification.show(qsTr("The Invite Link has been copied to the clipboard.")); - } - } - } - - 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)); - } - } + source: Qt.resolvedUrl("../components/chatInformationPage/ChatInformationPageContent.qml"); } } diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml index b5d89d1..a6afd7f 100644 --- a/qml/pages/ChatPage.qml +++ b/qml/pages/ChatPage.qml @@ -298,6 +298,8 @@ Page { case PageStatus.Active: if (!chatPage.isInitialized) { chatModel.initialize(chatInformation); + + pageStack.pushAttached(Qt.resolvedUrl("../pages/ChatInformationPage.qml"), { "chatInformation" : chatInformation, "privateChatUserInformation": chatPartnerInformation, "groupInformation": chatGroupInformation, "chatOnlineMemberCount": chatOnlineMemberCount}); chatPage.isInitialized = true; } break; @@ -516,7 +518,7 @@ Page { if(chatPage.state === "selectMessages") { chatPage.selectedMessages = []; } else { - pageStack.push(Qt.resolvedUrl("../pages/ChatInformationPage.qml"), { "chatInformation" : chatInformation, "privateChatUserInformation": chatPartnerInformation, "groupInformation": chatGroupInformation, "chatOnlineMemberCount": chatOnlineMemberCount}); + pageStack.navigateForward(); } } } diff --git a/translations/harbour-fernschreiber-de.ts b/translations/harbour-fernschreiber-de.ts index 19b9bff..413c482 100644 --- a/translations/harbour-fernschreiber-de.ts +++ b/translations/harbour-fernschreiber-de.ts @@ -96,74 +96,74 @@ - ChatInformationPage - - Unmute Chat - Stummschaltung des Chats aufheben - - - Mute Chat - Chat stummschalten - - - Unknown - Unbekannt - - - The Invite Link has been copied to the clipboard. - Der Einladungslink wurde in die Zwischenablage kopiert. - + ChatInformationPageContent %1 members, %2 online - %1 Mitglieder, %2 online + %1 Mitglieder, %2 online %1 subscribers - %1 Abonnenten + %1 Abonnenten %1 members - %1 Mitglieder + %1 Mitglieder + + + Leave Chat + Chat verlassen + + + Join Chat + Chat beitreten Leaving chat - Verlasse Gruppe + Verlasse Chat - Info - group or user infotext header - Info + Unmute Chat + Stummschaltung des Chats aufheben - Phone Number - user phone number header - Telefonnummer + Mute Chat + Chat stummschalten - Invite Link - header - Einladungslink - - - There is no information text available, yet. - Es gibt noch keinen Informationstext. + Unknown + Unbekannt Chat Title group title header - Chattitel + Chattitel Enter 1-128 characters - Geben Sie 1-128 Zeichen ein + Geben Sie 1-128 Zeichen ein - Leave Chat - Chat verlassen + There is no information text available, yet. + Es gibt noch keinen Informationstext. - Join Chat - Chat beitreten + Info + group or user infotext header + Info + + + Phone Number + user phone number header + Telefonnummer + + + Invite Link + header + Einladungslink + + + The Invite Link has been copied to the clipboard. + Der Einladungslink wurde in die Zwischenablage kopiert. @@ -181,16 +181,6 @@ Unknown Unbekannt - - Groups - Button: groups in common (short) - Gruppen - - - Members - Button: Group Members - Mitglieder - Loading group members… Lade Gruppenmitglieder… @@ -209,11 +199,21 @@ - ChatInformationTabItemSettings + ChatInformationTabView + + Groups + Button: groups in common (short) + Gruppen + + + Members + Button: Group Members + Mitglieder + Settings Button: Chat Settings - Einstellungen + Einstellungen diff --git a/translations/harbour-fernschreiber-en.ts b/translations/harbour-fernschreiber-en.ts index 6db6a80..f99c38d 100644 --- a/translations/harbour-fernschreiber-en.ts +++ b/translations/harbour-fernschreiber-en.ts @@ -96,74 +96,74 @@ - ChatInformationPage - - Unmute Chat - Unmute Chat - - - Mute Chat - Mute Chat - - - Unknown - Unknown - - - The Invite Link has been copied to the clipboard. - The Invite Link has been copied to the clipboard. - + ChatInformationPageContent %1 members, %2 online - %1 members, %2 online + %1 members, %2 online %1 subscribers - %1 subscribers + %1 subscribers %1 members - %1 members + %1 members + + + Leave Chat + Leave Chat + + + Join Chat + Join Chat Leaving chat - Leaving chat + Leaving chat - Info - group or user infotext header - Info + Unmute Chat + Unmute Chat - Phone Number - user phone number header - Phone Number + Mute Chat + Mute Chat - Invite Link - header - Invite Link - - - There is no information text available, yet. - There is no information text available, yet. + Unknown + Unknown Chat Title group title header - Chat Title + Chat Title Enter 1-128 characters - Enter 1-128 characters + Enter 1-128 characters - Leave Chat - Leave Chat + There is no information text available, yet. + There is no information text available, yet. - Join Chat - Join Chat + Info + group or user infotext header + Info + + + Phone Number + user phone number header + Phone Number + + + Invite Link + header + Invite Link + + + The Invite Link has been copied to the clipboard. + The Invite Link has been copied to the clipboard. @@ -177,16 +177,6 @@ Unknown Unknown - - Groups - Button: groups in common (short) - Groups - - - Members - Button: Group Members - Members - Loading group members… Loading group members… @@ -209,11 +199,21 @@ - ChatInformationTabItemSettings + ChatInformationTabView + + Groups + Button: groups in common (short) + Groups + + + Members + Button: Group Members + Members + Settings Button: Chat Settings - Settings + Settings diff --git a/translations/harbour-fernschreiber-es.ts b/translations/harbour-fernschreiber-es.ts index 3139783..b8e0b40 100644 --- a/translations/harbour-fernschreiber-es.ts +++ b/translations/harbour-fernschreiber-es.ts @@ -96,74 +96,74 @@ - ChatInformationPage - - Unmute Chat - habilitar notificación - - - Mute Chat - deshabilitar notificación - - - Unknown - Desconocido - - - The Invite Link has been copied to the clipboard. - El enlace de invitación se ha copiado en el portapapeles. - + ChatInformationPageContent %1 members, %2 online - %1 miembros, %2 en línea + %1 miembros, %2 en línea %1 subscribers - %1 suscriptores + %1 suscriptores %1 members - %1 miembros + %1 miembros + + + Leave Chat + Salir del grupo + + + Join Chat + Unirse al grupo Leaving chat - Saliendo del grupo + Saliendo del grupo - Info - group or user infotext header - Información + Unmute Chat + habilitar notificación - Phone Number - user phone number header - Número de teléfono + Mute Chat + deshabilitar notificación - Invite Link - header - Enlace de invitación - - - There is no information text available, yet. - Aún no hay texto de información disponible. + Unknown + Chat Title group title header - Título del grupo + Título del grupo Enter 1-128 characters - Marcar los caracteres 1-128 + Marcar los caracteres 1-128 - Leave Chat - Salir del grupo + There is no information text available, yet. + Aún no hay texto de información disponible. - Join Chat - Unirse al grupo + Info + group or user infotext header + Información + + + Phone Number + user phone number header + Número de teléfono + + + Invite Link + header + Enlace de invitación + + + The Invite Link has been copied to the clipboard. + El enlace de invitación se ha copiado en el portapapeles. @@ -177,16 +177,6 @@ Unknown Desconocido - - Groups - Button: groups in common (short) - Grupos - - - Members - Button: Group Members - Miembros - Loading group members… Cargando miembros del grupo… @@ -209,11 +199,21 @@ - ChatInformationTabItemSettings + ChatInformationTabView + + Groups + Button: groups in common (short) + Grupos + + + Members + Button: Group Members + Miembros + Settings Button: Chat Settings - Ajustes + Ajustes diff --git a/translations/harbour-fernschreiber-fi.ts b/translations/harbour-fernschreiber-fi.ts index 88eec74..fa067be 100644 --- a/translations/harbour-fernschreiber-fi.ts +++ b/translations/harbour-fernschreiber-fi.ts @@ -96,74 +96,74 @@ - ChatInformationPage - - Unmute Chat - Poista keskustelun vaimennus - - - Mute Chat - Vaimenna keskustelu - - - Unknown - Tuntematon - - - The Invite Link has been copied to the clipboard. - Kutsulinkki on kopioitu leikepöydälle. - + ChatInformationPageContent %1 members, %2 online - %1 jäsentä, %2 paikalla + %1 jäsentä, %2 paikalla %1 subscribers - %1 tilaajaa + %1 tilaajaa %1 members - %1 jäsentä + %1 jäsentä + + + Leave Chat + Poistu keskustelusta + + + Join Chat + Liity keskusteluun Leaving chat - Poistutaan keskustelusta + Poistutaan keskustelusta - Info - group or user infotext header - Tietoa + Unmute Chat + Poista keskustelun vaimennus - Phone Number - user phone number header - Puhelinnumero + Mute Chat + Vaimenna keskustelu - Invite Link - header - Kutsulinkki - - - There is no information text available, yet. - Tietoa ei ole vielä saatavilla. + Unknown + Tuntematon Chat Title group title header - Keskustelun otsikko + Keskustelun otsikko Enter 1-128 characters - Syötä 1-128 merkkiä + Syötä 1-128 merkkiä - Leave Chat - Poistu keskustelusta + There is no information text available, yet. + Tietoa ei ole vielä saatavilla. - Join Chat - Liity keskusteluun + Info + group or user infotext header + Tietoa + + + Phone Number + user phone number header + Puhelinnumero + + + Invite Link + header + Kutsulinkki + + + The Invite Link has been copied to the clipboard. + Kutsulinkki on kopioitu leikepöydälle. @@ -177,16 +177,6 @@ Unknown Tuntematon - - Groups - Button: groups in common (short) - Ryhmät - - - Members - Button: Group Members - Jäsenet - Loading group members… Ladataan ryhmän jäseniä... @@ -209,11 +199,21 @@ - ChatInformationTabItemSettings + ChatInformationTabView + + Groups + Button: groups in common (short) + Ryhmät + + + Members + Button: Group Members + Jäsenet + Settings Button: Chat Settings - Asetukset + Asetukset diff --git a/translations/harbour-fernschreiber-hu.ts b/translations/harbour-fernschreiber-hu.ts index cad2d5f..be6c998 100644 --- a/translations/harbour-fernschreiber-hu.ts +++ b/translations/harbour-fernschreiber-hu.ts @@ -96,23 +96,7 @@ - ChatInformationPage - - Unmute Chat - Csevegés némítás feloldása - - - Mute Chat - Csevegés némítása - - - Unknown - Ismeretlen - - - The Invite Link has been copied to the clipboard. - - + ChatInformationPageContent %1 members, %2 online %1 tag, %2 online @@ -125,10 +109,43 @@ %1 members %1 tag + + Leave Chat + + + + Join Chat + + Leaving chat + + Unmute Chat + Csevegés némítás feloldása + + + Mute Chat + Csevegés némítása + + + Unknown + Ismeretlen + + + Chat Title + group title header + + + + Enter 1-128 characters + + + + There is no information text available, yet. + + Info group or user infotext header @@ -145,24 +162,7 @@ - There is no information text available, yet. - - - - Chat Title - group title header - - - - Enter 1-128 characters - - - - Leave Chat - - - - Join Chat + The Invite Link has been copied to the clipboard. @@ -177,16 +177,6 @@ Unknown Ismeretlen - - Groups - Button: groups in common (short) - - - - Members - Button: Group Members - - Loading group members… @@ -209,7 +199,17 @@ - ChatInformationTabItemSettings + ChatInformationTabView + + Groups + Button: groups in common (short) + + + + Members + Button: Group Members + + Settings Button: Chat Settings diff --git a/translations/harbour-fernschreiber-it.ts b/translations/harbour-fernschreiber-it.ts index 8ecedeb..64e6d4f 100644 --- a/translations/harbour-fernschreiber-it.ts +++ b/translations/harbour-fernschreiber-it.ts @@ -96,88 +96,78 @@ - ChatInformationPage - - Leaving chat - Lascia chat - - - Unmute Chat - Riattiva suoni chat - - - Mute Chat - Silenzia chat - - - Unknown - Sconosciuto - - - The Invite Link has been copied to the clipboard. - Il link d'invito è stato copiato nella clipboard. - + ChatInformationPageContent %1 members, %2 online - %1 membri, %2 online + %1 membri, %2 online %1 subscribers - %1 abbonati + %1 abbonati %1 members - %1 membri + %1 membri - Info - group or user infotext header - Info + Leave Chat + Lascia chat - Phone Number - user phone number header - Telefono + Join Chat + Entra nella chat - Invite Link - header - Link d'invito + Leaving chat + Lascia chat - There is no information text available, yet. - Attualmente non è disponibile nessuna informazione. + Unmute Chat + Riattiva suoni chat + + + Mute Chat + Silenzia chat + + + Unknown + Sconosciuto Chat Title group title header - Titolo chat + Titolo chat Enter 1-128 characters - Inserisci da 1 a 128 caratteri + Inserisci da 1 a 128 caratteri - Leave Chat - Lascia chat + There is no information text available, yet. + Attualmente non è disponibile nessuna informazione. - Join Chat - Entra nella chat + Info + group or user infotext header + Info + + + Phone Number + user phone number header + Telefono + + + Invite Link + header + Link d'invito + + + The Invite Link has been copied to the clipboard. + Il link d'invito è stato copiato nella clipboard. ChatInformationTabItemMembersGroups - - Groups - Button: groups in common (short) - Gruppi - - - Members - Button: Group Members - Membri - You Tu @@ -209,11 +199,21 @@ - ChatInformationTabItemSettings + ChatInformationTabView + + Groups + Button: groups in common (short) + Gruppi + + + Members + Button: Group Members + Membri + Settings Button: Chat Settings - Impostazioni + Impostazioni diff --git a/translations/harbour-fernschreiber-pl.ts b/translations/harbour-fernschreiber-pl.ts index 9a81239..9d34102 100644 --- a/translations/harbour-fernschreiber-pl.ts +++ b/translations/harbour-fernschreiber-pl.ts @@ -96,23 +96,7 @@ - ChatInformationPage - - Unmute Chat - Wyłącz wyciszenie czatu - - - Mute Chat - Wycisz czat - - - Unknown - Nieznany - - - The Invite Link has been copied to the clipboard. - - + ChatInformationPageContent %1 members, %2 online $1 członków, %2 online @@ -125,10 +109,43 @@ %1 members %1 czlonków + + Leave Chat + + + + Join Chat + + Leaving chat + + Unmute Chat + Wyłącz wyciszenie czatu + + + Mute Chat + Wycisz czat + + + Unknown + Nieznany + + + Chat Title + group title header + + + + Enter 1-128 characters + + + + There is no information text available, yet. + + Info group or user infotext header @@ -145,24 +162,7 @@ - There is no information text available, yet. - - - - Chat Title - group title header - - - - Enter 1-128 characters - - - - Leave Chat - - - - Join Chat + The Invite Link has been copied to the clipboard. @@ -177,16 +177,6 @@ Unknown Nieznany - - Groups - Button: groups in common (short) - - - - Members - Button: Group Members - - Loading group members… @@ -209,7 +199,17 @@ - ChatInformationTabItemSettings + ChatInformationTabView + + Groups + Button: groups in common (short) + + + + Members + Button: Group Members + + Settings Button: Chat Settings diff --git a/translations/harbour-fernschreiber-ru.ts b/translations/harbour-fernschreiber-ru.ts index 34fa4c2..2872909 100644 --- a/translations/harbour-fernschreiber-ru.ts +++ b/translations/harbour-fernschreiber-ru.ts @@ -96,23 +96,7 @@ - ChatInformationPage - - Unmute Chat - Включить уведомления - - - Mute Chat - Выключить уведомления - - - Unknown - - - - The Invite Link has been copied to the clipboard. - Ссылка для приглашения скопирована в буффер обмена - + ChatInformationPageContent %1 members, %2 online %1 участников, %2 онлайн @@ -125,45 +109,61 @@ %1 members %1 участников + + Leave Chat + Выйти из чата + + + Join Chat + Зайти в чат + Leaving chat Выход из чата - Info - group or user infotext header - Информация + Unmute Chat + Включить уведомления - Phone Number - user phone number header - Номер телефона + Mute Chat + Выключить уведомления - Invite Link - header - Ссылка для приглашения - - - There is no information text available, yet. - Информация отсутствует + Unknown + Chat Title group title header - Заголовок чата + Заголовок чата Enter 1-128 characters - Введите 1-128 символов + Введите 1-128 символов - Leave Chat - Выйти из чата + There is no information text available, yet. + Информация отсутствует - Join Chat - Зайти в чат + Info + group or user infotext header + Информация + + + Phone Number + user phone number header + Номер телефона + + + Invite Link + header + Ссылка для приглашения + + + The Invite Link has been copied to the clipboard. + Ссылка для приглашения скопирована в буффер обмена @@ -177,16 +177,6 @@ Unknown нет информации - - Groups - Button: groups in common (short) - Группы - - - Members - Button: Group Members - Участники группы - Loading group members… Загрузка списка участников… @@ -209,11 +199,21 @@ - ChatInformationTabItemSettings + ChatInformationTabView + + Groups + Button: groups in common (short) + Группы + + + Members + Button: Group Members + Участники группы + Settings Button: Chat Settings - Настройки + Настройки diff --git a/translations/harbour-fernschreiber-sv.ts b/translations/harbour-fernschreiber-sv.ts index 0106fa2..8379e51 100644 --- a/translations/harbour-fernschreiber-sv.ts +++ b/translations/harbour-fernschreiber-sv.ts @@ -96,74 +96,74 @@ - ChatInformationPage - - Unmute Chat - Slå på chatten - - - Mute Chat - Stäng av chatten - - - Unknown - Okänd - - - The Invite Link has been copied to the clipboard. - Inbjudningslänken har kopierats till urklipp. - + ChatInformationPageContent %1 members, %2 online - %1 medlemmar, %2 inloggade + %1 medlem(mar), %2 inloggad(e) %1 subscribers - %1 prenumeranter + %1 prenumerant(er) %1 members - %1 medlemmar + %1 medlem(mar) + + + Leave Chat + Lämna chatten + + + Join Chat + Anslut till chatten Leaving chat - Lämnar chatten + Lämnar chatten - Info - group or user infotext header - Info + Unmute Chat + Slå på chatten - Phone Number - user phone number header - Telefonnummer + Mute Chat + Stäng av chatten - Invite Link - header - Inbjudningslänk - - - There is no information text available, yet. - Det finns ingen informationstext än. + Unknown + Okänd Chat Title group title header - Chattnamn + Chattnamn Enter 1-128 characters - Ange 1-128 tecken + Ange 1-128 tecken - Leave Chat - Lämna chatten + There is no information text available, yet. + Det finns ingen informationstext än. - Join Chat - Anslut till chatten + Info + group or user infotext header + Info + + + Phone Number + user phone number header + Telefonnummer + + + Invite Link + header + Inbjudningslänk + + + The Invite Link has been copied to the clipboard. + Inbjudningslänken har kopierats till urklipp. @@ -177,16 +177,6 @@ Unknown Okänd - - Groups - Button: groups in common (short) - Grupper - - - Members - Button: Group Members - Medlemmar - Loading group members… Läser in gruppmedlemmar... @@ -209,11 +199,21 @@ - ChatInformationTabItemSettings + ChatInformationTabView + + Groups + Button: groups in common (short) + Grupper + + + Members + Button: Group Members + Medlemmar + Settings Button: Chat Settings - Inställningar + Inställningar diff --git a/translations/harbour-fernschreiber-zh_CN.ts b/translations/harbour-fernschreiber-zh_CN.ts index f93749b..05c9911 100644 --- a/translations/harbour-fernschreiber-zh_CN.ts +++ b/translations/harbour-fernschreiber-zh_CN.ts @@ -96,74 +96,74 @@ - ChatInformationPage - - Unmute Chat - 取消对话静音 - - - Mute Chat - 静音对话 - - - Unknown - 未知 - - - The Invite Link has been copied to the clipboard. - 邀请链接已复制到剪切板 - + ChatInformationPageContent %1 members, %2 online - %1 位成员, %2 位在线 + %1 位成员, %2 位在线 %1 subscribers - %1 位订阅者 + %1 位订阅者 %1 members - %1 位成员 + %1 位成员 + + + Leave Chat + 离开对话 + + + Join Chat + 加入对话 Leaving chat - 正在离开对话 + 正在离开对话 - Info - group or user infotext header - 信息 + Unmute Chat + 取消对话静音 - Phone Number - user phone number header - 电话号码 + Mute Chat + - Invite Link - header - 邀请链接 - - - There is no information text available, yet. - 暂无信息 + Unknown + 未知 Chat Title group title header - 对话标题 + 对话标题 Enter 1-128 characters - 输入 1-128 个字符 + 输入 1-128 个字符 - Leave Chat - 离开对话 + There is no information text available, yet. + 暂无信息 - Join Chat - 加入对话 + Info + group or user infotext header + 信息 + + + Phone Number + user phone number header + 电话号码 + + + Invite Link + header + 邀请链接 + + + The Invite Link has been copied to the clipboard. + 邀请链接已复制到剪切板 @@ -177,16 +177,6 @@ Unknown 未知 - - Groups - Button: groups in common (short) - 群组 - - - Members - Button: Group Members - 成员 - Loading group members… 正在加载群组成员… @@ -209,11 +199,21 @@ - ChatInformationTabItemSettings + ChatInformationTabView + + Groups + Button: groups in common (short) + 群组 + + + Members + Button: Group Members + 成员 + Settings Button: Chat Settings - 设置 + 设置 diff --git a/translations/harbour-fernschreiber.ts b/translations/harbour-fernschreiber.ts index 06f8cc7..4996468 100644 --- a/translations/harbour-fernschreiber.ts +++ b/translations/harbour-fernschreiber.ts @@ -96,23 +96,7 @@ - ChatInformationPage - - Unmute Chat - - - - Mute Chat - - - - Unknown - - - - The Invite Link has been copied to the clipboard. - - + ChatInformationPageContent %1 members, %2 online @@ -125,10 +109,43 @@ %1 members + + Leave Chat + + + + Join Chat + + Leaving chat + + Unmute Chat + + + + Mute Chat + + + + Unknown + + + + Chat Title + group title header + + + + Enter 1-128 characters + + + + There is no information text available, yet. + + Info group or user infotext header @@ -145,24 +162,7 @@ - There is no information text available, yet. - - - - Chat Title - group title header - - - - Enter 1-128 characters - - - - Leave Chat - - - - Join Chat + The Invite Link has been copied to the clipboard. @@ -177,16 +177,6 @@ Unknown - - Groups - Button: groups in common (short) - - - - Members - Button: Group Members - - Loading group members… @@ -209,7 +199,17 @@ - ChatInformationTabItemSettings + ChatInformationTabView + + Groups + Button: groups in common (short) + + + + Members + Button: Group Members + + Settings Button: Chat Settings