Compare commits

..

88 commits

Author SHA1 Message Date
Sebastian Wolf
0236586e44 Switch to gh tool for release creation, see https://github.com/actions/runner-images/issues/8362 2023-12-03 23:52:21 +03:00
Sebastian Wolf
e13c7ae68c Prepare 0.17 release 2023-12-03 23:52:19 +03:00
Sebastian Wolf
1d68123ea1 Restore content width in landscape as per discussion in #540 2023-12-03 23:52:06 +03:00
Slava Monich
cf7b706582 Tweaked the logic of moving reactions into the view (#543)
There's no need to reposition list items if reactions bar are already
fully visible.
2023-12-03 23:50:55 +03:00
free software
c42d030d02 Update harbour-fernschreiber-es.ts (#542) 2023-12-03 23:50:55 +03:00
Sebastian Wolf
edfce9b492 Highlight message that was jumped to 2023-12-03 23:50:55 +03:00
mbarashkov
e5d1ecd9f3 Jump to post from quote (#538)
* Jump to post from quote

* Add a setting to go to quoted message.

---------

Co-authored-by: Mikhail Barashkov <git@mbarashkov.ru>
2023-12-03 23:50:23 +03:00
Sebastian Wolf
42a7813776 Not only tablets have widescreen ;) 2023-12-03 23:50:21 +03:00
mbarashkov
627faba0db Improve chat UI on tablets by making messages narrower and limiting content items width as well. (#540)
Co-authored-by: Mikhail Barashkov <git@mbarashkov.ru>
2023-12-03 23:49:14 +03:00
Slava Monich
a4ebaf52f5 Fix broken signal-slot connection (#541)
QObject::connect: No such signal TDLibWrapper::chatAvailableReactionsUpdated(qlonglong, QString) in src/chatlistmodel.cpp:410
2023-12-03 23:46:48 +03:00
Sebastian Wolf
660fe527f2 Handle event updateChatAvailableReactions 2023-12-03 23:46:46 +03:00
Sebastian Wolf
1a0ed7f298 Only one star per list, restore users in poll results 2023-12-03 23:46:30 +03:00
062f5d3811 Merge pull request 'upstream_changes_251123' (#14) from upstream_changes_251123 into master
Reviewed-on: #14
2023-11-25 13:50:00 +03:00
034c70542f Update build number 2023-11-25 13:49:08 +03:00
Patrick Hervieux
ef244c3319 Update French translation (#532)
Co-authored-by: Patrick Hervieux <patrick.hervieux+git@pherjung.ch>
2023-11-25 13:34:26 +03:00
free software
556505894c Update harbour-fernschreiber-es.ts (#531) 2023-11-25 13:34:11 +03:00
Sebastian Wolf
7c63ad66f9 Interaction hint for new reactions behavior 2023-11-25 13:33:45 +03:00
Sebastian Wolf
26772a48eb Show reactions on double-click 2023-11-25 13:33:13 +03:00
Slava Monich
2ded14deda Added "unread mention" indicator to the chat list (#530)
It's displayed in place of the "unread reaction" indicator. In case
if there are both unread mentions and reactions, "unread mention"
takes precedence.
2023-11-25 13:31:50 +03:00
free software
465c082328 Update harbour-fernschreiber-es.ts (#529)
* Update harbour-fernschreiber-es.ts

* Update harbour-fernschreiber-es.ts
2023-11-25 13:31:35 +03:00
Slava Monich
25e6660e8e Updated Russian translation (#528) 2023-11-25 13:31:25 +03:00
f58afe92cb Merge pull request 'upstream_changes' (#13) from upstream_changes into master
Reviewed-on: #13
2023-11-21 14:24:05 +03:00
2b3ca0dff9 Update gitignore 2023-11-21 14:23:24 +03:00
Sebastian Wolf
1e88a31f90 Display reactions on last message again 2023-11-21 14:18:20 +03:00
Sebastian Wolf
026d32c92a Restore search in chats 2023-11-21 14:18:20 +03:00
Sebastian Wolf
a28b9df6b5 Minor tweaks for the new session timout setting 2023-11-21 14:18:12 +03:00
d2bde99e1f Merge pull request 'Revert executable rename' (#12) from revert_executable_rename into master
Reviewed-on: #12
2023-11-20 22:31:56 +03:00
f8ffedb5db Revert executable rename 2023-11-20 19:31:56 +00:00
4b7d17c02f Merge pull request 'upstream_changes' (#11) from upstream_changes into master
Reviewed-on: #11
2023-11-20 00:54:47 +03:00
0ae98f96b5 Release version ++ 2023-11-19 21:54:39 +00:00
Slava Monich
fb3d314ee2 Added UI for configuring session inactivity timeout (#527) 2023-11-20 00:50:41 +03:00
Sebastian Wolf
b032b32db1 More places affected by new username handling 2023-11-20 00:50:37 +03:00
Sebastian Wolf
63f4b37655 Hide unsupported emojis for reactions 2023-11-20 00:49:35 +03:00
Sebastian Wolf
bdc0423bf3 Make replies backward-compatible again 2023-11-20 00:49:12 +03:00
749f05816c Merge pull request 'adapt_to_changes_in_tdlib' (#10) from adapt_to_changes_in_tdlib into master
Reviewed-on: #10
2023-11-19 16:35:16 +03:00
06ebe95309 Fix some validator warnings 2023-11-19 16:35:45 +03:00
Sebastian Wolf
40ec4b0968 Fix chat permissions handling 2023-11-19 16:16:46 +03:00
Slava Monich
c4c9dc83c0 Tweaked notification feedback settings UI (#526) 2023-11-19 16:16:36 +03:00
9a37db94ae Update tdlib headers 2023-11-19 16:11:29 +03:00
Sebastian Wolf
0ba3a8cd7f Trouble with usernames 2023-11-19 12:23:42 +03:00
Sebastian Wolf
0aeaf50c92 Some minor adjustments 2023-11-19 12:23:23 +03:00
Johannes Bachmann
a9947ff9f7 Always append last message content to notifications (#514)
* always append last message content to notifications

* make "always show notification" configurable

* add unfinished translations

* Fix spacing if no sender is printed
2023-11-19 12:22:22 +03:00
Peter G
c7324c020b Add option to suppress notification previews (#521)
* Add Switch in Settings

* Don't set notification preview body

* Support the setting in appSettings

* fixup! Add Switch in Settings

* Just show message count

* Also show only when notifications are enabled at all

---------

Co-authored-by: nephros <nemo@pgxperiiia10>
2023-11-19 12:22:13 +03:00
Peter G
46419b0960 Highlight unread Converstations (#513)
* Highlight unread conversations

See: #512

* make highlighting configurable

* more verbose variable names

* remove the rectangle gain, it is too annoying

* respect the setting

---------

Co-authored-by: nephros <nemo@pgxperiiia10>
2023-11-19 12:22:04 +03:00
Slava Monich
c1c8729023 Adapt to changes in reply message info (#525)
1.8.14:
https://github.com/tdlib/td/commit/fa94aba

1.8.21:
https://github.com/tdlib/td/commit/811a7c6
https://github.com/tdlib/td/commit/5216ea1
2023-11-19 12:21:17 +03:00
Sebastian Wolf
9bcc9ab690 Only expect chat partner information in private chats 2023-11-19 12:01:42 +03:00
Slava Monich
0b6a2db2f1 Adapt to changes in TdLib (#524)
* Adapt setTdlibParameters for TdLib > 1.8.5

For some reason tdlibParameters were inlined between 1.8.5 and 1.8.6
See https://github.com/tdlib/td/commit/f6a2ecd

* sponsoredMessage => sponsoredMessages in TdLib 1.8.8

See https://github.com/tdlib/td/commit/ec1310a

* Support another variant of messageReaction

The reaction field has changed from string to ReactionType somewhere
between 1.8.5 and 1.8.6

See https://github.com/tdlib/td/commit/b14708f

* Add support for new message reactions API

It has changed between 1.8.5 and 1.8.6

https://github.com/tdlib/td/commit/b14708f (ReactionType)
https://github.com/tdlib/td/commit/0b8e143 (ChatAvailableReactions)
https://github.com/tdlib/td/commit/6b2f6b4 (addMessageReaction)
https://github.com/tdlib/td/commit/d29d367 (updateActiveEmojiReactions)

etc.

* Highlight chosen reaction

* Support username in the new format

username attribute has been replaced with usernames in 1.8.8 and
now looks like this:

    "usernames": {
        "@type": "usernames",
        "active_usernames": [
            "whatever"
        ],
        "disabled_usernames": [
        ],
        "editable_username": "whatever"
    }

See https://github.com/tdlib/td/commit/897032e

* Support new reply_to message attribute

Since 1.8.15 it replaces reply_to_message_id and reply_in_chat_id.
Looks like this:

    "reply_to": {
        "@type": "messageReplyToMessage",
        "chat_id": -1001234567890,
        "is_quote_manual": false,
        "message_id": 234567890,
        "origin_send_date": 0
    },

See https://github.com/tdlib/td/commit/6116573

* Added support for MessageOrigin values

All of a sudden MessageForwardOrigin has been renamed into MessageOrigin
in TdLib 1.8.20 just because why not:

https://github.com/tdlib/td/commit/10c9e40
2023-11-19 12:01:27 +03:00
61a04b034a Merge pull request 'improve_unread_ballons' (#9) from sprainbrains/harbour-fernschreiber:improve_unread_ballons into master
Reviewed-on: #9
2023-11-18 22:38:58 +03:00
jgibbon
ca42a5e7e0 Add specific unread info for higher counts of unread messages 2023-11-18 22:38:44 +03:00
400cda8dcd Merge pull request 'origin_merged' (#8) from sprainbrains/harbour-fernschreiber:origin_merged into master
Reviewed-on: #8
2023-11-18 22:36:19 +03:00
fe50ead4ee Merged 2023-10-14 00:21:35 +03:00
f1717cbd29 Merge remote-tracking branch 'origin_sailfish/master' into origin_merged 2023-10-14 00:19:37 +03:00
Sebastian Wolf
5394fde136
Update chat list more reliably 2023-08-08 22:50:04 +02:00
1ad324aa23 Merge pull request 'Fixed size of background circle for Unread messages' (#7) from sprainbrains/harbour-fernschreiber:unread_message_background_fix into master
Reviewed-on: #7
2023-08-07 14:17:38 +03:00
59b99a0a28 Fixed size of background circle for Unread messages 2023-08-03 15:02:34 +03:00
12dbac7480 build number ++ 2023-07-12 01:31:25 +03:00
258466beeb Merge pull request 'remove own id from messages title' (#6) from remove_title_on_own_messages_4 into master
Reviewed-on: #6
2023-07-12 01:28:18 +03:00
656e8ccfe7 left margin for own messages in private chats 2023-07-12 01:27:18 +03:00
22930628ae wide message without left margin 2023-07-12 01:12:53 +03:00
0d26167ee3 remove left margin on own messages 2023-07-10 01:29:00 +03:00
723105382d remove own id from messages title 2023-07-09 15:16:06 +03:00
c9773fb5ab Merge pull request 'fix_own_message_ui_3' (#4) from fix_own_message_ui_3 into master
Reviewed-on: #4
2023-07-09 14:43:42 +03:00
51227c1323 forgot desktop file 2023-07-09 14:43:18 +03:00
aac7fd7328 remowed right align on own messages 2023-07-09 14:43:18 +03:00
f3dd33c4ca removed sailfish contact sync support 2023-07-09 14:43:18 +03:00
Sebastian Wolf
83f0c54f8b Switch to icon-m-video as placeholder 2023-07-09 14:43:18 +03:00
71d1831ed3 Merge pull request 'aurora_build' (#2) from aurora_build into master
Reviewed-on: #2
2023-07-08 10:32:41 +03:00
Sebastian Wolf
29621b739a
Switch to icon-m-video as placeholder 2023-06-20 09:46:01 +02:00
Denis Fedoseev
0b91948141 project build settings were modified 2023-04-04 10:54:18 +03:00
Denis Fedoseev
9d37635500 мелкие фиксы для валидатора 2023-04-04 10:53:39 +03:00
okruhliak
df6322c712 Update harbour-fernschreiber-sk.ts 2023-02-27 21:27:26 +01:00
free software
5de2e94f32 Update harbour-fernschreiber-es.ts 2023-02-27 11:57:52 +01:00
Rustem Abzalov
85732c6fbc Update harbour-fernschreiber-ru.ts 2023-02-27 11:56:18 +01:00
Sebastian Wolf
a7ab0ed33a
Prepare support for contact sync with SFOS 4.5 2023-02-05 20:17:06 +01:00
Slava Monich
f152bbeb5b
Always show user or group id on the info page (#511)
And copy it to the clipboard on tap.
2023-02-05 15:52:06 +01:00
Peter G
b469135877
improve message when search yields no results (#507)
Co-authored-by: nephros <nemo@pgxperiiia10>
2023-02-05 15:41:04 +01:00
Sebastian Wolf
a9b6bf5817
React to network configuration changes, fixes #504 2022-07-10 22:39:52 +02:00
Sebastian Wolf
f91eb7936a
Release 0.16 2022-06-12 17:39:15 +02:00
Sebastian Wolf
5465d454f5
Pre-allocate vertical space for reactions 2022-06-08 23:13:34 +02:00
Sebastian Wolf
227c9146f2
Try Auto-Build with 4.4.0.58 2022-06-07 23:27:36 +02:00
Sebastian Wolf
ec2a1cf398
Changelog for 0.16 2022-06-07 22:51:39 +02:00
Sebastian Wolf
0a76ede35a
Only display reactions on chat list for now 2022-06-06 23:06:57 +02:00
Sebastian Wolf
99910a3f3a
Bring unread mention/reactions to chat list 2022-06-06 15:55:21 +02:00
Sebastian Wolf
9ff7a8371d
README: build instructions | Try to avoid ghost chats in main list 2022-05-30 23:22:57 +02:00
Sebastian Wolf
fa8a77a265
Next version will be 0.16 2022-05-29 22:17:37 +02:00
Sebastian Wolf
03fad6da6d
Reactions only for current message, restore animated stickers 2022-05-29 22:10:30 +02:00
Sebastian Wolf
0cc6f959fc
Option to mark all chat reactions as read 2022-05-24 21:19:15 +02:00
Sebastian Wolf
033f96b366
Display reactions to message 2022-05-23 23:33:17 +02:00
176 changed files with 20241 additions and 2844 deletions

View file

@ -53,20 +53,20 @@ jobs:
id: build_armv7hl id: build_armv7hl
uses: coderus/github-sfos-build@master uses: coderus/github-sfos-build@master
with: with:
release: 4.2.0.21 release: 4.4.0.58
- name: Build i486 - name: Build i486
id: build_i486 id: build_i486
uses: coderus/github-sfos-build@master uses: coderus/github-sfos-build@master
with: with:
release: 4.2.0.21 release: 4.4.0.58
arch: i486 arch: i486
- name: Build aarch64 - name: Build aarch64
id: build_aarch64 id: build_aarch64
uses: coderus/github-sfos-build@master uses: coderus/github-sfos-build@master
with: with:
release: 4.2.0.21 release: 4.4.0.58
arch: aarch64 arch: aarch64
- name: Upload build result - name: Upload build result
@ -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
View file

@ -53,3 +53,6 @@ compile_commands.json
# TDLib API Secrets # TDLib API Secrets
tdlibsecrets.h tdlibsecrets.h
#Convinience scripts
*.sh

View file

@ -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,16 +52,17 @@ 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.7](https://github.com/tdlib/td) 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.
In case you want to use the same codebase which was used to compile the library that is shipped with Fernschreiber, please [check out the fork](https://github.com/Wunderfitz/td), be sure to use the branch `fernschreiber` and compile these sources using the following commands (be sure to have the Sailfish OS build engine running): In case you want to use the same codebase which was used to compile the library that is shipped with Fernschreiber, please [check out the fork](https://github.com/Wunderfitz/td), be sure to use the branch `fernschreiber` and compile these sources using the following commands (be sure to have the Sailfish OS build engine running):
- `alias sfdk=~/SailfishOS/bin/sfdk` - `alias sfdk=~/SailfishOS/bin/sfdk`
- `sfdk config target=SailfishOS-3.3.0.16-armv7hl` (this compiles the sources on SFOS 3.3 and ARM - the target needs to be adjusted according to the running SDK engine and the platform) - `sfdk config target=SailfishOS-4.4.0.58-armv7hl` (this compiles the sources on SFOS 4.4 and ARM - the target needs to be adjusted according to the running SDK engine and the platform)
- `mkdir build` - `mkdir build`
- `cd build` - `cd build`
- `sfdk build-init`
- `sfdk build-shell cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=../tdlib -DTD_ENABLE_LTO=ON ..` (in case of compilation issues, try removing the flag `-DTD_ENABLE_LTO=ON`) - `sfdk build-shell cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=../tdlib -DTD_ENABLE_LTO=ON ..` (in case of compilation issues, try removing the flag `-DTD_ENABLE_LTO=ON`)
- `sfdk build-shell cmake --build . --target install` - `sfdk build-shell cmake --build . --target install`

View file

@ -1,47 +0,0 @@
engine="docker exec -w $(pwd) --user mersdk aurora-os-build-engine"
targets=`${engine} sb2-config -l|grep -v default`
version=`grep -E "Version" $(pwd)/rpm/harbour-fernschreiber.spec|sed "s/Version: \+//g"`
release=`grep -E "Release:" $(pwd)/rpm/harbour-fernschreiber.spec|sed "s/Release: \+//g"`
for each in key cert; do
if [ -f `pwd`/regular_${each}.pem ]; then
echo "Found a regular_${each}.pem file: OK"
continue;
fi
echo -n "Downloading regular_${each}.pem for singing RPM for AuroraOS: "
curl https://community.omprussia.ru/documentation/files/doc/regular_${each}.pem -o regular_${each}.pem &> /dev/null
if [ $? -eq 0 ]; then
echo "OK"
else
echo "FAIL"
echo "Cant download regular_${each}.pem: https://community.omprussia.ru/documentation/files/doc/regular_${each}.pem"
exit 1
fi
done
for target in ${targets}; do
echo "Build for ${target}"
arch=${target##*-}
echo "Detected arch: ${arch}"
${engine} mb2 -t ${target} build
[ $? -ne 0 ] && exit 1
package_name="harbour-fernschreiber-${version}-${release}.${arch}.rpm"
echo -n "Signing RPM ${package_name}: "
temp_output="$(${engine} sb2 -t ${target} rpmsign-external sign --key `pwd`/regular_key.pem --cert `pwd`/regular_cert.pem `pwd`/RPMS/${package_name} 2>&1)"
if [ $? -ne 0 ]; then
echo "FAIL"
echo "${temp_output}"
exit 1
else
echo "OK"
fi
echo -n "Validate RPM ${package_name}: "
temp_output="$( ${engine} sb2 -t ${target} rpm-validator -p regular `pwd`/RPMS/${package_name} 2>&1 )"
if [ $? -ne 0 ]; then
echo "FAIL"
echo "${temp_output}"
exit 1
else
echo "OK"
fi
done

View file

@ -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

View file

@ -24,6 +24,8 @@ PhotoTextsListItem {
// message date // message date
tertiaryText.text: showDraft ? Functions.getDateTimeElapsed(draft_message_date) : ( last_message_date ? ( last_message_date.length === 0 ? "" : Functions.getDateTimeElapsed(last_message_date) + Emoji.emojify(last_message_status, tertiaryText.font.pixelSize) ) : "" ) tertiaryText.text: showDraft ? Functions.getDateTimeElapsed(draft_message_date) : ( last_message_date ? ( last_message_date.length === 0 ? "" : Functions.getDateTimeElapsed(last_message_date) + Emoji.emojify(last_message_status, tertiaryText.font.pixelSize) ) : "" )
unreadCount: unread_count unreadCount: unread_count
unreadReactionCount: unread_reaction_count
unreadMentionCount: unread_mention_count
isSecret: ( chat_type === TelegramAPI.ChatTypeSecret ) isSecret: ( chat_type === TelegramAPI.ChatTypeSecret )
isMarkedAsUnread: is_marked_as_unread isMarkedAsUnread: is_marked_as_unread
isPinned: is_pinned isPinned: is_pinned
@ -48,16 +50,18 @@ PhotoTextsListItem {
sourceComponent: Component { sourceComponent: Component {
ContextMenu { ContextMenu {
MenuItem { MenuItem {
visible: unread_count > 0 visible: unread_count > 0 || unread_reaction_count > 0 || unread_mention_count > 0
onClicked: { onClicked: {
tdLibWrapper.viewMessage(chat_id, display.last_message.id, true); tdLibWrapper.viewMessage(chat_id, display.last_message.id, true);
tdLibWrapper.readAllChatMentions(chat_id);
tdLibWrapper.readAllChatReactions(chat_id);
tdLibWrapper.toggleChatIsMarkedAsUnread(chat_id, false); tdLibWrapper.toggleChatIsMarkedAsUnread(chat_id, false);
} }
text: qsTr("Mark all messages as read") text: qsTr("Mark all messages as read")
} }
MenuItem { MenuItem {
visible: unread_count === 0 visible: unread_count === 0 && unread_reaction_count === 0 && unread_mention_count === 0
onClicked: { onClicked: {
tdLibWrapper.toggleChatIsMarkedAsUnread(chat_id, !is_marked_as_unread); tdLibWrapper.toggleChatIsMarkedAsUnread(chat_id, !is_marked_as_unread);
} }

View 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
// }
}

View file

@ -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

View file

@ -32,12 +32,13 @@ ListItem {
property int messageIndex property int messageIndex
property int messageViewCount property int messageViewCount
property var myMessage property var myMessage
property var reactions
property bool canReplyToMessage property bool canReplyToMessage
readonly property bool isAnonymous: myMessage.sender_id["@type"] === "messageSenderChat" readonly property bool isAnonymous: myMessage.sender_id["@type"] === "messageSenderChat"
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
@ -46,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
@ -63,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()
@ -93,6 +96,43 @@ ListItem {
} }
} }
function getInteractionText(viewCount, reactions, size, highlightColor) {
var interactionText = "";
if (viewCount > 0) {
interactionText = Emoji.emojify("👁️ ", size) + Functions.getShortenedCount(viewCount);
}
for (var i = 0; i < reactions.length; i++) {
var reaction = reactions[i]
var reactionText = reaction.reaction ? reaction.reaction : (reaction.type && reaction.type.emoji) ? reaction.type.emoji : ""
if (reactionText) {
interactionText += ( "&nbsp;" + 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;
}
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);
@ -110,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()
@ -139,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
@ -239,8 +312,13 @@ ListItem {
messageListItem.messageReactions = reactions; messageListItem.messageReactions = reactions;
showItemCompletelyTimer.requestedIndex = index; showItemCompletelyTimer.requestedIndex = index;
showItemCompletelyTimer.start(); showItemCompletelyTimer.start();
} else {
messageListItem.messageReactions = null;
} }
} }
onReactionsUpdated: {
chatReactions = tdLibWrapper.getChatReactions(page.chatInformation.id);
}
} }
Timer { Timer {
@ -253,15 +331,33 @@ 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();
@ -305,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
@ -346,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")
@ -381,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)
@ -423,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) {
chatPage.showMessage(messageInReplyToRow.inReplyToMessage.id, true)
} else {
messageOverlayLoader.active = true messageOverlayLoader.active = true
messageOverlayLoader.overlayMessage = messageInReplyToRow.inReplyToMessage
}
} }
} }
onPressAndHold: { onPressAndHold: {
@ -450,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);
@ -535,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 {
@ -549,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)
} }
@ -590,7 +693,6 @@ ListItem {
color: messageListItem.isOwnMessage ? Theme.secondaryHighlightColor : Theme.secondaryColor color: messageListItem.isOwnMessage ? Theme.secondaryHighlightColor : Theme.secondaryColor
horizontalAlignment: messageListItem.textAlign horizontalAlignment: messageListItem.textAlign
text: getMessageStatusText(myMessage, index, chatView.lastReadSentIndex, messageDateText.useElapsed) text: getMessageStatusText(myMessage, index, chatView.lastReadSentIndex, messageDateText.useElapsed)
rightPadding: interactionLoader.active ? interactionLoader.width : 0
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
enabled: !messageListItem.precalculatedValues.pageIsSelecting enabled: !messageListItem.precalculatedValues.pageIsSelecting
@ -599,35 +701,27 @@ ListItem {
messageDateText.text = getMessageStatusText(myMessage, index, chatView.lastReadSentIndex, messageDateText.useElapsed); messageDateText.text = getMessageStatusText(myMessage, index, chatView.lastReadSentIndex, messageDateText.useElapsed);
} }
} }
}
Loader { Loader {
id: interactionLoader id: interactionLoader
height: parent.height width: parent.width
anchors.right: parent.right
asynchronous: true asynchronous: true
active: chatPage.isChannel && messageViewCount active: ( chatPage.isChannel && messageViewCount > 0 ) || reactions.length > 0
height: ( ( chatPage.isChannel && messageViewCount > 0 ) || reactions.length > 0 ) ? ( Theme.fontSizeExtraSmall + Theme.paddingSmall ) : 0
sourceComponent: Component { sourceComponent: Component {
Label { Label {
text: Functions.getShortenedCount(messageViewCount) text: getInteractionText(messageViewCount, reactions, font.pixelSize, Theme.highlightColor)
leftPadding: Theme.iconSizeSmall width: parent.width
font.pixelSize: Theme.fontSizeTiny font.pixelSize: Theme.fontSizeTiny
color: Theme.secondaryColor color: messageListItem.isOwnMessage ? Theme.secondaryHighlightColor : Theme.secondaryColor
Icon { horizontalAlignment: messageListItem.textAlign
anchors.verticalCenter: parent.verticalCenter textFormat: Text.StyledText
width: Theme.iconSizeExtraSmall maximumLineCount: 1
height: Theme.iconSizeExtraSmall elide: Text.ElideRight
opacity: 0.6
source: "../../images/icon-s-eye.svg"
sourceSize {
width: Theme.iconSizeExtraSmall
height: Theme.iconSizeExtraSmall
} }
} }
} }
}
}
}
} }
@ -669,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
} }
@ -678,7 +772,7 @@ ListItem {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {
Debug.log("Reaction clicked: " + modelData); tdLibWrapper.setMessageReaction(messageListItem.chatId, messageListItem.messageId, modelData);
messageListItem.messageReactions = null; messageListItem.messageReactions = null;
} }
} }

View file

@ -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);

View file

@ -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();
} }

View file

@ -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
@ -11,6 +12,8 @@ ListItem {
property alias tertiaryText: tertiaryText //usually last message date property alias tertiaryText: tertiaryText //usually last message date
property int unreadCount: 0 property int unreadCount: 0
property int unreadMentionCount: 0
property int unreadReactionCount: 0
property bool isSecret: false property bool isSecret: false
property bool isVerified: false property bool isVerified: false
property bool isMarkedAsUnread: false property bool isMarkedAsUnread: false
@ -85,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
@ -101,10 +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 {
color: isMuted ? ((Theme.colorScheme === Theme.DarkOnLight) ? "lightgray" : "dimgray") : Theme.highlightBackgroundColor
width: Theme.fontSizeLarge
height: Theme.fontSizeLarge
anchors.right: parent.right
anchors.top: parent.top
radius: parent.width / 2
visible: chatListViewItem.unreadReactionCount > 0 || chatListViewItem.unreadMentionCount > 0
Icon {
source: "image://theme/icon-s-favorite"
height: Theme.iconSizeExtraSmall
width: Theme.iconSizeExtraSmall
highlighted: chatListViewItem.highlighted
anchors.centerIn: parent
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 {
@ -127,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 {

View file

@ -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"
}) })
} }

View file

@ -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")

View file

@ -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);

View file

@ -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.is_animated && 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

View file

@ -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
} }

View file

@ -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
} }

View file

@ -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
width: 1
height: 1
}
Column {
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
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 automaticCheck: false
onClicked: { onClicked: {
appSettings.notificationTurnsDisplayOn = !checked appSettings.notificationTurnsDisplayOn = !checked
} }
Behavior on height { SmoothedAnimation { duration: 200 } }
} }
TextSwitch { TextSwitch {
width: parent.columnWidth
checked: appSettings.notificationSoundsEnabled && enabled checked: appSettings.notificationSoundsEnabled && enabled
text: qsTr("Enable notification sounds") 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.") 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: parent.enabled
height: enabled ? implicitHeight: 0
clip: height < implicitHeight
visible: height > 0
automaticCheck: false automaticCheck: false
onClicked: { onClicked: {
appSettings.notificationSoundsEnabled = !checked appSettings.notificationSoundsEnabled = !checked
} }
Behavior on height { SmoothedAnimation { duration: 200 } } }
} }
} }
} }

View file

@ -30,37 +30,42 @@ 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 {
Column {
BusyIndicator {
anchors.horizontalCenter: parent.horizontalCenter
running: !activeSessionsListView.count && !activeSessionsItem.inactiveSessionsTtlDays
size: BusyIndicatorSize.Medium
visible: opacity > 0
height: running ? implicitHeight : 0
}
SilicaListView { SilicaListView {
id: activeSessionsListView id: activeSessionsListView
width: parent.width width: parent.width
@ -71,6 +76,7 @@ AccordionItem {
width: parent.width width: parent.width
color: Theme.primaryColor color: Theme.primaryColor
horizontalAlignment: Qt.AlignHCenter horizontalAlignment: Qt.AlignHCenter
visible: activeSessionsListView.count > 0
} }
delegate: ListItem { delegate: ListItem {
id: activeSessionListItem id: activeSessionListItem
@ -111,9 +117,6 @@ AccordionItem {
font.bold: true font.bold: true
visible: modelData.is_current visible: modelData.is_current
color: Theme.highlightColor color: Theme.highlightColor
anchors {
horizontalCenter: parent.horizontalCenter
}
} }
Label { Label {
@ -121,53 +124,28 @@ AccordionItem {
text: modelData.application_name + " " + modelData.application_version text: modelData.application_name + " " + modelData.application_version
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
font.bold: true font.bold: true
color: Theme.primaryColor
maximumLineCount: 1 maximumLineCount: 1
elide: Text.ElideRight elide: Text.ElideRight
anchors {
horizontalCenter: parent.horizontalCenter
}
} }
Label { Label {
width: parent.width width: parent.width
text: modelData.device_model + ", " + (modelData.platform + " " + modelData.system_version).trim() text: modelData.device_model + ", " + (modelData.platform + " " + modelData.system_version).trim()
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.primaryColor
maximumLineCount: 1 maximumLineCount: 1
truncationMode: TruncationMode.Fade 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 { Label {
width: parent.width 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)) 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 font.pixelSize: Theme.fontSizeExtraSmall
color: Theme.primaryColor
maximumLineCount: 1 maximumLineCount: 1
truncationMode: TruncationMode.Fade truncationMode: TruncationMode.Fade
anchors {
horizontalCenter: parent.horizontalCenter
}
} }
} }
Separator { Separator {
id: separator
anchors { anchors {
bottom: parent.bottom bottom: parent.bottom
} }
@ -176,7 +154,59 @@ AccordionItem {
color: Theme.primaryColor color: Theme.primaryColor
horizontalAlignment: Qt.AlignHCenter 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
}
} }
} }
} }

View file

@ -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
View 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
View 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
View 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
View file

Before

Width:  |  Height:  |  Size: 221 B

After

Width:  |  Height:  |  Size: 221 B

0
qml/js/emoji/1f91d-1f3fb.svg Executable file → Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View file

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 1 KiB

0
qml/js/emoji/1faab.svg Executable file → Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View file

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 1 KiB

0
qml/js/emoji/1fae1.svg Executable file → Normal file
View 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
View file

Before

Width:  |  Height:  |  Size: 971 B

After

Width:  |  Height:  |  Size: 971 B

0
qml/js/emoji/1fae3.svg Executable file → Normal file
View 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
View file

Before

Width:  |  Height:  |  Size: 422 B

After

Width:  |  Height:  |  Size: 422 B

0
qml/js/emoji/1fae5.svg Executable file → Normal file
View 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
View file

Before

Width:  |  Height:  |  Size: 689 B

After

Width:  |  Height:  |  Size: 689 B

0
qml/js/emoji/1fae7.svg Executable file → Normal file
View 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
View file

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 1 KiB

0
qml/js/emoji/1faf0-1f3fc.svg Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 1 KiB

0
qml/js/emoji/1faf0-1f3fd.svg Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 1 KiB

0
qml/js/emoji/1faf0-1f3fe.svg Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 1 KiB

0
qml/js/emoji/1faf0-1f3ff.svg Executable file → Normal file
View file

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 1 KiB

0
qml/js/emoji/1faf0.svg Executable file → Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View file

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Some files were not shown because too many files have changed in this diff Show more