2020-11-20 20:30:33 +03:00
|
|
|
/*
|
|
|
|
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 <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
import QtQuick 2.6
|
|
|
|
import Sailfish.Silica 1.0
|
|
|
|
import "../components"
|
|
|
|
import "../js/twemoji.js" as Emoji
|
|
|
|
import "../js/functions.js" as Functions
|
2021-02-19 00:48:01 +03:00
|
|
|
import "../js/debug.js" as Debug
|
2020-11-20 20:30:33 +03:00
|
|
|
|
|
|
|
Page {
|
|
|
|
id: newChatPage
|
|
|
|
allowedOrientations: Orientation.All
|
|
|
|
|
|
|
|
property bool isLoading: true;
|
2021-02-19 00:48:01 +03:00
|
|
|
property bool syncSupported: false;
|
2021-08-31 13:15:05 +03:00
|
|
|
property bool nemoSync: false;
|
2020-11-20 20:30:33 +03:00
|
|
|
|
2020-11-27 00:18:51 +03:00
|
|
|
function resetFocus() {
|
|
|
|
contactsSearchField.focus = false;
|
|
|
|
newChatPage.focus = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
function reloadContacts() {
|
|
|
|
contactsModel.hydrateContacts();
|
2020-11-28 21:11:51 +03:00
|
|
|
contactsListView.model = contactsProxyModel;
|
2020-11-27 00:18:51 +03:00
|
|
|
newChatPage.isLoading = false;
|
|
|
|
}
|
|
|
|
|
2020-11-21 01:00:50 +03:00
|
|
|
onStatusChanged: {
|
|
|
|
if (status === PageStatus.Active) {
|
2020-11-27 00:18:51 +03:00
|
|
|
reloadContacts();
|
2020-11-21 01:00:50 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-27 00:18:51 +03:00
|
|
|
Connections {
|
|
|
|
target: tdLibWrapper
|
|
|
|
onContactsImported: {
|
|
|
|
reloadContacts();
|
|
|
|
appNotification.show(qsTr("Contacts successfully synchronized with Telegram."));
|
|
|
|
}
|
2020-11-24 19:28:41 +03:00
|
|
|
}
|
|
|
|
|
2021-02-19 00:48:01 +03:00
|
|
|
Component.onCompleted: {
|
|
|
|
var sailfishOSVersion = fernschreiberUtils.getSailfishOSVersion().split(".");
|
2021-09-01 01:37:15 +03:00
|
|
|
// With Sailfish OS 4 we can't get up-to-date contacts with the standard database anymore. We might need to enter Sailjail eventually...
|
|
|
|
// Details see https://forum.sailfishos.org/t/4-0-1-45-non-jailed-contacts-sqlite-database-no-longer-updated/4724
|
|
|
|
// We try it with the inofficial Nemo Contact API via a loader...
|
2021-02-19 00:48:01 +03:00
|
|
|
if (parseInt(sailfishOSVersion[0]) < 4) {
|
|
|
|
Debug.log("Sailfish OS version 3.x - contact sync should still be possible...")
|
|
|
|
newChatPage.syncSupported = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-01 01:37:15 +03:00
|
|
|
Connections {
|
|
|
|
target: contactSyncLoader.item
|
|
|
|
onSyncError: {
|
|
|
|
newChatPage.isLoading = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Loader {
|
|
|
|
id: contactSyncLoader
|
|
|
|
source: "../components/ContactSync.qml"
|
|
|
|
active: true
|
|
|
|
onLoaded: {
|
|
|
|
newChatPage.nemoSync = true;
|
|
|
|
}
|
2021-08-31 13:15:05 +03:00
|
|
|
}
|
|
|
|
|
2020-11-20 20:30:33 +03:00
|
|
|
SilicaFlickable {
|
|
|
|
id: newChatContainer
|
|
|
|
contentHeight: newChatPage.height
|
|
|
|
anchors.fill: parent
|
|
|
|
|
2020-11-27 00:18:51 +03:00
|
|
|
PullDownMenu {
|
2021-09-01 01:37:15 +03:00
|
|
|
enabled: newChatPage.syncSupported || newChatPage.nemoSync
|
2020-11-27 00:18:51 +03:00
|
|
|
MenuItem {
|
|
|
|
onClicked: {
|
|
|
|
newChatPage.isLoading = true;
|
2021-08-31 13:15:05 +03:00
|
|
|
if (newChatPage.nemoSync) {
|
2021-09-01 01:37:15 +03:00
|
|
|
contactSyncLoader.item.synchronize();
|
2021-08-31 13:15:05 +03:00
|
|
|
}
|
|
|
|
if (newChatPage.syncSupported) {
|
|
|
|
if (!contactsModel.synchronizeContacts()) {
|
|
|
|
reloadContacts();
|
|
|
|
appNotification.show(qsTr("Could not synchronize your contacts with Telegram."));
|
|
|
|
}
|
2020-11-28 21:11:51 +03:00
|
|
|
}
|
|
|
|
// Success message is not fired before TDLib returned "Contacts imported" (see above)
|
2020-11-27 00:18:51 +03:00
|
|
|
}
|
|
|
|
text: qsTr("Synchronize Contacts with Telegram")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-20 20:30:33 +03:00
|
|
|
Column {
|
|
|
|
id: newChatPageColumn
|
|
|
|
width: newChatPage.width
|
|
|
|
height: newChatPage.height
|
|
|
|
|
|
|
|
PageHeader {
|
|
|
|
id: newChatPageHeader
|
|
|
|
title: qsTr("Your Contacts")
|
|
|
|
}
|
|
|
|
|
2020-11-22 00:13:37 +03:00
|
|
|
Item {
|
|
|
|
id: contactsItem
|
|
|
|
|
2020-11-20 20:30:33 +03:00
|
|
|
width: newChatPageColumn.width
|
2020-11-22 00:13:37 +03:00
|
|
|
height: newChatPageColumn.height - newChatPageHeader.height
|
2020-11-20 20:30:33 +03:00
|
|
|
|
2020-11-24 19:28:41 +03:00
|
|
|
Column {
|
|
|
|
visible: !newChatPage.isLoading
|
2020-11-22 00:13:37 +03:00
|
|
|
width: parent.width
|
|
|
|
height: parent.height
|
2020-11-24 19:28:41 +03:00
|
|
|
SearchField {
|
|
|
|
id: contactsSearchField
|
|
|
|
width: parent.width
|
2020-11-26 02:25:15 +03:00
|
|
|
placeholderText: qsTr("Search a contact...")
|
2020-11-24 19:28:41 +03:00
|
|
|
active: !newChatPage.isLoading
|
2020-11-28 21:11:51 +03:00
|
|
|
|
|
|
|
onTextChanged: {
|
|
|
|
contactsProxyModel.setFilterWildcard("*" + text + "*");
|
|
|
|
}
|
|
|
|
|
2020-11-24 19:28:41 +03:00
|
|
|
EnterKey.iconSource: "image://theme/icon-m-enter-close"
|
|
|
|
EnterKey.onClicked: {
|
|
|
|
resetFocus();
|
|
|
|
}
|
2020-11-20 20:30:33 +03:00
|
|
|
|
|
|
|
}
|
2020-11-22 00:13:37 +03:00
|
|
|
|
2020-11-24 19:28:41 +03:00
|
|
|
SilicaListView {
|
|
|
|
id: contactsListView
|
|
|
|
clip: true
|
2020-11-22 00:13:37 +03:00
|
|
|
width: parent.width
|
2020-11-24 19:28:41 +03:00
|
|
|
height: parent.height - contactsSearchField.height
|
|
|
|
visible: !newChatPage.isLoading
|
|
|
|
opacity: visible ? 1 : 0
|
|
|
|
Behavior on opacity { FadeAnimation {} }
|
2020-11-22 00:13:37 +03:00
|
|
|
|
2020-11-24 19:28:41 +03:00
|
|
|
signal newChatInitiated ( int currentIndex )
|
2020-11-22 00:13:37 +03:00
|
|
|
|
2020-11-24 19:28:41 +03:00
|
|
|
ViewPlaceholder {
|
|
|
|
y: Theme.paddingLarge
|
|
|
|
enabled: contactsListView.count === 0
|
|
|
|
text: qsTr("You don't have any contacts.")
|
|
|
|
}
|
2020-11-22 00:13:37 +03:00
|
|
|
|
2020-11-24 19:28:41 +03:00
|
|
|
delegate: Item {
|
|
|
|
id: newChatListItem
|
2020-11-22 00:13:37 +03:00
|
|
|
width: parent.width
|
2020-11-24 19:28:41 +03:00
|
|
|
height: contactListItem.height
|
2020-11-22 00:13:37 +03:00
|
|
|
|
2020-11-24 19:28:41 +03:00
|
|
|
PhotoTextsListItem {
|
|
|
|
id: contactListItem
|
2020-11-22 00:13:37 +03:00
|
|
|
|
2020-11-24 19:28:41 +03:00
|
|
|
opacity: visible ? 1 : 0
|
|
|
|
Behavior on opacity { FadeAnimation {} }
|
2020-11-22 00:13:37 +03:00
|
|
|
|
2020-11-24 19:28:41 +03:00
|
|
|
pictureThumbnail {
|
2020-11-28 21:11:51 +03:00
|
|
|
photoData: typeof photo_small !== "undefined" ? photo_small : {}
|
2020-11-22 00:13:37 +03:00
|
|
|
}
|
2020-11-24 19:28:41 +03:00
|
|
|
width: parent.width
|
2020-11-22 00:13:37 +03:00
|
|
|
|
2020-11-28 21:11:51 +03:00
|
|
|
primaryText.text: Emoji.emojify(title, primaryText.font.pixelSize, "../js/emoji/")
|
|
|
|
prologSecondaryText.text: "@" + ( username !== "" ? username : user_id )
|
2020-11-24 19:28:41 +03:00
|
|
|
tertiaryText {
|
|
|
|
maximumLineCount: 1
|
2020-11-28 21:11:51 +03:00
|
|
|
text: Functions.getChatPartnerStatusText(user_status, user_last_online);
|
2020-11-24 19:28:41 +03:00
|
|
|
}
|
2020-11-22 00:13:37 +03:00
|
|
|
|
2020-11-24 19:28:41 +03:00
|
|
|
onClicked: {
|
|
|
|
contactsListView.newChatInitiated(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
Connections {
|
|
|
|
target: contactsListView
|
|
|
|
|
|
|
|
onNewChatInitiated: {
|
|
|
|
if (index === currentIndex) {
|
|
|
|
contactListItem.visible = false;
|
|
|
|
} else {
|
|
|
|
contactListItem.visible = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-11-22 00:13:37 +03:00
|
|
|
|
2020-11-24 19:28:41 +03:00
|
|
|
Connections {
|
|
|
|
target: contactsSearchField
|
|
|
|
onFocusChanged: {
|
|
|
|
if (contactsSearchField.focus) {
|
|
|
|
contactListItem.visible = true;
|
|
|
|
}
|
|
|
|
}
|
2020-11-22 00:13:37 +03:00
|
|
|
}
|
2020-11-24 19:28:41 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
Column {
|
|
|
|
id: selectChatTypeColumn
|
|
|
|
visible: !contactListItem.visible
|
|
|
|
opacity: visible ? 1 : 0
|
|
|
|
Behavior on opacity { FadeAnimation {} }
|
|
|
|
width: parent.width
|
|
|
|
height: contactListItem.height
|
2020-11-22 00:13:37 +03:00
|
|
|
|
|
|
|
Item {
|
2020-11-24 19:28:41 +03:00
|
|
|
width: parent.width
|
|
|
|
height: parent.height - chatTypeSeparator.height
|
2020-11-22 00:13:37 +03:00
|
|
|
|
|
|
|
Rectangle {
|
|
|
|
anchors.fill: parent
|
2020-11-28 21:11:51 +03:00
|
|
|
opacity: Theme.opacityLow
|
2020-11-24 19:28:41 +03:00
|
|
|
color: Theme.overlayBackgroundColor
|
2020-11-22 00:13:37 +03:00
|
|
|
}
|
|
|
|
|
2020-11-24 19:28:41 +03:00
|
|
|
Item {
|
|
|
|
id: privateChatItem
|
|
|
|
height: parent.height
|
2020-11-28 21:11:51 +03:00
|
|
|
width: parent.width / 2
|
2020-11-24 19:28:41 +03:00
|
|
|
|
|
|
|
Rectangle {
|
|
|
|
id: privateChatHighlightBackground
|
|
|
|
anchors.fill: parent
|
|
|
|
color: Theme.highlightBackgroundColor
|
2020-11-28 21:11:51 +03:00
|
|
|
opacity: Theme.opacityHigh
|
2020-11-24 19:28:41 +03:00
|
|
|
visible: false
|
|
|
|
}
|
2020-11-22 00:13:37 +03:00
|
|
|
|
2020-11-24 19:28:41 +03:00
|
|
|
Row {
|
|
|
|
width: parent.width
|
|
|
|
height: parent.height - ( 2 * Theme.paddingSmall )
|
2020-11-22 00:13:37 +03:00
|
|
|
anchors.verticalCenter: parent.verticalCenter
|
2020-11-24 19:28:41 +03:00
|
|
|
|
|
|
|
IconButton {
|
|
|
|
id: privateChatButton
|
|
|
|
width: Theme.itemSizeLarge
|
|
|
|
height: Theme.itemSizeLarge
|
|
|
|
icon.source: "image://theme/icon-m-chat"
|
|
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
|
|
onClicked: {
|
2021-01-10 04:06:41 +03:00
|
|
|
tdLibWrapper.createPrivateChat(display.id, "openDirectly");
|
2020-11-24 19:28:41 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Column {
|
|
|
|
height: parent.height
|
|
|
|
width: parent.width - privateChatButton.width - Theme.horizontalPageMargin
|
|
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
|
|
spacing: Theme.paddingSmall
|
|
|
|
Text {
|
|
|
|
id: privateChatHeader
|
|
|
|
width: parent.width
|
|
|
|
font.pixelSize: Theme.fontSizeMedium
|
|
|
|
font.weight: Font.ExtraBold
|
|
|
|
color: Theme.primaryColor
|
|
|
|
maximumLineCount: 1
|
|
|
|
elide: Text.ElideRight
|
|
|
|
textFormat: Text.StyledText
|
|
|
|
text: qsTr("Private Chat")
|
|
|
|
}
|
|
|
|
Text {
|
|
|
|
width: parent.width
|
|
|
|
height: parent.height - privateChatHeader.height - Theme.paddingSmall
|
|
|
|
font.pixelSize: Theme.fontSizeTiny
|
|
|
|
color: Theme.secondaryColor
|
|
|
|
wrapMode: Text.Wrap
|
|
|
|
elide: Text.ElideRight
|
|
|
|
textFormat: Text.StyledText
|
2020-11-25 02:23:38 +03:00
|
|
|
text: qsTr("Transport-encrypted, uses Telegram Cloud, sharable across devices")
|
2020-11-24 19:28:41 +03:00
|
|
|
}
|
2020-11-22 00:13:37 +03:00
|
|
|
}
|
2020-11-24 19:28:41 +03:00
|
|
|
|
2020-11-22 00:13:37 +03:00
|
|
|
}
|
|
|
|
|
2020-11-24 19:28:41 +03:00
|
|
|
MouseArea {
|
|
|
|
anchors.fill: parent
|
|
|
|
onClicked: {
|
2021-01-10 04:06:41 +03:00
|
|
|
tdLibWrapper.createPrivateChat(display.id, "openDirectly");
|
2020-11-22 00:13:37 +03:00
|
|
|
}
|
2020-11-24 19:28:41 +03:00
|
|
|
onPressed: {
|
|
|
|
privateChatHighlightBackground.visible = true;
|
|
|
|
}
|
|
|
|
onReleased: {
|
|
|
|
privateChatHighlightBackground.visible = false;
|
2020-11-22 00:13:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-24 19:28:41 +03:00
|
|
|
Item {
|
|
|
|
id: secretChatItem
|
|
|
|
height: parent.height
|
2020-11-28 21:11:51 +03:00
|
|
|
width: parent.width / 2
|
2020-11-24 19:28:41 +03:00
|
|
|
anchors.left: privateChatItem.right
|
|
|
|
anchors.top: parent.top
|
|
|
|
|
|
|
|
Rectangle {
|
|
|
|
id: secretChatHighlightBackground
|
|
|
|
anchors.fill: parent
|
|
|
|
color: Theme.highlightBackgroundColor
|
2020-11-28 21:11:51 +03:00
|
|
|
opacity: Theme.opacityHigh
|
2020-11-24 19:28:41 +03:00
|
|
|
visible: false
|
2020-11-22 00:13:37 +03:00
|
|
|
}
|
|
|
|
|
2020-11-24 19:28:41 +03:00
|
|
|
Row {
|
|
|
|
width: parent.width
|
|
|
|
height: parent.height - ( 2 * Theme.paddingSmall )
|
|
|
|
anchors.verticalCenter: parent.verticalCenter
|
2020-11-22 00:13:37 +03:00
|
|
|
|
2020-11-24 19:28:41 +03:00
|
|
|
IconButton {
|
|
|
|
id: secretChatButton
|
|
|
|
width: Theme.itemSizeLarge
|
|
|
|
height: Theme.itemSizeLarge
|
|
|
|
icon.source: "image://theme/icon-m-device-lock"
|
|
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
|
|
onClicked: {
|
2021-01-10 04:06:41 +03:00
|
|
|
tdLibWrapper.createNewSecretChat(display.id, "openDirectly");
|
2020-11-24 19:28:41 +03:00
|
|
|
}
|
|
|
|
}
|
2020-11-22 00:13:37 +03:00
|
|
|
|
2020-11-24 19:28:41 +03:00
|
|
|
Column {
|
|
|
|
height: parent.height
|
|
|
|
width: parent.width - secretChatButton.width - Theme.horizontalPageMargin
|
|
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
|
|
spacing: Theme.paddingSmall
|
|
|
|
Text {
|
|
|
|
width: parent.width
|
|
|
|
font.pixelSize: Theme.fontSizeMedium
|
|
|
|
font.weight: Font.ExtraBold
|
|
|
|
color: Theme.primaryColor
|
|
|
|
maximumLineCount: 1
|
|
|
|
elide: Text.ElideRight
|
|
|
|
textFormat: Text.StyledText
|
|
|
|
text: qsTr("Secret Chat")
|
|
|
|
}
|
|
|
|
Text {
|
|
|
|
width: parent.width
|
|
|
|
height: parent.height - privateChatHeader.height - Theme.paddingSmall
|
|
|
|
font.pixelSize: Theme.fontSizeTiny
|
|
|
|
color: Theme.secondaryColor
|
|
|
|
wrapMode: Text.Wrap
|
|
|
|
elide: Text.ElideRight
|
|
|
|
textFormat: Text.StyledText
|
|
|
|
text: qsTr("End-to-end-encrypted, accessible on this device only")
|
|
|
|
}
|
|
|
|
}
|
2020-11-22 00:13:37 +03:00
|
|
|
|
2020-11-24 19:28:41 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
MouseArea {
|
|
|
|
anchors.fill: parent
|
2020-11-22 00:13:37 +03:00
|
|
|
onClicked: {
|
2021-01-10 04:06:41 +03:00
|
|
|
tdLibWrapper.createNewSecretChat(display.id, "openDirectly");
|
2020-11-22 00:13:37 +03:00
|
|
|
}
|
2020-11-24 19:28:41 +03:00
|
|
|
onPressed: {
|
|
|
|
secretChatHighlightBackground.visible = true;
|
2020-11-22 00:13:37 +03:00
|
|
|
}
|
2020-11-24 19:28:41 +03:00
|
|
|
onReleased: {
|
|
|
|
secretChatHighlightBackground.visible = false;
|
2020-11-22 00:13:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-11-24 19:28:41 +03:00
|
|
|
Separator {
|
|
|
|
id: chatTypeSeparator
|
|
|
|
width: parent.width
|
|
|
|
color: Theme.primaryColor
|
|
|
|
horizontalAlignment: Qt.AlignHCenter
|
|
|
|
}
|
2020-11-22 00:13:37 +03:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-11-24 19:28:41 +03:00
|
|
|
VerticalScrollDecorator {}
|
2020-11-22 00:13:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Column {
|
|
|
|
|
|
|
|
opacity: visible ? 1 : 0
|
|
|
|
Behavior on opacity { FadeAnimation {} }
|
|
|
|
visible: newChatPage.isLoading
|
2020-11-20 20:30:33 +03:00
|
|
|
width: parent.width
|
2020-11-22 00:13:37 +03:00
|
|
|
height: loadingLabel.height + loadingBusyIndicator.height + Theme.paddingMedium
|
|
|
|
|
|
|
|
spacing: Theme.paddingMedium
|
|
|
|
|
|
|
|
anchors.verticalCenter: parent.verticalCenter
|
2020-11-20 20:30:33 +03:00
|
|
|
|
2020-11-22 00:13:37 +03:00
|
|
|
InfoLabel {
|
|
|
|
id: loadingLabel
|
2020-11-25 02:23:38 +03:00
|
|
|
text: qsTr("Loading contacts...")
|
2020-11-20 20:30:33 +03:00
|
|
|
}
|
|
|
|
|
2020-11-22 00:13:37 +03:00
|
|
|
BusyIndicator {
|
|
|
|
id: loadingBusyIndicator
|
|
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
|
|
running: newChatPage.isLoading
|
|
|
|
size: BusyIndicatorSize.Large
|
2020-11-20 20:30:33 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-11-22 00:13:37 +03:00
|
|
|
}
|
2020-11-20 20:30:33 +03:00
|
|
|
}
|
|
|
|
}
|