Compare commits
76 commits
Author | SHA1 | Date | |
---|---|---|---|
|
0236586e44 | ||
|
e13c7ae68c | ||
|
1d68123ea1 | ||
|
cf7b706582 | ||
|
c42d030d02 | ||
|
edfce9b492 | ||
|
e5d1ecd9f3 | ||
|
42a7813776 | ||
|
627faba0db | ||
|
a4ebaf52f5 | ||
|
660fe527f2 | ||
|
1a0ed7f298 | ||
062f5d3811 | |||
034c70542f | |||
|
ef244c3319 | ||
|
556505894c | ||
|
7c63ad66f9 | ||
|
26772a48eb | ||
|
2ded14deda | ||
|
465c082328 | ||
|
25e6660e8e | ||
f58afe92cb | |||
2b3ca0dff9 | |||
|
1e88a31f90 | ||
|
026d32c92a | ||
|
a28b9df6b5 | ||
d2bde99e1f | |||
f8ffedb5db | |||
4b7d17c02f | |||
0ae98f96b5 | |||
|
fb3d314ee2 | ||
|
b032b32db1 | ||
|
63f4b37655 | ||
|
bdc0423bf3 | ||
749f05816c | |||
06ebe95309 | |||
|
40ec4b0968 | ||
|
c4c9dc83c0 | ||
9a37db94ae | |||
|
0ba3a8cd7f | ||
|
0aeaf50c92 | ||
|
a9947ff9f7 | ||
|
c7324c020b | ||
|
46419b0960 | ||
|
c1c8729023 | ||
|
9bcc9ab690 | ||
|
0b6a2db2f1 | ||
61a04b034a | |||
|
ca42a5e7e0 | ||
400cda8dcd | |||
fe50ead4ee | |||
f1717cbd29 | |||
|
5394fde136 | ||
1ad324aa23 | |||
59b99a0a28 | |||
12dbac7480 | |||
258466beeb | |||
656e8ccfe7 | |||
22930628ae | |||
0d26167ee3 | |||
723105382d | |||
c9773fb5ab | |||
51227c1323 | |||
aac7fd7328 | |||
f3dd33c4ca | |||
|
83f0c54f8b | ||
71d1831ed3 | |||
|
29621b739a | ||
|
0b91948141 | ||
|
9d37635500 | ||
|
df6322c712 | ||
|
5de2e94f32 | ||
|
85732c6fbc | ||
|
a7ab0ed33a | ||
|
f152bbeb5b | ||
|
b469135877 |
4
.github/workflows/main.yml
vendored
|
@ -84,7 +84,7 @@ jobs:
|
||||||
assets+=("-a" "$asset")
|
assets+=("-a" "$asset")
|
||||||
done
|
done
|
||||||
tag_name="${GITHUB_REF##*/}"
|
tag_name="${GITHUB_REF##*/}"
|
||||||
hub release create "${assets[@]}" -m "$tag_name" "$tag_name"
|
gh release create "$tag_name" "${assets[@]}"
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
@ -97,6 +97,6 @@ jobs:
|
||||||
assets+=("-a" "$asset")
|
assets+=("-a" "$asset")
|
||||||
done
|
done
|
||||||
tag_name="${GITHUB_REF##*/}"
|
tag_name="${GITHUB_REF##*/}"
|
||||||
hub release create -p "${assets[@]}" -m "$tag_name" -m "This is a pre-release for testing purposes only. It may or may not be unstable." -m "Join the Telegram group to help out: https://github.com/Wunderfitz/harbour-fernschreiber/issues/162" "$tag_name"
|
gh release create "$tag_name" -p -n "This is a pre-release for testing purposes only. It may or may not be unstable." "${assets[@]}"
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
3
.gitignore
vendored
|
@ -53,3 +53,6 @@ compile_commands.json
|
||||||
|
|
||||||
# TDLib API Secrets
|
# TDLib API Secrets
|
||||||
tdlibsecrets.h
|
tdlibsecrets.h
|
||||||
|
|
||||||
|
#Convinience scripts
|
||||||
|
*.sh
|
||||||
|
|
|
@ -14,7 +14,11 @@ Fernschreiber wouldn't be the same without all the people helping in making it b
|
||||||
- Chat info page, performance improvements to chat page, location support, app initialization/registration with Telegram, project dependencies, emoji handling, qml/js optimizations, multi-message actions, i18n fixes, chat permission handling, code reviews, logging categories, bot support, github build: [jgibbon](https://github.com/jgibbon)
|
- Chat info page, performance improvements to chat page, location support, app initialization/registration with Telegram, project dependencies, emoji handling, qml/js optimizations, multi-message actions, i18n fixes, chat permission handling, code reviews, logging categories, bot support, github build: [jgibbon](https://github.com/jgibbon)
|
||||||
- Copy message to clipboard: [Christian Stemmle](https://github.com/chstem)
|
- Copy message to clipboard: [Christian Stemmle](https://github.com/chstem)
|
||||||
- Hide send message button if send-by-enter is switched on, focus text input on entering a chat: [santhoshmanikandan](https://github.com/santhoshmanikandan)
|
- Hide send message button if send-by-enter is switched on, focus text input on entering a chat: [santhoshmanikandan](https://github.com/santhoshmanikandan)
|
||||||
- Integration of logout and sesison options to settings page: [Peter G.](https://github.com/nephros)
|
- Integration of logout and sesison options to settings page, search results optimization, highlight unread conversations: [Peter G.](https://github.com/nephros)
|
||||||
|
- Option to always append last message in notifications: [Johannes Bachmann](https://github.com/dscheinah)
|
||||||
|
- Option to jump to quoted message, widescreen UI adjustments: [Mikhail Barashkov](https://github.com/mbarashkov)
|
||||||
|
|
||||||
|
This list might not be complete. In case I forgot something/somebody, please let me know or create a PR, thanks! :)
|
||||||
|
|
||||||
### Logo/Icon
|
### Logo/Icon
|
||||||
- Designed by [Matteo](https://github.com/iamnomeutente), adjustments by [Slava Monich](https://github.com/monich)
|
- Designed by [Matteo](https://github.com/iamnomeutente), adjustments by [Slava Monich](https://github.com/monich)
|
||||||
|
@ -48,7 +52,7 @@ const char TDLIB_API_HASH[] = "1234567890abcdef1234567890abcdef";
|
||||||
|
|
||||||
You get the Telegram API ID and hash as soon as you've registered your own application on [https://my.telegram.org](https://my.telegram.org).
|
You get the Telegram API ID and hash as soon as you've registered your own application on [https://my.telegram.org](https://my.telegram.org).
|
||||||
|
|
||||||
Moreover, you need to have a compiled version of [TDLib 1.8.3](https://github.com/tdlib/td) or higher in the sub-directory `tdlib`. This sub-directory must contain another sub-directory that fits to the target device architecture (e.g. armv7hl, i486). Within this directory, there needs to be a folder called `lib` that contains at least `libtdjson.so`. For armv7hl the relative path would consequently be `tdlib/armv7hl/lib`.
|
Moreover, you need to have a compiled version of [TDLib 1.8.21](https://github.com/tdlib/td) or higher in the sub-directory `tdlib`. This sub-directory must contain another sub-directory that fits to the target device architecture (e.g. armv7hl, i486). Within this directory, there needs to be a folder called `lib` that contains at least `libtdjson.so`. For armv7hl the relative path would consequently be `tdlib/armv7hl/lib`.
|
||||||
|
|
||||||
You may just want to download the [tdlib.zip from our fork](https://github.com/Wunderfitz/td/releases) to just use the exact version of the latest official Fernschreiber release. To use it, you need to extract it into your local `tdlib/` folder as described above. If so, you're done and can compile Fernschreiber using the Sailfish SDK. If you want to build TDLib for yourself, please keep on reading.
|
You may just want to download the [tdlib.zip from our fork](https://github.com/Wunderfitz/td/releases) to just use the exact version of the latest official Fernschreiber release. To use it, you need to extract it into your local `tdlib/` folder as described above. If so, you're done and can compile Fernschreiber using the Sailfish SDK. If you want to build TDLib for yourself, please keep on reading.
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Type=Application
|
Type=Application
|
||||||
X-Nemo-Application-Type=generic
|
X-Nemo-Application-Type=silica-qt5
|
||||||
Icon=harbour-fernschreiber
|
Icon=harbour-fernschreiber
|
||||||
Exec=harbour-fernschreiber
|
Exec=harbour-fernschreiber
|
||||||
Name=Fernschreiber
|
Name=Fernschreiber
|
||||||
|
|
|
@ -46,6 +46,7 @@ DISTFILES += qml/harbour-fernschreiber.qml \
|
||||||
qml/components/AudioPreview.qml \
|
qml/components/AudioPreview.qml \
|
||||||
qml/components/BackgroundImage.qml \
|
qml/components/BackgroundImage.qml \
|
||||||
qml/components/ChatListViewItem.qml \
|
qml/components/ChatListViewItem.qml \
|
||||||
|
qml/components/ContactSync.qml \
|
||||||
qml/components/DocumentPreview.qml \
|
qml/components/DocumentPreview.qml \
|
||||||
qml/components/GamePreview.qml \
|
qml/components/GamePreview.qml \
|
||||||
qml/components/ImagePreview.qml \
|
qml/components/ImagePreview.qml \
|
||||||
|
@ -139,7 +140,6 @@ DISTFILES += qml/harbour-fernschreiber.qml \
|
||||||
qml/pages/VideoPage.qml \
|
qml/pages/VideoPage.qml \
|
||||||
rpm/harbour-fernschreiber.changes \
|
rpm/harbour-fernschreiber.changes \
|
||||||
rpm/harbour-fernschreiber.spec \
|
rpm/harbour-fernschreiber.spec \
|
||||||
rpm/harbour-fernschreiber.yaml \
|
|
||||||
translations/*.ts \
|
translations/*.ts \
|
||||||
harbour-fernschreiber.desktop
|
harbour-fernschreiber.desktop
|
||||||
|
|
||||||
|
|
44
qml/components/ContactSync.qml
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2021 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.0
|
||||||
|
//import org.nemomobile.contacts 1.0
|
||||||
|
|
||||||
|
Item {
|
||||||
|
|
||||||
|
// signal syncError();
|
||||||
|
|
||||||
|
// function synchronize() {
|
||||||
|
// if (peopleModel.count === 0) {
|
||||||
|
// appNotification.show(qsTr("Could not synchronize your contacts with Telegram."));
|
||||||
|
// syncError();
|
||||||
|
// } else {
|
||||||
|
// contactsModel.startImportingContacts();
|
||||||
|
// for (var i = 0; i < peopleModel.count; i++ ) {
|
||||||
|
// contactsModel.importContact(peopleModel.get(i));
|
||||||
|
// }
|
||||||
|
// contactsModel.stopImportingContacts();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// PeopleModel {
|
||||||
|
// id: peopleModel
|
||||||
|
// requiredProperty: PeopleModel.PhoneNumberRequired
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
|
@ -40,7 +40,7 @@ Loader {
|
||||||
|
|
||||||
property string chatId
|
property string chatId
|
||||||
property string userName
|
property string userName
|
||||||
property bool userNameIsValid: userName !== "" && inlineBotInformation && userName.toLowerCase() === inlineBotInformation.username.toLowerCase()
|
property bool userNameIsValid: userName !== "" && inlineBotInformation && userName.toLowerCase() === inlineBotInformation.usernames.editable_username.toLowerCase()
|
||||||
property string query
|
property string query
|
||||||
property int currentOffset: 0
|
property int currentOffset: 0
|
||||||
property string responseExtra: chatId+"|"+userName+"|"+query+"|"+currentOffset
|
property string responseExtra: chatId+"|"+userName+"|"+query+"|"+currentOffset
|
||||||
|
|
|
@ -38,7 +38,7 @@ ListItem {
|
||||||
readonly property var userInformation: tdLibWrapper.getUserInformation(myMessage.sender_id.user_id)
|
readonly property var userInformation: tdLibWrapper.getUserInformation(myMessage.sender_id.user_id)
|
||||||
property QtObject precalculatedValues: ListView.view.precalculatedValues
|
property QtObject precalculatedValues: ListView.view.precalculatedValues
|
||||||
readonly property color textColor: isOwnMessage ? Theme.highlightColor : Theme.primaryColor
|
readonly property color textColor: isOwnMessage ? Theme.highlightColor : Theme.primaryColor
|
||||||
readonly property int textAlign: isOwnMessage ? Text.AlignRight : Text.AlignLeft
|
readonly property int textAlign: Text.AlignLeft
|
||||||
readonly property Page page: precalculatedValues.page
|
readonly property Page page: precalculatedValues.page
|
||||||
readonly property bool isSelected: messageListItem.precalculatedValues.pageIsSelecting && page.selectedMessages.some(function(existingMessage) {
|
readonly property bool isSelected: messageListItem.precalculatedValues.pageIsSelecting && page.selectedMessages.some(function(existingMessage) {
|
||||||
return existingMessage.id === messageId
|
return existingMessage.id === messageId
|
||||||
|
@ -47,6 +47,7 @@ ListItem {
|
||||||
readonly property bool canDeleteMessage: myMessage.can_be_deleted_for_all_users || (myMessage.can_be_deleted_only_for_self && myMessage.chat_id === page.myUserId)
|
readonly property bool canDeleteMessage: myMessage.can_be_deleted_for_all_users || (myMessage.can_be_deleted_only_for_self && myMessage.chat_id === page.myUserId)
|
||||||
property bool hasContentComponent
|
property bool hasContentComponent
|
||||||
property bool additionalOptionsOpened
|
property bool additionalOptionsOpened
|
||||||
|
property bool wasNavigatedTo: false
|
||||||
|
|
||||||
readonly property var additionalItemsModel: (extraContentLoader.item && ("extraContextMenuItems" in extraContentLoader.item)) ?
|
readonly property var additionalItemsModel: (extraContentLoader.item && ("extraContextMenuItems" in extraContentLoader.item)) ?
|
||||||
extraContentLoader.item.extraContextMenuItems : 0
|
extraContentLoader.item.extraContextMenuItems : 0
|
||||||
|
@ -64,9 +65,10 @@ ListItem {
|
||||||
readonly property bool showForwardMessageMenuItem: (baseContextMenuItemCount + 2) <= maxContextMenuItemCount
|
readonly property bool showForwardMessageMenuItem: (baseContextMenuItemCount + 2) <= maxContextMenuItemCount
|
||||||
// And don't count "More Options..." for "Delete Message" if "Delete Message" is the only extra option
|
// And don't count "More Options..." for "Delete Message" if "Delete Message" is the only extra option
|
||||||
readonly property bool haveSpaceForDeleteMessageMenuItem: (baseContextMenuItemCount + 3 - (deleteMessageIsOnlyExtraOption ? 1 : 0)) <= maxContextMenuItemCount
|
readonly property bool haveSpaceForDeleteMessageMenuItem: (baseContextMenuItemCount + 3 - (deleteMessageIsOnlyExtraOption ? 1 : 0)) <= maxContextMenuItemCount
|
||||||
|
property var chatReactions
|
||||||
property var messageReactions
|
property var messageReactions
|
||||||
|
|
||||||
highlighted: (down || isSelected || additionalOptionsOpened) && !menuOpen
|
highlighted: (down || isSelected || additionalOptionsOpened || wasNavigatedTo) && !menuOpen
|
||||||
openMenuOnPressAndHold: !messageListItem.precalculatedValues.pageIsSelecting
|
openMenuOnPressAndHold: !messageListItem.precalculatedValues.pageIsSelecting
|
||||||
|
|
||||||
signal replyToMessage()
|
signal replyToMessage()
|
||||||
|
@ -94,20 +96,43 @@ ListItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getInteractionText(viewCount, reactions) {
|
function getInteractionText(viewCount, reactions, size, highlightColor) {
|
||||||
var interactionText = "";
|
var interactionText = "";
|
||||||
if (viewCount > 0) {
|
if (viewCount > 0) {
|
||||||
interactionText = Emoji.emojify("👁️", Theme.fontSizeTiny) + Functions.getShortenedCount(viewCount);
|
interactionText = Emoji.emojify("👁️ ", size) + Functions.getShortenedCount(viewCount);
|
||||||
}
|
}
|
||||||
for (var i = 0; i < reactions.length; i++) {
|
for (var i = 0; i < reactions.length; i++) {
|
||||||
interactionText += ( " " + Emoji.emojify(reactions[i].reaction, Theme.fontSizeTiny) );
|
var reaction = reactions[i]
|
||||||
if (!chatPage.isPrivateChat) {
|
var reactionText = reaction.reaction ? reaction.reaction : (reaction.type && reaction.type.emoji) ? reaction.type.emoji : ""
|
||||||
interactionText += ( " " + Functions.getShortenedCount(reactions[i].total_count) );
|
if (reactionText) {
|
||||||
|
interactionText += ( " " + Emoji.emojify(reactionText, size) );
|
||||||
|
if (!chatPage.isPrivateChat) {
|
||||||
|
var count = Functions.getShortenedCount(reaction.total_count)
|
||||||
|
interactionText += " "
|
||||||
|
interactionText += (reaction.is_chosen ? ( "<font color='" + highlightColor + "'><b>" + count + "</b></font>" ) : count)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return interactionText;
|
return interactionText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openReactions() {
|
||||||
|
if (messageListItem.chatReactions) {
|
||||||
|
Debug.log("Using chat reactions")
|
||||||
|
messageListItem.messageReactions = chatReactions
|
||||||
|
showItemCompletelyTimer.requestedIndex = index;
|
||||||
|
showItemCompletelyTimer.start();
|
||||||
|
} else {
|
||||||
|
Debug.log("Obtaining message reactions")
|
||||||
|
tdLibWrapper.getMessageAvailableReactions(messageListItem.chatId, messageListItem.messageId);
|
||||||
|
}
|
||||||
|
selectReactionBubble.visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getContentWidthMultiplier() {
|
||||||
|
return Functions.isWidescreen(appWindow) ? 0.4 : 1.0
|
||||||
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (messageListItem.precalculatedValues.pageIsSelecting) {
|
if (messageListItem.precalculatedValues.pageIsSelecting) {
|
||||||
page.toggleMessageSelection(myMessage);
|
page.toggleMessageSelection(myMessage);
|
||||||
|
@ -125,12 +150,26 @@ ListItem {
|
||||||
|
|
||||||
if (messageListItem.messageReactions) {
|
if (messageListItem.messageReactions) {
|
||||||
messageListItem.messageReactions = null;
|
messageListItem.messageReactions = null;
|
||||||
|
selectReactionBubble.visible = false;
|
||||||
} else {
|
} else {
|
||||||
tdLibWrapper.getMessageAvailableReactions(messageListItem.chatId, messageListItem.messageId);
|
selectReactionBubble.visible = !selectReactionBubble.visible;
|
||||||
|
elementSelected(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onDoubleClicked: {
|
||||||
|
if (messageListItem.chatReactions) {
|
||||||
|
Debug.log("Using chat reactions")
|
||||||
|
messageListItem.messageReactions = chatReactions
|
||||||
|
showItemCompletelyTimer.requestedIndex = index;
|
||||||
|
showItemCompletelyTimer.start();
|
||||||
|
} else {
|
||||||
|
Debug.log("Obtaining message reactions")
|
||||||
|
tdLibWrapper.getMessageAvailableReactions(messageListItem.chatId, messageListItem.messageId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onPressAndHold: {
|
onPressAndHold: {
|
||||||
if (openMenuOnPressAndHold) {
|
if (openMenuOnPressAndHold) {
|
||||||
openContextMenu()
|
openContextMenu()
|
||||||
|
@ -154,6 +193,25 @@ ListItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: chatPage
|
||||||
|
onResetElements: {
|
||||||
|
messageListItem.messageReactions = null;
|
||||||
|
selectReactionBubble.visible = false;
|
||||||
|
}
|
||||||
|
onElementSelected: {
|
||||||
|
if (elementIndex !== index) {
|
||||||
|
selectReactionBubble.visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onNavigatedTo: {
|
||||||
|
if (targetIndex === index) {
|
||||||
|
messageListItem.wasNavigatedTo = true;
|
||||||
|
restoreNormalityTimer.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: contextMenuLoader
|
id: contextMenuLoader
|
||||||
active: false
|
active: false
|
||||||
|
@ -258,6 +316,9 @@ ListItem {
|
||||||
messageListItem.messageReactions = null;
|
messageListItem.messageReactions = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
onReactionsUpdated: {
|
||||||
|
chatReactions = tdLibWrapper.getChatReactions(page.chatInformation.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
|
@ -270,16 +331,34 @@ ListItem {
|
||||||
interval: 200
|
interval: 200
|
||||||
triggeredOnStart: false
|
triggeredOnStart: false
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
|
Debug.log("Show item completely timer triggered, requested index: " + requestedIndex + ", current index: " + index)
|
||||||
if (requestedIndex === index) {
|
if (requestedIndex === index) {
|
||||||
chatView.highlightMoveDuration = -1;
|
var p = chatView.contentItem.mapFromItem(reactionsColumn, 0, 0)
|
||||||
chatView.highlightResizeDuration = -1;
|
if (chatView.contentY > p.y || p.y + reactionsColumn.height > chatView.contentY + chatView.height) {
|
||||||
chatView.scrollToIndex(requestedIndex);
|
Debug.log("Moving reactions for item at", requestedIndex, "info the view")
|
||||||
chatView.highlightMoveDuration = 0;
|
chatView.highlightMoveDuration = -1
|
||||||
chatView.highlightResizeDuration = 0;
|
chatView.highlightResizeDuration = -1
|
||||||
|
chatView.scrollToIndex(requestedIndex, height <= chatView.height ? ListView.Contain : ListView.End)
|
||||||
|
chatView.highlightMoveDuration = 0
|
||||||
|
chatView.highlightResizeDuration = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: restoreNormalityTimer
|
||||||
|
|
||||||
|
repeat: false
|
||||||
|
running: false
|
||||||
|
interval: 1000
|
||||||
|
triggeredOnStart: false
|
||||||
|
onTriggered: {
|
||||||
|
Debug.log("Restore normality for index " + index);
|
||||||
|
messageListItem.wasNavigatedTo = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
delegateComponentLoadingTimer.start();
|
delegateComponentLoadingTimer.start();
|
||||||
if (myMessage.reply_to_message_id) {
|
if (myMessage.reply_to_message_id) {
|
||||||
|
@ -322,8 +401,10 @@ ListItem {
|
||||||
id: messageTextRow
|
id: messageTextRow
|
||||||
spacing: Theme.paddingSmall
|
spacing: Theme.paddingSmall
|
||||||
width: precalculatedValues.entryWidth
|
width: precalculatedValues.entryWidth
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: Functions.isWidescreen(appWindow) ? undefined : parent.horizontalCenter
|
||||||
|
anchors.left: Functions.isWidescreen(appWindow) ? parent.left : undefined
|
||||||
y: Theme.paddingSmall
|
y: Theme.paddingSmall
|
||||||
|
anchors.leftMargin: Functions.isWidescreen(appWindow) ? Theme.paddingMedium : undefined
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: profileThumbnailLoader
|
id: profileThumbnailLoader
|
||||||
|
@ -363,13 +444,13 @@ ListItem {
|
||||||
|
|
||||||
anchors {
|
anchors {
|
||||||
left: parent.left
|
left: parent.left
|
||||||
leftMargin: messageListItem.isOwnMessage ? precalculatedValues.pageMarginDouble : 0
|
leftMargin: page.isPrivateChat ? (messageListItem.isOwnMessage ? precalculatedValues.pageMarginDouble : 0) : 0 //левый марджин для собственных сообщений в приватных чатах. В остальных на полную ширину
|
||||||
verticalCenter: parent.verticalCenter
|
verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
height: messageTextColumn.height + precalculatedValues.paddingMediumDouble
|
height: messageTextColumn.height + precalculatedValues.paddingMediumDouble
|
||||||
width: precalculatedValues.backgroundWidth
|
width: precalculatedValues.backgroundWidth
|
||||||
property bool isUnread: index > chatModel.getLastReadMessageIndex() && myMessage['@type'] !== "sponsoredMessage"
|
property bool isUnread: index > chatModel.getLastReadMessageIndex() && myMessage['@type'] !== "sponsoredMessage"
|
||||||
color: Theme.colorScheme === Theme.LightOnDark ? (isUnread ? Theme.secondaryHighlightColor : Theme.secondaryColor) : (isUnread ? Theme.backgroundGlowColor : Theme.overlayBackgroundColor)
|
color: Theme.colorScheme === Theme.LightOnDark ? (isOwnMessage ? Theme.highlightBackgroundColor : (isUnread ? Theme.secondaryHighlightColor : Theme.secondaryColor)) : (isOwnMessage ? Theme.highlightBackgroundColor : (isUnread ? Theme.backgroundGlowColor : Theme.overlayBackgroundColor))
|
||||||
radius: parent.width / 50
|
radius: parent.width / 50
|
||||||
opacity: isUnread ? 0.5 : 0.2
|
opacity: isUnread ? 0.5 : 0.2
|
||||||
visible: appSettings.showStickersAsImages || (myMessage.content['@type'] !== "messageSticker" && myMessage.content['@type'] !== "messageAnimatedEmoji")
|
visible: appSettings.showStickersAsImages || (myMessage.content['@type'] !== "messageSticker" && myMessage.content['@type'] !== "messageAnimatedEmoji")
|
||||||
|
@ -398,7 +479,7 @@ ListItem {
|
||||||
truncationMode: TruncationMode.Fade
|
truncationMode: TruncationMode.Fade
|
||||||
textFormat: Text.StyledText
|
textFormat: Text.StyledText
|
||||||
horizontalAlignment: messageListItem.textAlign
|
horizontalAlignment: messageListItem.textAlign
|
||||||
visible: precalculatedValues.showUserInfo || myMessage['@type'] === "sponsoredMessage"
|
visible: messageListItem.isOwnMessage ? false : (precalculatedValues.showUserInfo || myMessage['@type'] === "sponsoredMessage")
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
enabled: !(messageListItem.precalculatedValues.pageIsSelecting || messageListItem.isAnonymous)
|
enabled: !(messageListItem.precalculatedValues.pageIsSelecting || messageListItem.isAnonymous)
|
||||||
|
@ -440,8 +521,12 @@ ListItem {
|
||||||
page.toggleMessageSelection(myMessage)
|
page.toggleMessageSelection(myMessage)
|
||||||
} else {
|
} else {
|
||||||
messageOptionsDrawer.open = false
|
messageOptionsDrawer.open = false
|
||||||
messageOverlayLoader.overlayMessage = messageInReplyToRow.inReplyToMessage
|
if(appSettings.goToQuotedMessage) {
|
||||||
messageOverlayLoader.active = true
|
chatPage.showMessage(messageInReplyToRow.inReplyToMessage.id, true)
|
||||||
|
} else {
|
||||||
|
messageOverlayLoader.active = true
|
||||||
|
messageOverlayLoader.overlayMessage = messageInReplyToRow.inReplyToMessage
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onPressAndHold: {
|
onPressAndHold: {
|
||||||
|
@ -467,11 +552,12 @@ ListItem {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if (myMessage.forward_info.origin["@type"] === "messageForwardOriginChannel") {
|
var originType = myMessage.forward_info.origin["@type"]
|
||||||
|
if (originType === "messageOriginChannel" || originType === "messageForwardOriginChannel") {
|
||||||
var otherChatInformation = tdLibWrapper.getChat(myMessage.forward_info.origin.chat_id);
|
var otherChatInformation = tdLibWrapper.getChat(myMessage.forward_info.origin.chat_id);
|
||||||
forwardedThumbnail.photoData = (typeof otherChatInformation.photo !== "undefined") ? otherChatInformation.photo.small : {};
|
forwardedThumbnail.photoData = (typeof otherChatInformation.photo !== "undefined") ? otherChatInformation.photo.small : {};
|
||||||
forwardedChannelText.text = Emoji.emojify(otherChatInformation.title, Theme.fontSizeExtraSmall);
|
forwardedChannelText.text = Emoji.emojify(otherChatInformation.title, Theme.fontSizeExtraSmall);
|
||||||
} else if (myMessage.forward_info.origin["@type"] === "messageForwardOriginUser") {
|
} else if (originType === "messageOriginUser" || originType === "messageForwardOriginUser") {
|
||||||
var otherUserInformation = tdLibWrapper.getUserInformation(myMessage.forward_info.origin.sender_user_id);
|
var otherUserInformation = tdLibWrapper.getUserInformation(myMessage.forward_info.origin.sender_user_id);
|
||||||
forwardedThumbnail.photoData = (typeof otherUserInformation.profile_photo !== "undefined") ? otherUserInformation.profile_photo.small : {};
|
forwardedThumbnail.photoData = (typeof otherUserInformation.profile_photo !== "undefined") ? otherUserInformation.profile_photo.small : {};
|
||||||
forwardedChannelText.text = Emoji.emojify(Functions.getUserName(otherUserInformation), Theme.fontSizeExtraSmall);
|
forwardedChannelText.text = Emoji.emojify(Functions.getUserName(otherUserInformation), Theme.fontSizeExtraSmall);
|
||||||
|
@ -552,7 +638,7 @@ ListItem {
|
||||||
id: webPagePreviewLoader
|
id: webPagePreviewLoader
|
||||||
active: false
|
active: false
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
width: parent.width
|
width: parent.width * getContentWidthMultiplier()
|
||||||
height: (status === Loader.Ready) ? item.implicitHeight : myMessage.content.web_page ? precalculatedValues.webPagePreviewHeight : 0
|
height: (status === Loader.Ready) ? item.implicitHeight : myMessage.content.web_page ? precalculatedValues.webPagePreviewHeight : 0
|
||||||
|
|
||||||
sourceComponent: Component {
|
sourceComponent: Component {
|
||||||
|
@ -566,7 +652,7 @@ ListItem {
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: extraContentLoader
|
id: extraContentLoader
|
||||||
width: parent.width
|
width: parent.width * getContentWidthMultiplier()
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
height: item ? item.height : (messageListItem.hasContentComponent ? chatView.getContentComponentHeight(model.content_type, myMessage.content, width) : 0)
|
height: item ? item.height : (messageListItem.hasContentComponent ? chatView.getContentComponentHeight(model.content_type, myMessage.content, width) : 0)
|
||||||
}
|
}
|
||||||
|
@ -625,7 +711,7 @@ ListItem {
|
||||||
height: ( ( chatPage.isChannel && messageViewCount > 0 ) || reactions.length > 0 ) ? ( Theme.fontSizeExtraSmall + Theme.paddingSmall ) : 0
|
height: ( ( chatPage.isChannel && messageViewCount > 0 ) || reactions.length > 0 ) ? ( Theme.fontSizeExtraSmall + Theme.paddingSmall ) : 0
|
||||||
sourceComponent: Component {
|
sourceComponent: Component {
|
||||||
Label {
|
Label {
|
||||||
text: getInteractionText(messageViewCount, reactions)
|
text: getInteractionText(messageViewCount, reactions, font.pixelSize, Theme.highlightColor)
|
||||||
width: parent.width
|
width: parent.width
|
||||||
font.pixelSize: Theme.fontSizeTiny
|
font.pixelSize: Theme.fontSizeTiny
|
||||||
color: messageListItem.isOwnMessage ? Theme.secondaryHighlightColor : Theme.secondaryColor
|
color: messageListItem.isOwnMessage ? Theme.secondaryHighlightColor : Theme.secondaryColor
|
||||||
|
@ -677,7 +763,7 @@ ListItem {
|
||||||
Image {
|
Image {
|
||||||
id: emojiPicture
|
id: emojiPicture
|
||||||
source: Emoji.getEmojiPath(modelData)
|
source: Emoji.getEmojiPath(modelData)
|
||||||
width: Theme.fontSizeLarge
|
width: status === Image.Ready ? Theme.fontSizeLarge : 0
|
||||||
height: Theme.fontSizeLarge
|
height: Theme.fontSizeLarge
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,9 +40,11 @@ Flickable {
|
||||||
|
|
||||||
function getOriginalAuthor(forwardInformation, fontSize) {
|
function getOriginalAuthor(forwardInformation, fontSize) {
|
||||||
switch (forwardInformation.origin["@type"]) {
|
switch (forwardInformation.origin["@type"]) {
|
||||||
|
case "messageOriginChannel":
|
||||||
case "messageForwardOriginChannel":
|
case "messageForwardOriginChannel":
|
||||||
var otherChatInformation = tdLibWrapper.getChat(forwardInformation.origin.chat_id);
|
var otherChatInformation = tdLibWrapper.getChat(forwardInformation.origin.chat_id);
|
||||||
return Emoji.emojify(otherChatInformation.title, fontSize);
|
return Emoji.emojify(otherChatInformation.title, fontSize);
|
||||||
|
case "messageOriginUser":
|
||||||
case "messageForwardOriginUser":
|
case "messageForwardOriginUser":
|
||||||
var otherUserInformation = tdLibWrapper.getUserInformation(forwardInformation.origin.sender_id.user_id);
|
var otherUserInformation = tdLibWrapper.getUserInformation(forwardInformation.origin.sender_id.user_id);
|
||||||
return Emoji.emojify(Functions.getUserName(otherUserInformation), fontSize);
|
return Emoji.emojify(Functions.getUserName(otherUserInformation), fontSize);
|
||||||
|
|
|
@ -31,12 +31,12 @@ Loader {
|
||||||
property var botUserInformation: tdLibWrapper.getUserInformation(message.via_bot_user_id)
|
property var botUserInformation: tdLibWrapper.getUserInformation(message.via_bot_user_id)
|
||||||
color: Theme.secondaryColor
|
color: Theme.secondaryColor
|
||||||
font.pixelSize: Theme.fontSizeExtraSmall
|
font.pixelSize: Theme.fontSizeExtraSmall
|
||||||
text: qsTr("via %1", "message posted via bot user").arg("<a style=\"text-decoration: none; font-weight: bold; color:"+Theme.primaryColor+"\" href=\"userId://" + message.via_bot_user_id + "\">@" + Emoji.emojify(botUserInformation.username, font.pixelSize)+"</a>")
|
text: qsTr("via %1", "message posted via bot user").arg("<a style=\"text-decoration: none; font-weight: bold; color:"+Theme.primaryColor+"\" href=\"userId://" + message.via_bot_user_id + "\">@" + Emoji.emojify(botUserInformation.usernames.editable_username, font.pixelSize)+"</a>")
|
||||||
textFormat: Text.RichText
|
textFormat: Text.RichText
|
||||||
truncationMode: TruncationMode.Fade
|
truncationMode: TruncationMode.Fade
|
||||||
onLinkActivated: {
|
onLinkActivated: {
|
||||||
if(link === "userId://" + message.via_bot_user_id && botUserInformation.type.is_inline) {
|
if(link === "userId://" + message.via_bot_user_id && botUserInformation.type.is_inline) {
|
||||||
newMessageTextField.text = "@"+botUserInformation.username+" "
|
newMessageTextField.text = "@"+botUserInformation.usernames.editable_username+" "
|
||||||
newMessageTextField.cursorPosition = newMessageTextField.text.length
|
newMessageTextField.cursorPosition = newMessageTextField.text.length
|
||||||
lostFocusTimer.start();
|
lostFocusTimer.start();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import QtQuick 2.6
|
import QtQuick 2.6
|
||||||
import Sailfish.Silica 1.0
|
import Sailfish.Silica 1.0
|
||||||
import WerkWolf.Fernschreiber 1.0
|
import WerkWolf.Fernschreiber 1.0
|
||||||
|
import "../js/functions.js" as Functions
|
||||||
|
|
||||||
ListItem {
|
ListItem {
|
||||||
id: chatListViewItem
|
id: chatListViewItem
|
||||||
|
@ -87,7 +88,7 @@ ListItem {
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: chatUnreadMessagesCountBackground
|
id: chatUnreadMessagesCountBackground
|
||||||
color: isMuted ? ((Theme.colorScheme === Theme.DarkOnLight) ? "lightgray" : "dimgray") : Theme.highlightBackgroundColor
|
color: isMuted ? ((Theme.colorScheme === Theme.DarkOnLight) ? "lightgray" : "dimgray") : Theme.highlightBackgroundColor
|
||||||
width: Theme.fontSizeLarge
|
width: chatUnreadMessagesCount.width + Theme.fontSizeLarge / 2
|
||||||
height: Theme.fontSizeLarge
|
height: Theme.fontSizeLarge
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
|
@ -103,31 +104,42 @@ ListItem {
|
||||||
anchors.centerIn: chatUnreadMessagesCountBackground
|
anchors.centerIn: chatUnreadMessagesCountBackground
|
||||||
visible: chatListViewItem.unreadCount > 0
|
visible: chatListViewItem.unreadCount > 0
|
||||||
opacity: isMuted ? Theme.opacityHigh : 1.0
|
opacity: isMuted ? Theme.opacityHigh : 1.0
|
||||||
text: chatListViewItem.unreadCount > 99 ? "99+" : chatListViewItem.unreadCount
|
text: Functions.formatUnreadCount(chatListViewItem.unreadCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: chatUnreadReactionCountBackground
|
|
||||||
color: isMuted ? ((Theme.colorScheme === Theme.DarkOnLight) ? "lightgray" : "dimgray") : Theme.highlightBackgroundColor
|
color: isMuted ? ((Theme.colorScheme === Theme.DarkOnLight) ? "lightgray" : "dimgray") : Theme.highlightBackgroundColor
|
||||||
width: Theme.fontSizeLarge
|
width: Theme.fontSizeLarge
|
||||||
height: Theme.fontSizeLarge
|
height: Theme.fontSizeLarge
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
radius: parent.width / 2
|
radius: parent.width / 2
|
||||||
visible: chatListViewItem.unreadReactionCount > 0
|
visible: chatListViewItem.unreadReactionCount > 0 || chatListViewItem.unreadMentionCount > 0
|
||||||
}
|
|
||||||
|
|
||||||
Icon {
|
Icon {
|
||||||
source: "image://theme/icon-s-favorite"
|
source: "image://theme/icon-s-favorite"
|
||||||
height: Theme.iconSizeExtraSmall
|
height: Theme.iconSizeExtraSmall
|
||||||
width: Theme.iconSizeExtraSmall
|
width: Theme.iconSizeExtraSmall
|
||||||
highlighted: chatListViewItem.highlighted
|
highlighted: chatListViewItem.highlighted
|
||||||
anchors.centerIn: chatUnreadReactionCountBackground
|
anchors.centerIn: parent
|
||||||
visible: chatListViewItem.unreadReactionCount > 0
|
visible: chatListViewItem.unreadReactionCount > 0 && !chatListViewItem.unreadMentionCount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
font {
|
||||||
|
pixelSize: Theme.iconSizeExtraSmall
|
||||||
|
bold: true
|
||||||
|
}
|
||||||
|
color: Theme.primaryColor
|
||||||
|
anchors.centerIn: parent
|
||||||
|
visible: chatListViewItem.unreadMentionCount > 0
|
||||||
|
opacity: isMuted ? Theme.opacityHigh : 1.0
|
||||||
|
text: "@"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: contentColumn
|
id: contentColumn
|
||||||
anchors {
|
anchors {
|
||||||
|
@ -150,6 +162,9 @@ ListItem {
|
||||||
truncationMode: TruncationMode.Fade
|
truncationMode: TruncationMode.Fade
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
width: Math.min(contentColumn.width - (verifiedImage.visible ? (verifiedImage.width + primaryTextRow.spacing) : 0) - (mutedImage.visible ? (mutedImage.width + primaryTextRow.spacing) : 0), implicitWidth)
|
width: Math.min(contentColumn.width - (verifiedImage.visible ? (verifiedImage.width + primaryTextRow.spacing) : 0) - (mutedImage.visible ? (mutedImage.width + primaryTextRow.spacing) : 0), implicitWidth)
|
||||||
|
font.bold: appSettings.highlightUnreadConversations && ( !chatListViewItem.isMuted && (chatListViewItem.unreadCount > 0 || chatListViewItem.isMarkedAsUnread) )
|
||||||
|
font.italic: appSettings.highlightUnreadConversations && (chatListViewItem.unreadReactionCount > 0)
|
||||||
|
color: (appSettings.highlightUnreadConversations && (chatListViewItem.unreadCount > 0)) ? Theme.highlightColor : Theme.primaryColor
|
||||||
}
|
}
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
|
|
|
@ -60,12 +60,12 @@ Column {
|
||||||
},
|
},
|
||||||
inlineKeyboardButtonTypeSwitchInline: function() {
|
inlineKeyboardButtonTypeSwitchInline: function() {
|
||||||
if(modelData.type.in_current_chat) {
|
if(modelData.type.in_current_chat) {
|
||||||
chatPage.setMessageText("@" + userInformation.username + " "+(modelData.type.query || ""))
|
chatPage.setMessageText("@" + userInformation.usernames.editable_username + " "+(modelData.type.query || ""))
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
pageStack.push(Qt.resolvedUrl("../pages/ChatSelectionPage.qml"), {
|
pageStack.push(Qt.resolvedUrl("../pages/ChatSelectionPage.qml"), {
|
||||||
myUserId: chatPage.myUserId,
|
myUserId: chatPage.myUserId,
|
||||||
payload: { neededPermissions: ["can_send_other_messages"], text:"@" + userInformation.username + " "+(modelData.type.query || "")},
|
payload: { neededPermissions: ["can_send_other_messages"], text:"@" + userInformation.usernames.editable_username + " "+(modelData.type.query || "")},
|
||||||
state: "fillTextArea"
|
state: "fillTextArea"
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -300,7 +300,8 @@ SilicaFlickable {
|
||||||
}
|
}
|
||||||
leftMargin: imageContainer.getEased((imageContainer.minDimension + Theme.paddingMedium), 0, imageContainer.tweenFactor) + Theme.horizontalPageMargin
|
leftMargin: imageContainer.getEased((imageContainer.minDimension + Theme.paddingMedium), 0, imageContainer.tweenFactor) + Theme.horizontalPageMargin
|
||||||
title: chatInformationPage.chatInformation.title !== "" ? Emoji.emojify(chatInformationPage.chatInformation.title, Theme.fontSizeLarge) : qsTr("Unknown")
|
title: chatInformationPage.chatInformation.title !== "" ? Emoji.emojify(chatInformationPage.chatInformation.title, Theme.fontSizeLarge) : qsTr("Unknown")
|
||||||
description: (chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) ? ("@"+(chatInformationPage.privateChatUserInformation.username || chatInformationPage.chatPartnerGroupId)) : ""
|
description: ((chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) && chatInformationPage.privateChatUserInformation.usernames.editable_username)
|
||||||
|
? ("@"+chatInformationPage.privateChatUserInformation.usernames.editable_username) : ""
|
||||||
}
|
}
|
||||||
|
|
||||||
SilicaFlickable {
|
SilicaFlickable {
|
||||||
|
@ -363,6 +364,27 @@ SilicaFlickable {
|
||||||
height: imageContainer.hasImage ? imageContainer.maxDimension : 0
|
height: imageContainer.hasImage ? imageContainer.maxDimension : 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
id: copyIdText
|
||||||
|
x: Math.max(headerItem.x + imageContainer.x - groupInfoItem.x + (imageContainer.width - width)/2, 0)
|
||||||
|
text: chatInformationPage.chatPartnerGroupId
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: copyIdMouseArea.pressed ? Theme.secondaryHighlightColor : Theme.highlightColor
|
||||||
|
visible: text !== ""
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: copyIdMouseArea
|
||||||
|
anchors {
|
||||||
|
fill: parent
|
||||||
|
margins: -Theme.paddingLarge
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
Clipboard.text = copyIdText.text
|
||||||
|
appNotification.show(qsTr("ID has been copied to the clipboard."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
InformationEditArea {
|
InformationEditArea {
|
||||||
visible: canEdit
|
visible: canEdit
|
||||||
canEdit: !(chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) && chatInformationPage.groupInformation.status && (chatInformationPage.groupInformation.status.can_change_info || chatInformationPage.groupInformation.status["@type"] === "chatMemberStatusCreator")
|
canEdit: !(chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) && chatInformationPage.groupInformation.status && (chatInformationPage.groupInformation.status.can_change_info || chatInformationPage.groupInformation.status["@type"] === "chatMemberStatusCreator")
|
||||||
|
|
|
@ -79,7 +79,7 @@ ChatInformationTabItemBase {
|
||||||
// chat title
|
// chat title
|
||||||
primaryText.text: Emoji.emojify(Functions.getUserName(user), primaryText.font.pixelSize)
|
primaryText.text: Emoji.emojify(Functions.getUserName(user), primaryText.font.pixelSize)
|
||||||
// last user
|
// last user
|
||||||
prologSecondaryText.text: "@"+(user.username !== "" ? user.username : member_id.user_id) + (member_id.user_id === chatInformationPage.myUserId ? " " + qsTr("You") : "")
|
prologSecondaryText.text: "@"+(user.username ? user.username : member_id.user_id) + (member_id.user_id === chatInformationPage.myUserId ? " " + qsTr("You") : "")
|
||||||
secondaryText {
|
secondaryText {
|
||||||
horizontalAlignment: Text.AlignRight
|
horizontalAlignment: Text.AlignRight
|
||||||
property string statusText: Functions.getChatMemberStatusText(model.status["@type"])
|
property string statusText: Functions.getChatMemberStatusText(model.status["@type"])
|
||||||
|
@ -180,6 +180,9 @@ ChatInformationTabItemBase {
|
||||||
for(var memberIndex in members) {
|
for(var memberIndex in members) {
|
||||||
var memberData = members[memberIndex];
|
var memberData = members[memberIndex];
|
||||||
var userInfo = tdLibWrapper.getUserInformation(memberData.member_id.user_id) || {user:{}, bot_info:{}};
|
var userInfo = tdLibWrapper.getUserInformation(memberData.member_id.user_id) || {user:{}, bot_info:{}};
|
||||||
|
if (!userInfo.username && userInfo.usernames && userInfo.usernames.active_usernames) {
|
||||||
|
userInfo.username = userInfo.usernames.active_usernames[0]
|
||||||
|
}
|
||||||
memberData.user = userInfo;
|
memberData.user = userInfo;
|
||||||
memberData.bot_info = memberData.bot_info || {};
|
memberData.bot_info = memberData.bot_info || {};
|
||||||
pageContent.membersList.append(memberData);
|
pageContent.membersList.append(memberData);
|
||||||
|
|
|
@ -27,7 +27,7 @@ MessageContentBase {
|
||||||
|
|
||||||
property var stickerData: messageListItem ? messageListItem.myMessage.content.sticker : overlayFlickable.overlayMessage.content.sticker;
|
property var stickerData: messageListItem ? messageListItem.myMessage.content.sticker : overlayFlickable.overlayMessage.content.sticker;
|
||||||
readonly property bool asEmoji: appSettings.showStickersAsEmojis
|
readonly property bool asEmoji: appSettings.showStickersAsEmojis
|
||||||
readonly property bool animated: stickerData.type["@type"] === "stickerTypeAnimated" && appSettings.animateStickers
|
readonly property bool animated: stickerData.format["@type"] === "stickerFormatTgs" && appSettings.animateStickers
|
||||||
readonly property bool stickerVisible: staticStickerLoader.item ? staticStickerLoader.item.visible :
|
readonly property bool stickerVisible: staticStickerLoader.item ? staticStickerLoader.item.visible :
|
||||||
animatedStickerLoader.item ? animatedStickerLoader.item.visible : false
|
animatedStickerLoader.item ? animatedStickerLoader.item.visible : false
|
||||||
readonly property bool isOwnSticker : messageListItem ? messageListItem.isOwnMessage : overlayFlickable.isOwnMessage
|
readonly property bool isOwnSticker : messageListItem ? messageListItem.isOwnMessage : overlayFlickable.isOwnMessage
|
||||||
|
|
|
@ -95,7 +95,7 @@ MessageContentBase {
|
||||||
tdLibWrapper.downloadFile(previewFileId);
|
tdLibWrapper.downloadFile(previewFileId);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
placeholderImage.source = "image://theme/icon-l-video?white";
|
placeholderImage.source = "image://theme/icon-m-video?white";
|
||||||
placeholderImage.width = Theme.itemSizeLarge
|
placeholderImage.width = Theme.itemSizeLarge
|
||||||
placeholderImage.height = Theme.itemSizeLarge
|
placeholderImage.height = Theme.itemSizeLarge
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,10 @@
|
||||||
|
|
||||||
import QtQuick 2.6
|
import QtQuick 2.6
|
||||||
import Sailfish.Silica 1.0
|
import Sailfish.Silica 1.0
|
||||||
|
import "../../js/functions.js" as Functions
|
||||||
|
|
||||||
Grid {
|
Grid {
|
||||||
width: parent.width - ( 2 * x )
|
width: parent.width - ( 2 * x )
|
||||||
columns: (appWindow.deviceOrientation & Orientation.LandscapeMask) || Screen.sizeCategory === Screen.Large || Screen.sizeCategory === Screen.ExtraLarge ? 2 : 1
|
columns: Functions.isWidescreen(appWindow) ? 2 : 1
|
||||||
readonly property real columnWidth: width/columns
|
readonly property real columnWidth: width/columns
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,17 @@ AccordionItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextSwitch {
|
||||||
|
width: parent.columnWidth
|
||||||
|
checked: appSettings.highlightUnreadConversations
|
||||||
|
text: qsTr("Highlight unread messages")
|
||||||
|
description: qsTr("Highlight Conversations with unread messages")
|
||||||
|
automaticCheck: false
|
||||||
|
onClicked: {
|
||||||
|
appSettings.highlightUnreadConversations = !checked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TextSwitch {
|
TextSwitch {
|
||||||
width: parent.columnWidth
|
width: parent.columnWidth
|
||||||
checked: appSettings.useOpenWith
|
checked: appSettings.useOpenWith
|
||||||
|
@ -81,6 +92,28 @@ AccordionItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextSwitch {
|
||||||
|
width: parent.columnWidth
|
||||||
|
checked: appSettings.notificationAlwaysShowPreview
|
||||||
|
text: qsTr("Always append message preview to notifications")
|
||||||
|
description: qsTr("In addition to showing the number of unread messages, the latest message will also be appended to notifications.")
|
||||||
|
automaticCheck: false
|
||||||
|
onClicked: {
|
||||||
|
appSettings.notificationAlwaysShowPreview = !checked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextSwitch {
|
||||||
|
width: parent.columnWidth
|
||||||
|
checked: appSettings.goToQuotedMessage
|
||||||
|
text: qsTr("Go to quoted message")
|
||||||
|
description: qsTr("When tapping a quoted message, open it in chat instead of showing it in an overlay.")
|
||||||
|
automaticCheck: false
|
||||||
|
onClicked: {
|
||||||
|
appSettings.goToQuotedMessage = !checked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ComboBox {
|
ComboBox {
|
||||||
id: feedbackComboBox
|
id: feedbackComboBox
|
||||||
width: parent.columnWidth
|
width: parent.columnWidth
|
||||||
|
@ -135,35 +168,53 @@ AccordionItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextSwitch {
|
Item {
|
||||||
width: parent.columnWidth
|
// Occupies one grid cell so that the column ends up under the combo box
|
||||||
checked: appSettings.notificationTurnsDisplayOn && enabled
|
// in the landscape layout
|
||||||
text: qsTr("Notification turns on the display")
|
visible: parent.columns === 2
|
||||||
enabled: appSettings.notificationFeedback !== AppSettings.NotificationFeedbackNone
|
width: 1
|
||||||
height: enabled ? implicitHeight: 0
|
height: 1
|
||||||
clip: height < implicitHeight
|
|
||||||
visible: height > 0
|
|
||||||
automaticCheck: false
|
|
||||||
onClicked: {
|
|
||||||
appSettings.notificationTurnsDisplayOn = !checked
|
|
||||||
}
|
|
||||||
Behavior on height { SmoothedAnimation { duration: 200 } }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TextSwitch {
|
Column {
|
||||||
width: parent.columnWidth
|
|
||||||
checked: appSettings.notificationSoundsEnabled && enabled
|
|
||||||
text: qsTr("Enable notification sounds")
|
|
||||||
description: qsTr("When sounds are enabled, Fernschreiber will use the current Sailfish OS notification sound for chats, which can be configured in the system settings.")
|
|
||||||
enabled: appSettings.notificationFeedback !== AppSettings.NotificationFeedbackNone
|
enabled: appSettings.notificationFeedback !== AppSettings.NotificationFeedbackNone
|
||||||
|
width: parent.columnWidth
|
||||||
height: enabled ? implicitHeight: 0
|
height: enabled ? implicitHeight: 0
|
||||||
clip: height < implicitHeight
|
clip: height < implicitHeight
|
||||||
visible: height > 0
|
visible: height > 0
|
||||||
automaticCheck: false
|
|
||||||
onClicked: {
|
|
||||||
appSettings.notificationSoundsEnabled = !checked
|
|
||||||
}
|
|
||||||
Behavior on height { SmoothedAnimation { duration: 200 } }
|
Behavior on height { SmoothedAnimation { duration: 200 } }
|
||||||
|
|
||||||
|
TextSwitch {
|
||||||
|
checked: appSettings.notificationSuppressContent && enabled
|
||||||
|
text: qsTr("Hide content in notifications")
|
||||||
|
enabled: parent.enabled
|
||||||
|
automaticCheck: false
|
||||||
|
onClicked: {
|
||||||
|
appSettings.notificationSuppressContent = !checked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextSwitch {
|
||||||
|
checked: appSettings.notificationTurnsDisplayOn && enabled
|
||||||
|
text: qsTr("Notification turns on the display")
|
||||||
|
enabled: parent.enabled
|
||||||
|
automaticCheck: false
|
||||||
|
onClicked: {
|
||||||
|
appSettings.notificationTurnsDisplayOn = !checked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextSwitch {
|
||||||
|
checked: appSettings.notificationSoundsEnabled && enabled
|
||||||
|
text: qsTr("Enable notification sounds")
|
||||||
|
description: qsTr("When sounds are enabled, Fernschreiber will use the current Sailfish OS notification sound for chats, which can be configured in the system settings.")
|
||||||
|
enabled: parent.enabled
|
||||||
|
automaticCheck: false
|
||||||
|
onClicked: {
|
||||||
|
appSettings.notificationSoundsEnabled = !checked
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,153 +30,183 @@ AccordionItem {
|
||||||
Column {
|
Column {
|
||||||
id: activeSessionsItem
|
id: activeSessionsItem
|
||||||
bottomPadding: Theme.paddingMedium
|
bottomPadding: Theme.paddingMedium
|
||||||
property variant activeSessions;
|
property variant activeSessions
|
||||||
property bool loaded : false;
|
property int inactiveSessionsTtlDays
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if (!activeSessions) {
|
if (!activeSessions) {
|
||||||
tdLibWrapper.getActiveSessions();
|
tdLibWrapper.getActiveSessions();
|
||||||
} else {
|
|
||||||
activeSessionsItem.loaded = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: tdLibWrapper
|
target: tdLibWrapper
|
||||||
onSessionsReceived: {
|
onSessionsReceived: {
|
||||||
activeSessionsItem.activeSessions = sessions;
|
activeSessionsItem.activeSessions = sessions
|
||||||
activeSessionsItem.loaded = true;
|
activeSessionsItem.inactiveSessionsTtlDays = inactive_session_ttl_days
|
||||||
}
|
}
|
||||||
onOkReceived: {
|
onOkReceived: {
|
||||||
if (request === "terminateSession") {
|
if (request === "terminateSession") {
|
||||||
appNotification.show(qsTr("Session was terminated"));
|
appNotification.show(qsTr("Session was terminated"));
|
||||||
activeSessionsItem.loaded = false;
|
|
||||||
tdLibWrapper.getActiveSessions();
|
tdLibWrapper.getActiveSessions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: sessionInformationLoader
|
|
||||||
active: tdLibWrapper.authorizationState === TelegramAPI.AuthorizationReady
|
active: tdLibWrapper.authorizationState === TelegramAPI.AuthorizationReady
|
||||||
width: parent.width
|
width: parent.width
|
||||||
sourceComponent: Component {
|
sourceComponent: Component {
|
||||||
SilicaListView {
|
Column {
|
||||||
id: activeSessionsListView
|
BusyIndicator {
|
||||||
width: parent.width
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
height: contentHeight
|
running: !activeSessionsListView.count && !activeSessionsItem.inactiveSessionsTtlDays
|
||||||
model: activeSessionsItem.activeSessions
|
size: BusyIndicatorSize.Medium
|
||||||
headerPositioning: ListView.OverlayHeader
|
visible: opacity > 0
|
||||||
header: Separator {
|
height: running ? implicitHeight : 0
|
||||||
width: parent.width
|
|
||||||
color: Theme.primaryColor
|
|
||||||
horizontalAlignment: Qt.AlignHCenter
|
|
||||||
}
|
}
|
||||||
delegate: ListItem {
|
|
||||||
id: activeSessionListItem
|
SilicaListView {
|
||||||
|
id: activeSessionsListView
|
||||||
width: parent.width
|
width: parent.width
|
||||||
contentHeight: activeSessionColumn.height + ( 2 * Theme.paddingMedium )
|
height: contentHeight
|
||||||
|
model: activeSessionsItem.activeSessions
|
||||||
menu: ContextMenu {
|
headerPositioning: ListView.OverlayHeader
|
||||||
hasContent: !modelData.is_current
|
header: Separator {
|
||||||
onHeightChanged: {
|
|
||||||
if (parent && flickable) {
|
|
||||||
// Make sure we are inside the screen area
|
|
||||||
var bottom = parent.mapToItem(flickable, x, y).y + height
|
|
||||||
if (bottom > flickable.height) {
|
|
||||||
flickable.contentY += bottom - flickable.height
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MenuItem {
|
|
||||||
onClicked: {
|
|
||||||
var sessionId = modelData.id;
|
|
||||||
Remorse.itemAction(activeSessionListItem, qsTr("Terminating session"), function() { tdLibWrapper.terminateSession(sessionId); });
|
|
||||||
}
|
|
||||||
text: qsTr("Terminate Session")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: activeSessionColumn
|
|
||||||
width: parent.width - ( 2 * Theme.horizontalPageMargin )
|
|
||||||
spacing: Theme.paddingSmall
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
|
|
||||||
Label {
|
|
||||||
width: parent.width
|
|
||||||
text: qsTr("This app")
|
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
|
||||||
font.bold: true
|
|
||||||
visible: modelData.is_current
|
|
||||||
color: Theme.highlightColor
|
|
||||||
anchors {
|
|
||||||
horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
|
||||||
width: parent.width
|
|
||||||
text: modelData.application_name + " " + modelData.application_version
|
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
|
||||||
font.bold: true
|
|
||||||
color: Theme.primaryColor
|
|
||||||
maximumLineCount: 1
|
|
||||||
elide: Text.ElideRight
|
|
||||||
anchors {
|
|
||||||
horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
|
||||||
width: parent.width
|
|
||||||
text: modelData.device_model + ", " + (modelData.platform + " " + modelData.system_version).trim()
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: Theme.primaryColor
|
|
||||||
maximumLineCount: 1
|
|
||||||
truncationMode: TruncationMode.Fade
|
|
||||||
anchors {
|
|
||||||
horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
|
||||||
width: parent.width
|
|
||||||
text: qsTr("IP address: %1, origin: %2").arg(modelData.ip).arg(modelData.country)
|
|
||||||
font.pixelSize: Theme.fontSizeExtraSmall
|
|
||||||
color: Theme.secondaryColor
|
|
||||||
maximumLineCount: 1
|
|
||||||
truncationMode: TruncationMode.Fade
|
|
||||||
anchors {
|
|
||||||
horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
|
||||||
width: parent.width
|
|
||||||
text: qsTr("Active since: %1, last online: %2").arg(Functions.getDateTimeTimepoint(modelData.log_in_date)).arg(Functions.getDateTimeElapsed(modelData.last_active_date))
|
|
||||||
font.pixelSize: Theme.fontSizeExtraSmall
|
|
||||||
color: Theme.primaryColor
|
|
||||||
maximumLineCount: 1
|
|
||||||
truncationMode: TruncationMode.Fade
|
|
||||||
anchors {
|
|
||||||
horizontalCenter: parent.horizontalCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Separator {
|
|
||||||
id: separator
|
|
||||||
anchors {
|
|
||||||
bottom: parent.bottom
|
|
||||||
}
|
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
color: Theme.primaryColor
|
color: Theme.primaryColor
|
||||||
horizontalAlignment: Qt.AlignHCenter
|
horizontalAlignment: Qt.AlignHCenter
|
||||||
|
visible: activeSessionsListView.count > 0
|
||||||
|
}
|
||||||
|
delegate: ListItem {
|
||||||
|
id: activeSessionListItem
|
||||||
|
width: parent.width
|
||||||
|
contentHeight: activeSessionColumn.height + ( 2 * Theme.paddingMedium )
|
||||||
|
|
||||||
|
menu: ContextMenu {
|
||||||
|
hasContent: !modelData.is_current
|
||||||
|
onHeightChanged: {
|
||||||
|
if (parent && flickable) {
|
||||||
|
// Make sure we are inside the screen area
|
||||||
|
var bottom = parent.mapToItem(flickable, x, y).y + height
|
||||||
|
if (bottom > flickable.height) {
|
||||||
|
flickable.contentY += bottom - flickable.height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
onClicked: {
|
||||||
|
var sessionId = modelData.id;
|
||||||
|
Remorse.itemAction(activeSessionListItem, qsTr("Terminating session"), function() { tdLibWrapper.terminateSession(sessionId); });
|
||||||
|
}
|
||||||
|
text: qsTr("Terminate Session")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: activeSessionColumn
|
||||||
|
width: parent.width - ( 2 * Theme.horizontalPageMargin )
|
||||||
|
spacing: Theme.paddingSmall
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|
||||||
|
Label {
|
||||||
|
width: parent.width
|
||||||
|
text: qsTr("This app")
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
font.bold: true
|
||||||
|
visible: modelData.is_current
|
||||||
|
color: Theme.highlightColor
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
width: parent.width
|
||||||
|
text: modelData.application_name + " " + modelData.application_version
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
font.bold: true
|
||||||
|
maximumLineCount: 1
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
width: parent.width
|
||||||
|
text: modelData.device_model + ", " + (modelData.platform + " " + modelData.system_version).trim()
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
maximumLineCount: 1
|
||||||
|
truncationMode: TruncationMode.Fade
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
width: parent.width
|
||||||
|
text: qsTr("Active since: %1, last online: %2").arg(Functions.getDateTimeTimepoint(modelData.log_in_date)).arg(Functions.getDateTimeElapsed(modelData.last_active_date))
|
||||||
|
font.pixelSize: Theme.fontSizeExtraSmall
|
||||||
|
maximumLineCount: 1
|
||||||
|
truncationMode: TruncationMode.Fade
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Separator {
|
||||||
|
anchors {
|
||||||
|
bottom: parent.bottom
|
||||||
|
}
|
||||||
|
|
||||||
|
width: parent.width
|
||||||
|
color: Theme.primaryColor
|
||||||
|
horizontalAlignment: Qt.AlignHCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ComboBox {
|
||||||
|
readonly property int ttl: activeSessionsItem.inactiveSessionsTtlDays
|
||||||
|
label: qsTr("Session Timeout")
|
||||||
|
description: qsTr("Inactive sessions will be terminated after this timeframe")
|
||||||
|
value: (currentItem && currentItem.text) ? currentItem.text : qsTr("%1 day(s)", "", ttl).arg(ttl)
|
||||||
|
visible: ttl > 0
|
||||||
|
menu: ContextMenu {
|
||||||
|
id: ttlMenu
|
||||||
|
MenuItem {
|
||||||
|
readonly property int days: 7
|
||||||
|
text: qsTr("1 week")
|
||||||
|
onClicked: tdLibWrapper.setInactiveSessionTtl(days)
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
readonly property int days: 30
|
||||||
|
text: qsTr("1 month")
|
||||||
|
onClicked: tdLibWrapper.setInactiveSessionTtl(days)
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
readonly property int days: 90
|
||||||
|
text: qsTr("3 months")
|
||||||
|
onClicked: tdLibWrapper.setInactiveSessionTtl(days)
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
readonly property int days: 180
|
||||||
|
text: qsTr("6 months")
|
||||||
|
onClicked: tdLibWrapper.setInactiveSessionTtl(days)
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
readonly property int days: 365
|
||||||
|
text: qsTr("1 year")
|
||||||
|
onClicked: tdLibWrapper.setInactiveSessionTtl(days)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: updateSelection()
|
||||||
|
|
||||||
|
onTtlChanged: updateSelection()
|
||||||
|
|
||||||
|
function updateSelection() {
|
||||||
|
var menuItems = ttlMenu.children
|
||||||
|
var n = menuItems.length
|
||||||
|
for (var i = 0; i < n; i++) {
|
||||||
|
if (menuItems[i].days === ttl) {
|
||||||
|
currentIndex = i
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentIndex = -1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ AccordionItem {
|
||||||
|
|
||||||
readonly property var userInformation: tdLibWrapper.getUserInformation()
|
readonly property var userInformation: tdLibWrapper.getUserInformation()
|
||||||
property bool uploadInProgress: false
|
property bool uploadInProgress: false
|
||||||
|
property bool contactSyncEnabled: false
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
tdLibWrapper.getUserProfilePhotos(userInformation.id, 100, 0);
|
tdLibWrapper.getUserProfilePhotos(userInformation.id, 100, 0);
|
||||||
|
@ -142,7 +143,7 @@ AccordionItem {
|
||||||
visible: true
|
visible: true
|
||||||
canEdit: true
|
canEdit: true
|
||||||
headerText: qsTr("Username", "user name of the logged-in profile - header")
|
headerText: qsTr("Username", "user name of the logged-in profile - header")
|
||||||
text: userInformation.username
|
text: userInformation.usernames.editable_username
|
||||||
width: parent.columnWidth
|
width: parent.columnWidth
|
||||||
headerLeftAligned: true
|
headerLeftAligned: true
|
||||||
|
|
||||||
|
@ -151,6 +152,49 @@ AccordionItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: contactSyncItem
|
||||||
|
width: parent.width
|
||||||
|
height: syncInProgress ? ( syncContactsBusyIndicator.height + Theme.paddingMedium ) : ( syncContactsButton.height + Theme.paddingMedium )
|
||||||
|
visible: accordionContent.contactSyncEnabled
|
||||||
|
|
||||||
|
property bool syncInProgress: false
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: contactSyncLoader.item
|
||||||
|
onSyncError: {
|
||||||
|
contactSyncItem.syncInProgress = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: tdLibWrapper
|
||||||
|
onContactsImported: {
|
||||||
|
appNotification.show(qsTr("Contacts successfully synchronized with Telegram."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
id: syncContactsButton
|
||||||
|
text: qsTr("Synchronize Contacts with Telegram")
|
||||||
|
visible: !contactSyncItem.syncInProgress
|
||||||
|
anchors {
|
||||||
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
contactSyncLoader.item.synchronize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BusyIndicator {
|
||||||
|
id: syncContactsBusyIndicator
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
running: contactSyncItem.syncInProgress
|
||||||
|
size: BusyIndicatorSize.Small
|
||||||
|
visible: running
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SectionHeader {
|
SectionHeader {
|
||||||
|
@ -247,6 +291,15 @@ AccordionItem {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: contactSyncLoader
|
||||||
|
source: "../ContactSync.qml"
|
||||||
|
active: true
|
||||||
|
onLoaded: {
|
||||||
|
accordionContent.contactSyncEnabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: imagePickerPage
|
id: imagePickerPage
|
||||||
ImagePickerPage {
|
ImagePickerPage {
|
||||||
|
|
0
qml/js/emoji/1f6dd.svg
Executable file → Normal file
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
0
qml/js/emoji/1f6de.svg
Executable file → Normal file
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
0
qml/js/emoji/1f6df.svg
Executable file → Normal file
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
0
qml/js/emoji/1f7f0.svg
Executable file → Normal file
Before Width: | Height: | Size: 221 B After Width: | Height: | Size: 221 B |
0
qml/js/emoji/1f91d-1f3fb.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1f91d-1f3fc.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1f91d-1f3fd.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1f91d-1f3fe.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1f91d-1f3ff.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1f979.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1f9cc.svg
Executable file → Normal file
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
0
qml/js/emoji/1fa7b.svg
Executable file → Normal file
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
0
qml/js/emoji/1fa7c.svg
Executable file → Normal file
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
0
qml/js/emoji/1faa9.svg
Executable file → Normal file
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
0
qml/js/emoji/1faaa.svg
Executable file → Normal file
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
0
qml/js/emoji/1faab.svg
Executable file → Normal file
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
0
qml/js/emoji/1faac.svg
Executable file → Normal file
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
0
qml/js/emoji/1fab7.svg
Executable file → Normal file
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
0
qml/js/emoji/1fab8.svg
Executable file → Normal file
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
0
qml/js/emoji/1fab9.svg
Executable file → Normal file
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
0
qml/js/emoji/1faba.svg
Executable file → Normal file
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
0
qml/js/emoji/1fac3-1f3fb.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
0
qml/js/emoji/1fac3-1f3fc.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
0
qml/js/emoji/1fac3-1f3fd.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
0
qml/js/emoji/1fac3-1f3fe.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
0
qml/js/emoji/1fac3-1f3ff.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
0
qml/js/emoji/1fac3.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
0
qml/js/emoji/1fac4-1f3fb.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
0
qml/js/emoji/1fac4-1f3fc.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
0
qml/js/emoji/1fac4-1f3fd.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
0
qml/js/emoji/1fac4-1f3fe.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
0
qml/js/emoji/1fac4-1f3ff.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
0
qml/js/emoji/1fac4.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
0
qml/js/emoji/1fac5-1f3fb.svg
Executable file → Normal file
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
0
qml/js/emoji/1fac5-1f3fc.svg
Executable file → Normal file
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
0
qml/js/emoji/1fac5-1f3fd.svg
Executable file → Normal file
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
0
qml/js/emoji/1fac5-1f3fe.svg
Executable file → Normal file
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
0
qml/js/emoji/1fac5-1f3ff.svg
Executable file → Normal file
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
0
qml/js/emoji/1fac5.svg
Executable file → Normal file
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
0
qml/js/emoji/1fad7.svg
Executable file → Normal file
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
0
qml/js/emoji/1fad8.svg
Executable file → Normal file
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
0
qml/js/emoji/1fad9.svg
Executable file → Normal file
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
0
qml/js/emoji/1fae0.svg
Executable file → Normal file
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
0
qml/js/emoji/1fae1.svg
Executable file → Normal file
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
0
qml/js/emoji/1fae2.svg
Executable file → Normal file
Before Width: | Height: | Size: 971 B After Width: | Height: | Size: 971 B |
0
qml/js/emoji/1fae3.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
0
qml/js/emoji/1fae4.svg
Executable file → Normal file
Before Width: | Height: | Size: 422 B After Width: | Height: | Size: 422 B |
0
qml/js/emoji/1fae5.svg
Executable file → Normal file
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
0
qml/js/emoji/1fae6.svg
Executable file → Normal file
Before Width: | Height: | Size: 689 B After Width: | Height: | Size: 689 B |
0
qml/js/emoji/1fae7.svg
Executable file → Normal file
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
0
qml/js/emoji/1faf0-1f3fb.svg
Executable file → Normal file
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
0
qml/js/emoji/1faf0-1f3fc.svg
Executable file → Normal file
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
0
qml/js/emoji/1faf0-1f3fd.svg
Executable file → Normal file
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
0
qml/js/emoji/1faf0-1f3fe.svg
Executable file → Normal file
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
0
qml/js/emoji/1faf0-1f3ff.svg
Executable file → Normal file
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
0
qml/js/emoji/1faf0.svg
Executable file → Normal file
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
0
qml/js/emoji/1faf1-1f3fb-200d-1faf2-1f3fc.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1faf1-1f3fb-200d-1faf2-1f3fd.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1faf1-1f3fb-200d-1faf2-1f3fe.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1faf1-1f3fb-200d-1faf2-1f3ff.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1faf1-1f3fb.svg
Executable file → Normal file
Before Width: | Height: | Size: 741 B After Width: | Height: | Size: 741 B |
0
qml/js/emoji/1faf1-1f3fc-200d-1faf2-1f3fb.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1faf1-1f3fc-200d-1faf2-1f3fd.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1faf1-1f3fc-200d-1faf2-1f3fe.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1faf1-1f3fc-200d-1faf2-1f3ff.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1faf1-1f3fc.svg
Executable file → Normal file
Before Width: | Height: | Size: 741 B After Width: | Height: | Size: 741 B |
0
qml/js/emoji/1faf1-1f3fd-200d-1faf2-1f3fb.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1faf1-1f3fd-200d-1faf2-1f3fc.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1faf1-1f3fd-200d-1faf2-1f3fe.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1faf1-1f3fd-200d-1faf2-1f3ff.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1faf1-1f3fd.svg
Executable file → Normal file
Before Width: | Height: | Size: 741 B After Width: | Height: | Size: 741 B |
0
qml/js/emoji/1faf1-1f3fe-200d-1faf2-1f3fb.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1faf1-1f3fe-200d-1faf2-1f3fc.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1faf1-1f3fe-200d-1faf2-1f3fd.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1faf1-1f3fe-200d-1faf2-1f3ff.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1faf1-1f3fe.svg
Executable file → Normal file
Before Width: | Height: | Size: 741 B After Width: | Height: | Size: 741 B |
0
qml/js/emoji/1faf1-1f3ff-200d-1faf2-1f3fb.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1faf1-1f3ff-200d-1faf2-1f3fc.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1faf1-1f3ff-200d-1faf2-1f3fd.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
0
qml/js/emoji/1faf1-1f3ff-200d-1faf2-1f3fe.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |