Compare commits

...

73 Commits

Author SHA1 Message Date
John Preston
f619afc4c6 Alpha 1.0.33: Fix build for Xcode. 2017-04-16 00:45:25 +03:00
John Preston
7ad7028880 Alpha 1.0.33: Various fixes and improvements. 2017-04-16 00:36:46 +03:00
John Preston
8e241e8b78 Improve Emoji-Stickers-GIFs panel.
Fix broken minimal panel size.
Remove HistoryWidget context menu from the panel.
2017-04-16 00:05:57 +03:00
John Preston
6226cf2809 Display video message playback progress time. 2017-04-15 23:30:28 +03:00
John Preston
7312114b75 Use full volume for video messages.
Set video volume to VideoVolume in MediaView and to 1 in HistoryGif.
2017-04-15 22:51:53 +03:00
John Preston
0ff299758a Use correct lang phrases for video messages. 2017-04-15 22:51:44 +03:00
John Preston
de7c886008 Move passcode management from MainWindow.
Check for auto lock in AuthSession. Don't autolock while video plays.
Closes #3219
2017-04-15 21:51:12 +03:00
John Preston
e3aacc8072 Don't change notification sound to empty on mute.
If notifications are muted no one from official apps play sound.
So there is no need to turn the sound off, otherwise if you enable
the notifications from a different app the sound stays off.

Enable the sound (change to "default") when turning notifications on.
2017-04-15 21:51:11 +03:00
John Preston
4fc2c18f58 Fix crash in intro label crossfade animation.
Remove the assertion because the assumption was not valid.

Closed #3270
2017-04-15 20:40:23 +03:00
John Preston
8a8e101cd0 Fix crash in file downloader destruction.
Regression was introduced in 835b1801bc.

We need to destroy all FileLoader instances before destroying the
Downloader instance, because they hold pointers to it and call its
methods in destructor if they need to cancel some MTP requests.
2017-04-15 20:39:32 +03:00
John Preston
c10dee11e8 Fix crash in macOS notifications manager init.
Regression was introduced in 1725927aea.

Also create the thread only when it is first needed.
2017-04-15 20:39:25 +03:00
John Preston
4e5c4a462b Fix crash in videoplayer audio stream loader.
Regression was introduced in 835b1801bc.
2017-04-15 20:32:14 +03:00
John Preston
bc7139d67a Fix crash in AuthSession::Exists() if there is no Messenger.
Also use toggleAnimated instead of show/hideAnimated in intro.
2017-04-15 19:28:07 +03:00
Ariel Jannai
bf0bf908c2 Update building-msvc.md (#3264)
* Update building-msvc.md

Fixed some wrong, missing or unclear parts. Based on the problems I came into when trying to build and configure everything.

Ninja not in path - from #3237
Newer msys - from #3247
Telegram.sln - from #2811

* Updated from the PR comments and added a signature


Signed-off-by: Ariel Jannai <arieljannai@gmail.com> (github: arieljannai)

* Updated by the latest comments from the PR

Signed-off-by: Ariel Jannai <arieljannai@gmail.com> (github: arieljannai)
2017-04-14 11:58:10 +02:00
John Preston
dd005d9027 Generate correct lang tag count, not hardcoded. 2017-04-13 11:51:47 +03:00
John Preston
670a725c53 Alpha 1.0.32: Fix round video checks in MediaView. 2017-04-12 23:34:57 +03:00
John Preston
af28e3b0d7 Alpha 1.0.32: Fix build in Xcode. 2017-04-12 23:28:04 +03:00
John Preston
ca90b8b8fd Alpha 1.0.32: Test the new API and CDN support. 2017-04-12 23:04:34 +03:00
John Preston
7b7b9db20b Add support for video messages send actions.
Animate record and upload the same way as voice messages.
2017-04-12 22:37:47 +03:00
John Preston
96dbb38aaa Improve mute and info display in video messages.
Display mute on top of the video and move info to the right side
for incoming messages (because of channel authors and views count).
2017-04-12 22:37:28 +03:00
John Preston
1b7777e3a0 Pause other GIFs when playing round video message. 2017-04-12 22:37:28 +03:00
John Preston
5480a63beb Support round video inline playback with sound. 2017-04-12 22:37:27 +03:00
John Preston
cbf040b4dc Crop round video messages to a circle.
Also display unread media dot like in voice messages.
2017-04-12 22:37:26 +03:00
John Preston
8eb7f1f1aa Display round video messages using HistoryGif.
Use autodownload and autoplay options from GIFs.
Also improve EditCaptionBox code.
2017-04-12 22:37:26 +03:00
John Preston
8d28d0691f API scheme updated to layer 66.
Support CDN file download.
2017-04-12 22:36:25 +03:00
John Preston
7dd24a30b5 Replace MetaLang with codegen_lang. 2017-04-12 22:18:42 +03:00
John Preston
1725927aea Clear macOS notifications in a separate thread.
Sometimes NSUserNotificationCenter -deliveredNotifications method call
freezes for a long time, so now we use it only in a separate thread and
we group all the requests for clearing while another clearing is done.
2017-04-12 15:50:35 +03:00
John Preston
50ea4e316e Improve macOS window behavior.
Don't deactivate the application when the main window is hidden.
Such behavior provides some unwanted windows reordering in the
current workspace when the window is hidden by Cmd+W.

Ignore app activation by applicationDidBecomeActive: notification
for a short period of time after a user notification for other app
instance was received (the system sends them sometimes and the main
window is shown + activated for a wrong instance of the application).
2017-04-12 15:50:12 +03:00
srazi
734b426518 Fix canceling forward when clicking on _userpicButton or _cloudButton (#3248)
- Fixes #3192

Signed-off-by: srazi <s.r.alavizadeh@gmail.com> (github: srazi)
2017-04-11 23:03:34 +03:00
Nicholas Guriev
232d3dcb54 Make theme preview more realistic (#3250)
Signed-off-by: Nicholas Guriev <guriev-ns@ya.ru> (github: mymedia2)
2017-04-11 21:16:12 +03:00
John Preston
eaf1e2b18e Alpha 1.0.31: Fix layout for message edit. 2017-04-11 21:04:28 +03:00
John Preston
4b7e5750ec Alpha 1.0.31: Fix crash in localstorage. 2017-04-11 20:31:20 +03:00
John Preston
d4af14041c Fix build for OS X 10.6-10.7.
Qt 5.3.2 doesn't support QTimer::singleShot(delay, lambda).
2017-04-11 18:44:11 +03:00
John Preston
b736d45bc4 Alpha 1.0.30: New tabbed panel as a third column. 2017-04-11 18:02:46 +03:00
John Preston
7f7318c0bf Fix members dropdown and chat info menu position. 2017-04-11 17:27:46 +03:00
John Preston
0e2c282476 Don't stop GIFs when TabbedSection is opened.
Also improve the appearance of Stickers and GIFs tabs with no items.
2017-04-11 17:03:47 +03:00
John Preston
891d200e2d Add TabbedSection which uses the TabbedSelector. 2017-04-10 12:08:56 +03:00
John Preston
647ea44881 Extract TabbedSelector from TabbedPanel.
Now we can use TabbedSelector separately, not only inside the panel.
2017-04-10 12:08:55 +03:00
John Preston
2c81014188 Fix crash on precondition in PeerListBox.
If a global search request was sent and we clear the query the
response still was being processed which caused an Expects() fail.
2017-04-10 12:08:15 +03:00
John Preston
6c4943de97 Cache travis dependencies after Qt build. 2017-04-08 20:29:21 +03:00
Viktor Oreshkin
f1d97fb92c Fix build in Xcode (#3241)
Signed-off-by: Viktor Oreshkin <stek29@users.noreply.github.com>
2017-04-08 18:05:59 +03:00
John Preston
26b05cf844 Finalize rename / move.
Also removed non-existent emoji_section module from GYP.
2017-04-08 17:05:19 +03:00
John Preston
155cd8ce42 Rename / move emoji_panel to tabbed_panel.
Next commit fixes the build.
2017-04-08 16:56:14 +03:00
John Preston
330fc35800 Move some classes to separate modules.
MessageField, BotKeyboard, HistoryInner from historywidget.
2017-04-08 16:31:58 +03:00
John Preston
570cd9bdfa Move GIF pausing methods to Window::Controller. 2017-04-08 16:31:57 +03:00
John Preston
cd3c5e4ade Fix build in GCC.
GCC doesn't allow using scoped enums in bitfields without warnings.
So we use "unsigned" bitfield and a couple of get/set methods.
2017-04-08 14:25:54 +03:00
John Preston
38f94c63e9 Add blocked users list in supergroups profiles. 2017-04-07 18:13:22 +03:00
John Preston
34ab04cbe6 Add lambda-based checked timers.
Also ApiWrap is now not a QObject.
2017-04-07 18:13:21 +03:00
John Preston
6b242a982b Fix GIF pause by layer.
Let MainWindow enable / disable GIF pausing when a layer is shown.
2017-04-07 18:13:20 +03:00
John Preston
0d0307e175 Move ApiWrap to AuthSession.
Also send all ApiWrap requests as an MTP::Sender.
Also create AuthSession only after starting MTProto.
2017-04-07 18:13:19 +03:00
John Preston
835b1801bc Remove Q_OBJECT dependency from ApiWrap.
Also remove it from SingleDelayedCall -> SingleQueuedInvocation.
2017-04-07 18:13:19 +03:00
John Preston
5444b8166c Finalize rename / move of files. 2017-04-07 18:13:18 +03:00
John Preston
c94a88e154 Rename / move a bunch of files.
Next commit fixes the build.
2017-04-07 18:13:16 +03:00
John Preston
b185af6f0c Use a separate Travis job for dependencies. 2017-04-06 18:14:55 +03:00
John Preston
8504bbb9d5 Improve icons and scripts for Windows Store. 2017-04-06 14:35:35 +03:00
John Preston
b2f1177661 Remove 'git checkout 5.*' before 'init-repository'.
Something has changed in Qt libraries remote layout so now the perl
init-repository script from the old Qt version doesn't work anymore.

We init the submodules using script from the latest Qt version and
after that we checkout the desired version by tag in all submodules.
2017-04-06 11:19:00 +03:00
John Preston
6746d4ba2d Build crashpad from git. Crashpad path has changed. 2017-04-06 11:06:29 +03:00
John Preston
0f7567970c Update preview image. 2017-04-05 18:56:58 +03:00
John Preston
7b7df23e3b Version 1.0.29: Fix crash on app quit.
Some cleanup actions in App::clearHistories() queue file loader
destructions that should be completed before MTProto is reset.
2017-04-05 13:39:31 +03:00
John Preston
252a6f9d5a Version 1.0.29: Fix cancel GIFs search button. 2017-04-05 13:14:17 +03:00
John Preston
a1adf2dae6 Version 1.0.29: Fix crash on app quit.
Destroy queued file loaders before destroying AuthSession, because
they have references to Downloader which is owned by AuthSession.
2017-04-05 13:04:26 +03:00
John Preston
f4d1cdf14d Merge branch 'master' into dev 2017-04-05 12:25:43 +03:00
John Preston
22d905b39c Version 1.0.29: Add cloud icon to main menu. 2017-04-05 12:22:45 +03:00
Jan Grulich
58bbc3f537 Add appstream metadata file (#3203)
Signed-off-by: Jan Grulich <grulja@gmail.com> (github: grulja)
2017-04-05 09:35:57 +02:00
John Preston
03a59b04be Add progress animation to GIFs search.
Also display "no results" phrase.
2017-04-04 16:19:49 +03:00
Christoph
2028116e22 Link to image 2017-04-04 14:50:01 +02:00
Christoph
244361b5c6 Add preview image to readme 2017-04-04 14:45:42 +02:00
Christoph
7e680624a0 Add preview image 2017-04-04 14:42:19 +02:00
Christoph
3304ad7222 Rename doc to docs 2017-04-04 14:40:49 +02:00
John Preston
4384c80961 Prefer appindicator only on Unity and Pantheon.
Commit dcd6028e91 introduced a regression which caused
appindicator tray icon to be preferred everywhere else.
2017-04-04 12:59:48 +03:00
John Preston
15befa98c4 Fix headers in building docs. Closes #3182 2017-04-04 12:17:54 +03:00
Lonami
b7ea15b83d Use message date by default when saving a photo (#1586) (#3150)
Signed-off-by: Lonami <totufals@hotmail.com> (github: Lonami)
2017-04-04 12:14:32 +03:00
Fritz Elfert
3915957612 Update libva git URL and Qt init-repository invocation (#3201)
Signed-off-by: Fritz Elfert <fritz-github@fritz-elfert.de> (github: felfert)
2017-04-04 12:12:56 +03:00
340 changed files with 10291 additions and 7508 deletions

View File

@@ -9,33 +9,35 @@ UPSTREAM="$REPO/upstream"
EXTERNAL="$REPO/external"
CACHE="$HOME/travisCacheDir"
QT_WAS_BUILT="0"
QT_VERSION=5.6.2
XKB_PATH="$BUILD/libxkbcommon"
XKB_CACHE_VERSION="2"
XKB_CACHE_VERSION="3"
QT_PATH="$BUILD/qt"
QT_CACHE_VERSION="2"
QT_CACHE_VERSION="3"
QT_PATCH="$UPSTREAM/Telegram/Patches/qtbase_${QT_VERSION//\./_}.diff"
BREAKPAD_PATH="$BUILD/breakpad"
BREAKPAD_CACHE_VERSION="2"
BREAKPAD_CACHE_VERSION="3"
GYP_PATH="$BUILD/gyp"
GYP_CACHE_VERSION="2"
GYP_CACHE_VERSION="3"
GYP_PATCH="$UPSTREAM/Telegram/Patches/gyp.diff"
VA_PATH="$BUILD/libva"
VA_CACHE_VERSION="2"
VA_CACHE_VERSION="3"
VDPAU_PATH="$BUILD/libvdpau"
VDPAU_CACHE_VERSION="1"
VDPAU_CACHE_VERSION="3"
FFMPEG_PATH="$BUILD/ffmpeg"
FFMPEG_CACHE_VERSION="2"
FFMPEG_CACHE_VERSION="3"
OPENAL_PATH="$BUILD/openal-soft"
OPENAL_CACHE_VERSION="2"
OPENAL_CACHE_VERSION="3"
GYP_DEFINES=""
@@ -57,6 +59,8 @@ run() {
build() {
mkdir -p "$EXTERNAL"
BUILD_VERSION_DATA=$(echo $BUILD_VERSION | cut -d'-' -f 1)
# libxkbcommon
getXkbCommon
@@ -84,6 +88,11 @@ build() {
# Guideline Support Library
getGSL
if [ "$QT_WAS_BUILT" == "1" ]; then
error_msg "Qt was built, please restart the job :("
exit 1
fi
# Configure the build
if [[ $BUILD_VERSION == *"disable_autoupdate"* ]]; then
GYP_DEFINES+=",TDESKTOP_DISABLE_AUTOUPDATE"
@@ -205,7 +214,7 @@ buildVa() {
rm -rf *
cd "$EXTERNAL"
git clone git://anongit.freedesktop.org/git/libva
git clone https://github.com/01org/libva
cd "$EXTERNAL/libva"
./autogen.sh --prefix=$VA_PATH --enable-static
@@ -511,6 +520,7 @@ getCustomQt() {
}
buildCustomQt() {
QT_WAS_BUILT="1"
info_msg "Downloading and building patched qt"
if [ -d "$EXTERNAL/qt${QT_VERSION}" ]; then
@@ -523,8 +533,7 @@ buildCustomQt() {
git clone git://code.qt.io/qt/qt5.git qt${QT_VERSION}
cd "$EXTERNAL/qt${QT_VERSION}"
git checkout "$(echo ${QT_VERSION} | sed -e s/\..$//)"
perl init-repository --module-subset=qtbase,qtimageformats
perl init-repository --branch --module-subset=qtbase,qtimageformats
git checkout v${QT_VERSION}
cd qtbase && git checkout v${QT_VERSION} && cd ..
cd qtimageformats && git checkout v${QT_VERSION} && cd ..

View File

@@ -6,6 +6,8 @@ This is the complete source code and the build instructions for the alpha versio
[![Build Status](https://travis-ci.org/telegramdesktop/tdesktop.svg?branch=dev)](https://travis-ci.org/telegramdesktop/tdesktop)
[![Build status](https://ci.appveyor.com/api/projects/status/uiw2y768iy4i5bu8/branch/dev?svg=true)](https://ci.appveyor.com/project/telegramdesktop/tdesktop)
[![Preview of Telegram Desktop][preview_image]][preview_image_url]
The source code is published under GPLv3 with OpenSSL exception, the license is available [here][license].
## Supported systems
@@ -47,7 +49,9 @@ The source code is published under GPLv3 with OpenSSL exception, the license is
[telegram_api]: https://core.telegram.org
[telegram_proto]: https://core.telegram.org/mtproto
[license]: LICENSE
[msvc]: doc/building-msvc.md
[xcode]: doc/building-xcode.md
[xcode_old]: doc/building-xcode-old.md
[cmake]: doc/building-cmake.md
[msvc]: docs/building-msvc.md
[xcode]: docs/building-xcode.md
[xcode_old]: docs/building-xcode-old.md
[cmake]: docs/building-cmake.md
[preview_image]: https://github.com/telegramdesktop/tdesktop/blob/dev/docs/assets/preview.png "Preview of Telegram Desktop"
[preview_image_url]: https://raw.githubusercontent.com/telegramdesktop/tdesktop/dev/docs/assets/preview.png

View File

@@ -462,6 +462,8 @@ changePhoneSimcardTo: notificationSampleNameFg; // change phone number box right
mainMenuBg: windowBg; // main menu background
mainMenuCoverBg: dialogsBgActive; // main menu top cover background
mainMenuCoverFg: windowFgActive; // main menu top cover text
mainMenuCloudFg: activeButtonFg;
mainMenuCloudBg: #2785bf | activeButtonBgRipple;
mediaPlayerBg: windowBg; // audio file player background
mediaPlayerActiveFg: windowBgActive; // audio file player playback progress already played part

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 B

View File

@@ -496,6 +496,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_profile_create_public_link" = "Create public link";
"lng_profile_edit_public_link" = "Edit public link";
"lng_profile_manage_admins" = "Manage administrators";
"lng_profile_manage_blocklist" = "Manage blocked users";
"lng_profile_common_groups" = "{count:_not_used_|# group|# groups} in common";
"lng_profile_common_groups_section" = "Groups in common";
"lng_profile_participants_section" = "Members";
@@ -575,6 +576,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_channel_admin_sure" = "Add {user} to administrators?";
"lng_channel_admins_too_much" = "Sorry, you have reached the limit of the administrators. Please remove one administrator first.";
"lng_group_blocked_list_about" = "Blocked users are removed from the group and can only come back if invited by an admin.\nInvite links don't work for them.";
"lng_chat_all_members_admins" = "All Members Are Admins";
"lng_chat_about_all_admins" = "Group members can add new members, edit name and photo of the group.";
"lng_chat_about_admins" = "Group admins can add and remove members, edit name and photo of the group.";
@@ -654,6 +657,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_action_pinned_media_video" = "a video";
"lng_action_pinned_media_audio" = "an audio file";
"lng_action_pinned_media_voice" = "a voice message";
"lng_action_pinned_media_video_message" = "a video message";
"lng_action_pinned_media_file" = "a file";
"lng_action_pinned_media_gif" = "a GIF animation";
"lng_action_pinned_media_contact" = "a contact information";
@@ -778,8 +782,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_switch_gifs" = "GIFs";
"lng_stickers_featured_add" = "Add";
"lng_gifs_search" = "Search GIFs";
"lng_gifs_no_saved" = "You have no saved GIFs yet.";
"lng_inline_bot_no_results" = "No results";
"lng_inline_bot_no_results" = "No results.";
"lng_inline_bot_via" = "via {inline_bot}";
"lng_box_remove" = "Remove";
@@ -806,6 +811,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_in_dlg_audio_file" = "Audio file";
"lng_in_dlg_contact" = "Contact";
"lng_in_dlg_audio" = "Voice message";
"lng_in_dlg_video_message" = "Video message";
"lng_in_dlg_file" = "File";
"lng_in_dlg_sticker" = "Sticker";
"lng_in_dlg_sticker_emoji" = "{emoji} Sticker";
@@ -885,6 +891,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_user_action_record_audio" = "{user} is recording a voice message";
"lng_send_action_upload_audio" = "sending a voice message";
"lng_user_action_upload_audio" = "{user} is sending a voice message";
"lng_send_action_record_round" = "recording a video message";
"lng_user_action_record_round" = "{user} is recording a video message";
"lng_send_action_upload_round" = "sending a video message";
"lng_user_action_upload_round" = "{user} is sending a video message";
"lng_send_action_upload_photo" = "sending a photo";
"lng_user_action_upload_photo" = "{user} is sending a photo";
"lng_send_action_upload_file" = "sending a file";
@@ -1075,7 +1085,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_new_version_wrap" = "Telegram Desktop was updated to version {version}\n\n{changes}\n\nFull version history is available here:\n{link}";
"lng_new_version_minor" = "— Bug fixes and other minor improvements";
"lng_new_version_text" = "— Send MP4/MOV files as videos that will play right inside Telegram.\n— Click on the date in any chat to quickly jump to messages from a specific day.\n— Change your phone number in Settings.\n— Edit who can see your last seen time and who can add you to groups in Settings.\n— Edit your list of blocked users in Settings.\n— App now respects the \"Do Not Disturb\" setting for macOS notifications.\n— Bug fixes and other minor improvements.";
"lng_new_version_text" = "— Improved Emoji, Stickers, and Saved GIFs panel.\n— Bug fixes and other minor improvements.";
"lng_menu_insert_unicode" = "Insert Unicode control character";

View File

@@ -774,12 +774,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_recent_stickers" = "Häufig genutzt";
"lng_switch_stickers" = "Sticker";
"lng_switch_stickers_gifs" = "GIFs & Sticker";
"lng_switch_emoji" = "Emoji";
"lng_switch_gifs" = "GIFs";
"lng_stickers_featured_add" = "Hinzufügen";
"lng_gifs_search" = "Suche GIFs";
"lng_saved_gifs" = "Gespeicherte GIFs";
"lng_inline_bot_results" = "Ergebnisse von {inline_bot}";
"lng_inline_bot_no_results" = "Keine Ergebnisse";
"lng_inline_bot_via" = "via {inline_bot}";
@@ -1076,7 +1075,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_new_version_wrap" = "Telegram Desktop wurde aktualisiert auf Version {version}\n\n{changes}\n\nGesamter Versionsverlauf:\n{link}";
"lng_new_version_minor" = "— Fehlerbehebungen und Softwareoptimierungen";
"lng_new_version_text" = "— Sende MP4/MOV Dateien als Videos. Sie werden dann direkt in der App abgespielt.\n— Schnell zu einem bestimmten Datum springen: Tippe auf das Datum im Chat und springe so direkt zu einem anderen Tag.\n— Neue Einstellungen: Telefonnummer ändern, \"zuletzt gesehen\" Status und Gruppeneinladungen in den Telegram-Einstellungen.\n— Die App hält sich an die \"Nicht stören\" Einstellungen bei macOS.\n— Fehlerbehebungen und kleinere Verbesserungen.";
"lng_new_version_text" = "— Emoji-, Sticker- und GIF-Panel wurden optimiert.\n— Fehlerbehebungen und Softwareoptimierungen";
"lng_menu_insert_unicode" = "Unicode-Steuerzeichen einfügen";

View File

@@ -774,12 +774,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_recent_stickers" = "Uso frecuente";
"lng_switch_stickers" = "Stickers";
"lng_switch_stickers_gifs" = "GIF y stickers";
"lng_switch_emoji" = "Emoji";
"lng_switch_gifs" = "GIF";
"lng_stickers_featured_add" = "Añadir";
"lng_gifs_search" = "Buscar GIF";
"lng_saved_gifs" = "GIF guardados";
"lng_inline_bot_results" = "Resultados de {inline_bot}";
"lng_inline_bot_no_results" = "Sin resultados";
"lng_inline_bot_via" = "vía {inline_bot}";
@@ -1076,7 +1075,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_new_version_wrap" = "Telegram Desktop ha sido actualizada a la versión {version}\n\n{changes}\n\nEl historial completo está disponible aquí:\n{link}";
"lng_new_version_minor" = "— Corrección de errores y otras mejoras menores";
"lng_new_version_text" = "— Envía archivos MP4/MOV como videos que se reproducirán dentro de Telegram.\n— Haz clic en la fecha en cualquier chat para ir a los mensajes de un día en específico.\n— Cambia tu número de teléfono en ajustes.\n— Edita quién puede ver tu última conexión y quién puede añadirte a grupos en ajustes.\n— Edita la lista de usuarios bloqueados en ajustes.\n— La aplicación ahora respeta la opción “No molestar” en las notificaciones de macOS. \n— Corrección de errores y otras mejoras menores.";
"lng_new_version_text" = "— Mejoras en el panel de emojis, stickers y GIF guardados.\n— Corrección de errores y otras mejoras menores.";
"lng_menu_insert_unicode" = "Insertar caracteres de control Unicode";

View File

@@ -774,12 +774,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_recent_stickers" = "Usati di frequente";
"lng_switch_stickers" = "Sticker";
"lng_switch_stickers_gifs" = "GIF e Sticker";
"lng_switch_emoji" = "Emoji";
"lng_switch_gifs" = "GIF";
"lng_stickers_featured_add" = "Aggiungi";
"lng_gifs_search" = "Cerca GIF";
"lng_saved_gifs" = "GIF salvate";
"lng_inline_bot_results" = "Risultati da {inline_bot}";
"lng_inline_bot_no_results" = "Nessun risultato";
"lng_inline_bot_via" = "via {inline_bot}";
@@ -1076,7 +1075,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_new_version_wrap" = "Telegram Desktop si è aggiornato alla versione {version}\n\n{changes}\n\nLa cronologia degli aggiornamenti è disponibile qui:\n{link}";
"lng_new_version_minor" = "— Risoluzione di problemi e altri miglioramenti minori";
"lng_new_version_text" = "— Vai alla data. Quando esegui una ricerca in una chat clicca sulla data per andare al giorno selezionato.\n— Aggiunte le Impostazioni per la privacy dell'ultimo accesso e per l'invito ai gruppi.\n— Cambia il tuo numero nelle Impostazioni.\n— Modifica la lista degli utenti bloccati nelle Impostazioni.\n— Invia file MP4/MOV come video in modo che vengano aperti all'interno di Telegram.\n— L'app ora rispetta la modalità \"Non disturbare\" per le notifiche di macOS.\n— Risoluzione di problemi e altri miglioramenti minori.";
"lng_new_version_text" = "— Miglioramenti nel pannello Emoji, Sticker e GIF salvate.\n— Risoluzione di problemi e altri miglioramenti minori.";
"lng_menu_insert_unicode" = "Inserisci carattere di controllo Unicode";

View File

@@ -774,12 +774,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_recent_stickers" = "자주 사용";
"lng_switch_stickers" = "스티커";
"lng_switch_stickers_gifs" = "GIF & 스티커";
"lng_switch_emoji" = "이모티콘";
"lng_switch_gifs" = "GIF";
"lng_stickers_featured_add" = "추가";
"lng_gifs_search" = "GIF 검색";
"lng_saved_gifs" = "저장된 GIF";
"lng_inline_bot_results" = "{inline_bot} 결과";
"lng_inline_bot_no_results" = "결과 없음";
"lng_inline_bot_via" = "{inline_bot} 결과";
@@ -1076,7 +1075,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_new_version_wrap" = "텔레그램 데스크탑은 {version} 버전으로 업데이트 되었습니다.\n\n{changes}\n\n전체 버전 히스토리는 아래에서 확인 가능합니다:\n{link}";
"lng_new_version_minor" = "— 버그 수정 및 일부 기능 향상";
"lng_new_version_text" = "— 텔레그램내에서 바로 MP4/MOV 파일 재생\n— 특정날자로 이동하여 대화내역 확인\n— 설정에서 전화번호 변경\n— 개인정보 설정화면에서 마지막 접속 및 그룹 초대 허용설정\n— 설정에서 차단된 사용자 리스트 수정\n— OSX 알림설정인 \"Do Not Disturb\" 설정 반영\n— 버그 수정 및 일부 기능 향상";
"lng_new_version_text" = "— 이모티콘, 스티커 및 GIF 저장 패널 기능 향상\n— 버그 수정 및 일부 기능 향상";
"lng_menu_insert_unicode" = "유니코드 문자를 입력하세요.";

View File

@@ -774,12 +774,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_recent_stickers" = "Veelgebruikt";
"lng_switch_stickers" = "Stickers";
"lng_switch_stickers_gifs" = "GIF's & stickers";
"lng_switch_emoji" = "Emoji";
"lng_switch_gifs" = "GIF's";
"lng_stickers_featured_add" = "Toevoegen";
"lng_gifs_search" = "GIF's zoeken";
"lng_saved_gifs" = "Opgeslagen GIF's";
"lng_inline_bot_results" = "Resultaten van {inline_bot}";
"lng_inline_bot_no_results" = "Geen resultaten";
"lng_inline_bot_via" = "via {inline_bot}";
@@ -1076,7 +1075,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_new_version_wrap" = "Telegram is bijgewerkt naar versie {version}\n\n{changes} \n\nVolledige versiegeschiedenis is hier te vinden:\n{link}";
"lng_new_version_minor" = "— Probleemoplossing en andere kleine verbeteringen";
"lng_new_version_text" = "— MP4/MOV-bestanden versturen als video, deze spelen direct af in Telegram.\n— Spring naar datum. Klik op de datum in een chat om naar een specifieke dag te springen.\n— Wijzig je telefoonnummer via de instellingen.\n— Privacyinstellingen voor \"laatst gezien\" en groepsuitnodigingen.\n— Geblokkeerde gebruikers beheren via instellingen.\n— Ondersteuning voor de \"Niet storen\"-functie van macOS.\n— Probleemoplossing en andere kleine verbeteringen.";
"lng_new_version_text" = "— Verbeterd paneel voor Emoji's, stickers en opgeslagen GIF's.\n— Probleemoplossing en andere kleine verbeteringen.";
"lng_menu_insert_unicode" = "Unicode-besturingsteken invoegen";

View File

@@ -774,12 +774,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_recent_stickers" = "Usados frequentemente";
"lng_switch_stickers" = "Stickers";
"lng_switch_stickers_gifs" = "GIFs e Stickers";
"lng_switch_emoji" = "Emoji";
"lng_switch_gifs" = "GIFs";
"lng_stickers_featured_add" = "Adicionar";
"lng_gifs_search" = "Buscar GIFs";
"lng_saved_gifs" = "GIFs Salvos";
"lng_inline_bot_results" = "Resultados de {inline_bot}";
"lng_inline_bot_no_results" = "Nenhum resultado";
"lng_inline_bot_via" = "via {inline_bot}";
@@ -1076,7 +1075,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_new_version_wrap" = "Telegram Desktop foi atualizado para a versão {version}\n\n{changes}\n\nHistórico completo de mudanças disponível aqui:\n{link}";
"lng_new_version_minor" = "— Resolução de bugs e outras melhorias menores";
"lng_new_version_text" = "— Envie arquivos MP4/MOV como vídeos que serão reproduzidos dentro do Telegram.\n— Clique em uma data na conversa para pular para o dia específico.\n— Altere seu número nas Configurações.\n— Edite quem pode ver suas opções de visto por último e quem pode te adicionar em grupos nas Configurações.\n— Edite a lista de usuários bloqueados nas Configurações.\n— O aplicativo agora respeita ao \"Não Perturbe\" nas notificações do macOS.\n— Resolução de bugs e outras melhorias.";
"lng_new_version_text" = "— Melhorias no painel de Emoji, Stickers e GIFs Salvos.\n— Resolução de bugs e outras melhorias menores";
"lng_menu_insert_unicode" = "Inserir caractere de controle Unicode";

View File

@@ -201,7 +201,7 @@ fileLocationUnavailable#7c596b46 volume_id:long local_id:int secret:long = FileL
fileLocation#53d69076 dc_id:int volume_id:long local_id:int secret:long = FileLocation;
userEmpty#200250ba id:int = User;
user#d10d979a flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true id:int access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?string bot_inline_placeholder:flags.19?string = User;
user#2e13f4c3 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true id:int access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?string bot_inline_placeholder:flags.19?string lang_code:flags.22?string = User;
userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto;
userProfilePhoto#d559d8c8 photo_id:long photo_small:FileLocation photo_big:FileLocation = UserProfilePhoto;
@@ -357,6 +357,8 @@ inputMessagesFilterVoice#50f5c392 = MessagesFilter;
inputMessagesFilterMusic#3751b49e = MessagesFilter;
inputMessagesFilterChatPhotos#3a20ecb8 = MessagesFilter;
inputMessagesFilterPhoneCalls#80c99768 flags:# missed:flags.0?true = MessagesFilter;
inputMessagesFilterRoundVoice#7a7c17a4 = MessagesFilter;
inputMessagesFilterRoundVideo#b549da53 = MessagesFilter;
updateNewMessage#1f2b0afd message:Message pts:int pts_count:int = Update;
updateMessageID#4e90bfd6 id:int random_id:long = Update;
@@ -440,8 +442,9 @@ photos.photosSlice#15051f54 count:int photos:Vector<Photo> users:Vector<User> =
photos.photo#20212ca8 photo:Photo users:Vector<User> = photos.Photo;
upload.file#96a18d5 type:storage.FileType mtime:int bytes:bytes = upload.File;
upload.fileCdnRedirect#1508485a dc_id:int file_token:bytes encryption_key:bytes encryption_iv:bytes = upload.File;
dcOption#5d8c6cc flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true id:int ip_address:string port:int = DcOption;
dcOption#5d8c6cc flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true cdn:flags.3?true id:int ip_address:string port:int = DcOption;
config#cb601684 flags:# phonecalls_enabled:flags.1?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int chat_big_size:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int rating_e_decay:int stickers_recent_limit:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string disabled_features:Vector<DisabledFeature> = Config;
@@ -501,6 +504,8 @@ sendMessageUploadDocumentAction#aa0cd9e4 progress:int = SendMessageAction;
sendMessageGeoLocationAction#176f8ba1 = SendMessageAction;
sendMessageChooseContactAction#628cbc6f = SendMessageAction;
sendMessageGamePlayAction#dd6a8f48 = SendMessageAction;
sendMessageRecordRoundAction#88f27fbc = SendMessageAction;
sendMessageUploadRoundAction#bb718624 = SendMessageAction;
contacts.found#1aa1f784 results:Vector<Peer> chats:Vector<Chat> users:Vector<User> = contacts.Found;
@@ -533,7 +538,7 @@ accountDaysTTL#b8d0afdf days:int = AccountDaysTTL;
documentAttributeImageSize#6c37c15c w:int h:int = DocumentAttribute;
documentAttributeAnimated#11b58939 = DocumentAttribute;
documentAttributeSticker#6319d612 flags:# mask:flags.1?true alt:string stickerset:InputStickerSet mask_coords:flags.0?MaskCoords = DocumentAttribute;
documentAttributeVideo#5910cccb duration:int w:int h:int = DocumentAttribute;
documentAttributeVideo#ef02ce6 flags:# round_message:flags.0?true duration:int w:int h:int = DocumentAttribute;
documentAttributeAudio#9852f9c6 flags:# voice:flags.10?true duration:int title:flags.0?string performer:flags.1?string waveform:flags.2?bytes = DocumentAttribute;
documentAttributeFilename#15590068 file_name:string = DocumentAttribute;
documentAttributeHasStickers#9801d2f7 = DocumentAttribute;
@@ -853,6 +858,13 @@ phoneCallProtocol#a2bb35cb flags:# udp_p2p:flags.0?true udp_reflector:flags.1?tr
phone.phoneCall#ec82e140 phone_call:PhoneCall users:Vector<User> = phone.PhoneCall;
upload.cdnFileReuploadNeeded#eea8e46e request_token:bytes = upload.CdnFile;
upload.cdnFile#a99fca4f bytes:bytes = upload.CdnFile;
cdnPublicKey#c982eaba dc_id:int public_key:string = CdnPublicKey;
cdnConfig#5725e40a public_keys:Vector<CdnPublicKey> = CdnConfig;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@@ -1024,6 +1036,8 @@ upload.saveFilePart#b304a621 file_id:long file_part:int bytes:bytes = Bool;
upload.getFile#e3a6cfb5 location:InputFileLocation offset:int limit:int = upload.File;
upload.saveBigFilePart#de7b673d file_id:long file_part:int file_total_parts:int bytes:bytes = Bool;
upload.getWebFile#24e6818d location:InputWebFileLocation offset:int limit:int = upload.WebFile;
upload.getCdnFile#2000bcc3 file_token:bytes offset:int limit:int = upload.CdnFile;
upload.reuploadCdnFile#2e7a2020 file_token:bytes request_token:bytes = Bool;
help.getConfig#c4f9186b = Config;
help.getNearestDc#1fb33026 = NearestDc;
@@ -1034,6 +1048,7 @@ help.getSupport#9cdf08cd = help.Support;
help.getAppChangelog#9010ef6f prev_app_version:string = Updates;
help.getTermsOfService#350170f3 = help.TermsOfService;
help.setBotUpdatesStatus#ec22cfcd pending_updates_count:int message:string = Bool;
help.getCdnConfig#52029342 = CdnConfig;
channels.readHistory#cc104937 channel:InputChannel max_id:int = Bool;
channels.deleteMessages#84c1fd4e channel:InputChannel id:Vector<int> = messages.AffectedMessages;
@@ -1082,4 +1097,4 @@ phone.discardCall#78d413a6 peer:InputPhoneCall duration:int reason:PhoneCallDisc
phone.setCallRating#1c536a34 peer:InputPhoneCall rating:int comment:string = Updates;
phone.saveCallDebug#277add7e peer:InputPhoneCall debug:DataJSON = Bool;
// LAYER 65
// LAYER 66

View File

@@ -7,9 +7,9 @@
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap uap2 uap3 rescap">
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
ProcessorArchitecture="x64"
ProcessorArchitecture="ARCHITECTURE"
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
Version="1.0.28.0" />
Version="1.0.33.0" />
<Properties>
<DisplayName>Telegram Desktop</DisplayName>
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>
@@ -28,7 +28,7 @@
<Applications>
<Application Id="Telegram.TelegramDesktop.Store" Executable="Telegram.exe" EntryPoint="Windows.FullTrustApplication">
<uap:VisualElements
BackgroundColor="transparent"
BackgroundColor="#1e94d0"
DisplayName="Telegram Desktop"
Square150x150Logo="Assets\logo150\logo150.png"
Square44x44Logo="Assets\logo44\logo44.png"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 852 B

After

Width:  |  Height:  |  Size: 640 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 816 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -34,8 +34,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,28,0
PRODUCTVERSION 1,0,28,0
FILEVERSION 1,0,33,0
PRODUCTVERSION 1,0,33,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -52,10 +52,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileDescription", "Telegram Desktop"
VALUE "FileVersion", "1.0.28.0"
VALUE "FileVersion", "1.0.33.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2017"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "1.0.28.0"
VALUE "ProductVersion", "1.0.33.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,28,0
PRODUCTVERSION 1,0,28,0
FILEVERSION 1,0,33,0
PRODUCTVERSION 1,0,33,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -43,10 +43,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileDescription", "Telegram Desktop Updater"
VALUE "FileVersion", "1.0.28.0"
VALUE "FileVersion", "1.0.33.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2017"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "1.0.28.0"
VALUE "ProductVersion", "1.0.33.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -1,795 +0,0 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop 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.
It 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.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "genlang.h"
#include <QtCore/QtPlugin>
#ifdef Q_OS_WIN
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
#endif
#ifdef Q_OS_MAC
//Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin)
#endif
typedef unsigned int uint32;
QString layoutDirection;
typedef QMap<QByteArray, QString> LangKeys;
LangKeys keys;
typedef QMap<QByteArray, ushort> LangTags;
LangTags tags;
typedef QMap<QByteArray, QVector<QByteArray> > LangKeysTags;
LangKeysTags keysTags;
typedef QVector<QByteArray> KeysOrder;
KeysOrder keysOrder;
KeysOrder tagsOrder;
typedef QMap<QByteArray, QMap<QByteArray, QVector<QString> > > LangKeysCounted;
LangKeysCounted keysCounted;
static const QChar TextCommand(0x0010);
static const QChar TextCommandLangTag(0x0020);
bool skipWhitespaces(const char *&from, const char *end) {
while (from < end && (*from == ' ' || *from == '\n' || *from == '\t' || *from == '\r')) {
++from;
}
return (from < end);
}
bool skipComment(const char *&from, const char *end) {
if (from >= end) return false;
if (*from == '/') {
if (from + 1 >= end) return true;
if (*(from + 1) == '*') {
from += 2;
while (from + 1 < end && (*from != '*' || *(from + 1) != '/')) {
++from;
}
from += 2;
return (from < end);
} else if (*(from + 1) == '/') {
from += 2;
while (from < end && *from != '\n' && *from != '\r') {
++from;
}
if (from < end) ++from;
return true;
} else {
return true;
}
}
return true;
}
bool skipJunk(const char *&from, const char *end) {
const char *start;
do {
start = from;
if (!skipWhitespaces(from, end)) return false;
if (!skipComment(from, end)) throw Exception("Unexpected end of comment!");
} while (start != from);
return true;
}
inline bool _lngEquals(const QByteArray &key, int from, int len, const char *value, int size) {
if (size != len || from + len > key.size()) return false;
for (const char *v = key.constData() + from, *e = v + len; v != e; ++v, ++value) {
if (*v != *value) return false;
}
return true;
}
#define LNG_EQUALS_PART(key, from, len, value) _lngEquals(key, from, len, value, sizeof(value) - 1)
#define LNG_EQUALS_TAIL(key, from, value) _lngEquals(key, from, key.size() - from, value, sizeof(value) - 1)
#define LNG_EQUALS(key, value) _lngEquals(key, 0, key.size(), value, sizeof(value) - 1)
static const int MaxCountedValues = 6;
void readKeyValue(const char *&from, const char *end) {
if (!skipJunk(from, end)) return;
if (*from != '"') throw Exception(QString("Expected quote before key name!"));
const char *nameStart = ++from;
while (from < end && ((*from >= 'a' && *from <= 'z') || (*from >= 'A' && *from <= 'Z') || *from == '_' || (*from >= '0' && *from <= '9'))) {
++from;
}
if (from == nameStart) throw Exception(QString("Expected key name!"));
QByteArray varName = QByteArray(nameStart, int(from - nameStart));
for (const char *t = nameStart; t + 1 < from; ++t) {
if (*t == '_') {
if (*(t + 1) == '_') throw Exception(QString("Bad key name: %1").arg(QLatin1String(varName)));
++t;
}
}
if (from == end || *from != '"') throw Exception(QString("Expected quote after key name in key '%1'!").arg(QLatin1String(varName)));
++from;
if (!skipJunk(from, end)) throw Exception(QString("Unexpected end of file in key '%1'!").arg(QLatin1String(varName)));
if (*from != '=') throw Exception(QString("'=' expected in key '%1'!").arg(QLatin1String(varName)));
if (!skipJunk(++from, end)) throw Exception(QString("Unexpected end of file in key '%1'!").arg(QLatin1String(varName)));
if (*from != '"') throw Exception(QString("Expected string after '=' in key '%1'!").arg(QLatin1String(varName)));
QByteArray varValue;
const char *start = ++from;
QVector<QByteArray> tagsList;
while (from < end && *from != '"') {
if (*from == '\n') {
throw Exception(QString("Unexpected end of string in key '%1'!").arg(QLatin1String(varName)));
}
if (*from == '\\') {
if (from + 1 >= end) throw Exception(QString("Unexpected end of file in key '%1'!").arg(QLatin1String(varName)));
if (*(from + 1) == '"' || *(from + 1) == '\\' || *(from + 1) == '{') {
if (from > start) varValue.append(start, int(from - start));
start = ++from;
} else if (*(from + 1) == 'n') {
if (from > start) varValue.append(start, int(from - start));
varValue.append('\n');
start = (++from) + 1;
}
} else if (*from == '{') {
if (from > start) varValue.append(start, int(from - start));
const char *tagStart = ++from;
while (from < end && ((*from >= 'a' && *from <= 'z') || (*from >= 'A' && *from <= 'Z') || *from == '_' || (*from >= '0' && *from <= '9'))) {
++from;
}
if (from == tagStart) throw Exception(QString("Expected tag name in key '%1'!").arg(QLatin1String(varName)));
QByteArray tagName = QByteArray(tagStart, int(from - tagStart));
if (from == end || (*from != '}' && *from != ':')) throw Exception(QString("Expected '}' or ':' after tag name in key '%1'!").arg(QLatin1String(varName)));
LangTags::const_iterator i = tags.constFind(tagName);
if (i == tags.cend()) {
i = tags.insert(tagName, tagsOrder.size());
tagsOrder.push_back(tagName);
}
if (0x0020 + *i > 0x007F) throw Exception(QString("Too many different tags in key '%1'").arg(QLatin1String(varName)));
QString tagReplacer(4, TextCommand);
tagReplacer[1] = TextCommandLangTag;
tagReplacer[2] = QChar(0x0020 + *i);
varValue.append(tagReplacer.toUtf8());
for (int j = 0, s = tagsList.size(); j < s; ++j) {
if (tagsList.at(j) == tagName) throw Exception(QString("Tag '%1' double used in key '%2'!").arg(QLatin1String(tagName)).arg(QLatin1String(varName)));
}
tagsList.push_back(tagName);
if (*from == ':') {
start = ++from;
QVector<QString> &counted(keysCounted[varName][tagName]);
QByteArray subvarValue;
bool foundtag = false;
while (from < end && *from != '"' && *from != '}') {
if (*from == '|') {
if (from > start) subvarValue.append(start, int(from - start));
counted.push_back(QString::fromUtf8(subvarValue));
subvarValue = QByteArray();
foundtag = false;
start = from + 1;
}
if (*from == '\n') {
throw Exception(QString("Unexpected end of string inside counted tag '%1' in '%2' key!").arg(QLatin1String(tagName)).arg(QLatin1String(varName)));
}
if (*from == '\\') {
if (from + 1 >= end) throw Exception(QString("Unexpected end of file inside counted tag '%1' in '%2' key!").arg(QLatin1String(tagName)).arg(QLatin1String(varName)));
if (*(from + 1) == '"' || *(from + 1) == '\\' || *(from + 1) == '{' || *(from + 1) == '#') {
if (from > start) subvarValue.append(start, int(from - start));
start = ++from;
} else if (*(from + 1) == 'n') {
if (from > start) subvarValue.append(start, int(from - start));
subvarValue.append('\n');
start = (++from) + 1;
}
} else if (*from == '{') {
throw Exception(QString("Unexpected tag inside counted tag '%1' in '%2' key!").arg(QLatin1String(tagName)).arg(QLatin1String(varName)));
} else if (*from == '#') {
if (foundtag) throw Exception(QString("Replacement '#' double used inside counted tag '%1' in '%2' key!").arg(QLatin1String(tagName)).arg(QLatin1String(varName)));
foundtag = true;
if (from > start) subvarValue.append(start, int(from - start));
subvarValue.append(tagReplacer.toUtf8());
start = from + 1;
}
++from;
}
if (from >= end) throw Exception(QString("Unexpected end of file inside counted tag '%1' in '%2' key!").arg(QLatin1String(tagName)).arg(QLatin1String(varName)));
if (*from == '"') throw Exception(QString("Unexpected end of string inside counted tag '%1' in '%2' key!").arg(QLatin1String(tagName)).arg(QLatin1String(varName)));
if (from > start) subvarValue.append(start, int(from - start));
counted.push_back(QString::fromUtf8(subvarValue));
if (counted.size() > MaxCountedValues) {
throw Exception(QString("Too many values inside counted tag '%1' in '%2' key!").arg(QLatin1String(tagName)).arg(QLatin1String(varName)));
}
}
start = from + 1;
}
++from;
}
if (from >= end) throw Exception(QString("Unexpected end of file in key '%1'!").arg(QLatin1String(varName)));
if (from > start) varValue.append(start, int(from - start));
if (!skipJunk(++from, end)) throw Exception(QString("Unexpected end of file in key '%1'!").arg(QLatin1String(varName)));
if (*from != ';') throw Exception(QString("';' expected after \"value\" in key '%1'!").arg(QLatin1String(varName)));
skipJunk(++from, end);
if (varName == "direction") {
throw Exception(QString("Unexpected value for 'direction' in key '%1'!").arg(QLatin1String(varName)));
} else if (!LNG_EQUALS_PART(varName, 0, 4, "lng_")) {
throw Exception(QString("Bad key '%1'!").arg(QLatin1String(varName)));
} else if (keys.constFind(varName) != keys.cend()) {
throw Exception(QString("Key '%1' doubled!").arg(QLatin1String(varName)));
} else {
keys.insert(varName, QString::fromUtf8(varValue));
keysTags.insert(varName, tagsList);
keysOrder.push_back(varName);
}
}
QString escapeCpp(const QByteArray &key, QString value) {
if (value.isEmpty()) return "QString()";
QString res;
res.reserve(value.size() * 10);
bool instr = false;
for (const QChar *ch = value.constData(), *e = value.constData() + value.size(); ch != e; ++ch) {
if (ch->unicode() > 0x007F) {
if (instr) {
res.append('"');
instr = false;
}
res.append(' ').append('u').append('"').append('\\').append('x').append(QString("%1").arg(ch->unicode(), 4, 16, QChar('0'))).append('"');
} else {
if (ch->unicode() == '\\' || ch->unicode() == '\n' || ch->unicode() == '\r' || ch->unicode() == '"') {
if (!instr) {
res.append(' ').append('u').append('"');
instr = true;
}
res.append('\\');
if (ch->unicode() == '\\' || ch->unicode() == '"') {
res.append(*ch);
} else if (ch->unicode() == '\n') {
res.append('n');
} else if (ch->unicode() == '\r') {
res.append('r');
}
} else if (ch->unicode() < 0x0020) {
if (*ch == TextCommand) {
if (ch + 3 >= e || (ch + 1)->unicode() != TextCommandLangTag || (ch + 2)->unicode() > 0x007F || (ch + 2)->unicode() < 0x0020 || *(ch + 3) != TextCommand) {
throw Exception(QString("Bad value for key '%1'").arg(QLatin1String(key)));
} else {
if (instr) {
res.append('"');
instr = false;
}
res.append(' ').append('u').append('"');
res.append('\\').append('x').append(QString("%1").arg(ch->unicode(), 2, 16, QChar('0')));
res.append('\\').append('x').append(QString("%1").arg((ch + 1)->unicode(), 2, 16, QChar('0')));
res.append('\\').append('x').append(QString("%1").arg((ch + 2)->unicode(), 2, 16, QChar('0')));
res.append('\\').append('x').append(QString("%1").arg((ch + 3)->unicode(), 2, 16, QChar('0')));
res.append('"');
ch += 3;
}
} else {
throw Exception(QString("Bad value for key '%1'").arg(QLatin1String(key)));
}
} else {
if (!instr) {
res.append(' ').append('u').append('"');
instr = true;
}
res.append(*ch);
}
}
}
if (instr) res.append('"');
return "qsl(" + res.mid(1) + ")";
}
void writeCppKey(QTextStream &tcpp, const QByteArray &key, const QString &val) {
tcpp << "\t\t\tset(" << key << ", " << escapeCpp(key, val) << ");\n";
}
bool genLang(const QString &lang_in, const QString &lang_out) {
QString lang_cpp = lang_out + ".cpp", lang_h = lang_out + ".h";
QFile f(lang_in);
if (!f.open(QIODevice::ReadOnly)) {
cout << "Could not open lang input file '" << lang_in.toUtf8().constData() << "'!\n";
QCoreApplication::exit(1);
return false;
}
QByteArray checkCodec = f.read(3);
if (checkCodec.size() < 3) {
cout << "Bad lang input file '" << lang_in.toUtf8().constData() << "'!\n";
QCoreApplication::exit(1);
return false;
}
f.seek(0);
QByteArray data;
int skip = 0;
if ((checkCodec.at(0) == '\xFF' && checkCodec.at(1) == '\xFE') || (checkCodec.at(0) == '\xFE' && checkCodec.at(1) == '\xFF') || (checkCodec.at(1) == 0)) {
QTextStream stream(&f);
stream.setCodec("UTF-16");
QString string = stream.readAll();
if (stream.status() != QTextStream::Ok) {
cout << "Could not read valid UTF-16 file '" << lang_in.toUtf8().constData() << "'!\n";
QCoreApplication::exit(1);
return false;
}
f.close();
data = string.toUtf8();
} else if (checkCodec.at(0) == 0) {
QByteArray tmp = "\xFE\xFF" + f.readAll(); // add fake UTF-16 BOM
f.close();
QTextStream stream(&tmp);
stream.setCodec("UTF-16");
QString string = stream.readAll();
if (stream.status() != QTextStream::Ok) {
cout << "Could not read valid UTF-16 file '" << lang_in.toUtf8().constData() << "'!\n";
QCoreApplication::exit(1);
return false;
}
data = string.toUtf8();
} else {
data = f.readAll();
if (checkCodec.at(0) == '\xEF' && checkCodec.at(1) == '\xBB' && checkCodec.at(2) == '\xBF') {
skip = 3; // skip UTF-8 BOM
}
}
const char *text = data.constData() + skip, *end = text + data.size() - skip;
try {
while (text < end) {
readKeyValue(text, end);
}
QByteArray cppText, hText;
{
QTextStream tcpp(&cppText), th(&hText);
tcpp.setCodec("ISO 8859-1");
th.setCodec("ISO 8859-1");
th << "\
/*\n\
Created from \'/Resources/langs/lang.strings\' by \'/MetaLang\' project\n\
\n\
WARNING! All changes made in this file will be lost!\n\
\n\
This file is part of Telegram Desktop,\n\
the official desktop version of Telegram messaging app, see https://telegram.org\n\
\n\
Telegram Desktop is free software: you can redistribute it and/or modify\n\
it under the terms of the GNU General Public License as published by\n\
the Free Software Foundation, either version 3 of the License, or\n\
(at your option) any later version.\n\
\n\
It is distributed in the hope that it will be useful,\n\
but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
GNU General Public License for more details.\n\
\n\
In addition, as a special exception, the copyright holders give permission\n\
to link the code of portions of this program with the OpenSSL library.\n\
\n\
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE\n\
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org\n\
*/\n";
th << "#pragma once\n\n";
for (int i = 0, l = tagsOrder.size(); i < l; ++i) {
th << "enum lngtag_" << tagsOrder[i] << " { lt_" << tagsOrder[i] << " = " << i << " };\n";
}
th << "static const ushort lngtags_cnt = " << tagsOrder.size() << ";\n";
th << "static const ushort lngtags_max_counted_values = " << MaxCountedValues << ";\n";
th << "\n";
th << "enum LangKey {\n";
for (int i = 0, l = keysOrder.size(); i < l; ++i) {
if (keysTags[keysOrder[i]].isEmpty()) {
th << "\t" << keysOrder[i] << (i ? "" : " = 0") << ",\n";
} else {
th << "\t" << keysOrder[i] << "__tagged" << (i ? "" : " = 0") << ",\n";
QMap<QByteArray, QVector<QString> > &countedTags(keysCounted[keysOrder[i]]);
if (!countedTags.isEmpty()) {
for (QMap<QByteArray, QVector<QString> >::const_iterator j = countedTags.cbegin(), e = countedTags.cend(); j != e; ++j) {
const auto &counted(*j);
for (int k = 0, s = counted.size(); k < s; ++k) {
th << "\t" << keysOrder[i] << "__" + j.key() + QString::number(k).toUtf8() << ",\n";
}
}
}
}
}
th << "\n\tlngkeys_cnt\n";
th << "};\n\n";
th << "LangString lang(LangKey key);\n\n";
th << "LangString langOriginal(LangKey key);\n\n";
for (int i = 0, l = keysOrder.size(); i < l; ++i) {
QVector<QByteArray> &tagsList(keysTags[keysOrder[i]]);
if (tagsList.isEmpty()) continue;
QMap<QByteArray, QVector<QString> > &countedTags(keysCounted[keysOrder[i]]);
th << "inline LangString " << keysOrder[i] << "(";
for (int j = 0, s = tagsList.size(); j < s; ++j) {
if (countedTags[tagsList[j]].isEmpty()) {
th << "lngtag_" << tagsList[j] << ", const QString &" << tagsList[j] << "__val";
} else {
th << "lngtag_" << tagsList[j] << ", float64 " << tagsList[j] << "__val";
}
if (j + 1 < s) th << ", ";
}
th << ") {\n";
th << "\treturn lang(" << keysOrder[i] << "__tagged)";
for (int j = 0, s = tagsList.size(); j < s; ++j) {
if (countedTags[tagsList[j]].isEmpty()) {
th << ".tag(lt_" << tagsList[j] << ", " << tagsList[j] << "__val)";
} else {
th << ".tag(lt_" << tagsList[j] << ", langCounted(" << keysOrder[i] << "__" << tagsList[j] << "0, lt_" << tagsList[j] << ", " << tagsList[j] << "__val))";
}
}
th << ";\n";
th << "}\n";
}
tcpp << "\
/*\n\
Created from \'/Resources/langs/lang.strings\' by \'/MetaLang\' project\n\
\n\
WARNING! All changes made in this file will be lost!\n\
\n\
This file is part of Telegram Desktop,\n\
the official desktop version of Telegram messaging app, see https://telegram.org\n\
\n\
Telegram Desktop is free software: you can redistribute it and/or modify\n\
it under the terms of the GNU General Public License as published by\n\
the Free Software Foundation, either version 3 of the License, or\n\
(at your option) any later version.\n\
\n\
It is distributed in the hope that it will be useful,\n\
but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
GNU General Public License for more details.\n\
\n\
In addition, as a special exception, the copyright holders give permission\n\
to link the code of portions of this program with the OpenSSL library.\n\
\n\
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE\n\
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org\n\
*/\n";
tcpp << "#include \"lang.h\"\n\n";
tcpp << "namespace {\n";
tcpp << "\tconst char *_langKeyNames[lngkeys_cnt] = {\n";
for (int i = 0, l = keysOrder.size(); i < l; ++i) {
if (keysTags[keysOrder[i]].isEmpty()) {
tcpp << "\t\t\"" << keysOrder[i] << "\",\n";
} else {
tcpp << "\t\t\"" << keysOrder[i] << "__tagged\",\n";
QMap<QByteArray, QVector<QString> > &countedTags(keysCounted[keysOrder[i]]);
if (!countedTags.isEmpty()) {
for (QMap<QByteArray, QVector<QString> >::const_iterator j = countedTags.cbegin(), e = countedTags.cend(); j != e; ++j) {
const auto &counted(*j);
for (int k = 0, s = counted.size(); k < s; ++k) {
tcpp << "\t\t\"" << keysOrder[i] << "__" + j.key() + QString::number(k).toUtf8() << "\",\n";
}
}
}
}
}
tcpp << "\t};\n\n";
tcpp << "\tLangString _langValues[lngkeys_cnt], _langValuesOriginal[lngkeys_cnt];\n\n";
tcpp << "\tvoid set(LangKey key, const QString &val) {\n";
tcpp << "\t\t_langValues[key] = val;\n";
tcpp << "\t}\n\n";
tcpp << "\tclass LangInit {\n";
tcpp << "\tpublic:\n";
tcpp << "\t\tLangInit() {\n";
for (int i = 0, l = keysOrder.size(); i < l; ++i) {
writeCppKey(tcpp, keysOrder[i] + (keysTags[keysOrder[i]].isEmpty() ? "" : "__tagged"), keys[keysOrder[i]]);
QMap<QByteArray, QVector<QString> > &countedTags(keysCounted[keysOrder[i]]);
if (!countedTags.isEmpty()) {
for (QMap<QByteArray, QVector<QString> >::const_iterator j = countedTags.cbegin(), e = countedTags.cend(); j != e; ++j) {
const auto &counted(*j);
for (int k = 0, s = counted.size(); k < s; ++k) {
writeCppKey(tcpp, keysOrder[i] + "__" + j.key() + QString::number(k).toUtf8(), counted[k]);
}
}
}
}
tcpp << "\t\t}\n";
tcpp << "\t};\n\n";
tcpp << "\tLangInit _langInit;\n\n";
tcpp << "\tinline bool _lngEquals(const QByteArray &key, int from, int len, const char *value, int size) {\n";
tcpp << "\t\tif (size != len || from + len > key.size()) return false;\n";
tcpp << "\t\tfor (const char *v = key.constData() + from, *e = v + len; v != e; ++v, ++value) {\n";
tcpp << "\t\t\tif (*v != *value) return false;\n";
tcpp << "\t\t}\n";
tcpp << "\t\treturn true;\n";
tcpp << "\t}\n";
tcpp << "}\n\n";
tcpp << "#define LNG_EQUALS_PART(key, from, len, value) _lngEquals(key, from, len, value, sizeof(value) - 1)\n";
tcpp << "#define LNG_EQUALS_TAIL(key, from, value) _lngEquals(key, from, key.size() - from, value, sizeof(value) - 1)\n";
tcpp << "#define LNG_EQUALS(key, value) _lngEquals(key, 0, key.size(), value, sizeof(value) - 1)\n\n";
tcpp << "LangString lang(LangKey key) {\n";
tcpp << "\treturn (key < 0 || key > lngkeys_cnt) ? QString() : _langValues[key];\n";
tcpp << "}\n\n";
tcpp << "LangString langOriginal(LangKey key) {\n";
tcpp << "\treturn (key < 0 || key > lngkeys_cnt || _langValuesOriginal[key] == qsl(\"{}\")) ? QString() : (_langValuesOriginal[key].isEmpty() ? _langValues[key] : _langValuesOriginal[key]);\n";
tcpp << "}\n\n";
tcpp << "const char *langKeyName(LangKey key) {\n";
tcpp << "\treturn (key < 0 || key > lngkeys_cnt) ? \"\" : _langKeyNames[key];\n";
tcpp << "}\n\n";
tcpp << "ushort LangLoader::tagIndex(const QByteArray &tag) const {\n";
tcpp << "\tif (tag.isEmpty()) return lngtags_cnt;\n\n";
if (!tags.isEmpty()) {
QString tab("\t");
tcpp << "\tconst char *ch = tag.constData(), *e = tag.constData() + tag.size();\n";
QByteArray current;
int depth = current.size();
tcpp << "\tswitch (*ch) {\n";
for (LangTags::const_iterator i = tags.cbegin(), j = i + 1, e = tags.cend(); i != e; ++i) {
QByteArray tag = i.key();
while (depth > 0 && tag.mid(0, depth) != current) {
tcpp << tab.repeated(depth + 1) << "}\n";
current.chop(1);
--depth;
tcpp << tab.repeated(depth + 1) << "break;\n";
}
do {
if (tag == current) break;
char ich = i.key().at(current.size());
tcpp << tab.repeated(current.size() + 1) << "case '" << ich << "':\n";
if (j == e || ich != ((j.key().size() > depth) ? j.key().at(depth) : 0)) {
if (tag == current + ich) {
tcpp << tab.repeated(depth + 1) << "\tif (ch + " << (depth + 1) << " == e) return lt_" << tag << ";\n";
} else {
tcpp << tab.repeated(depth + 1) << "\tif (LNG_EQUALS_TAIL(tag, " << (depth + 1) << ", \"" << i.key().mid(depth + 1) << "\")) return lt_" << tag << ";\n";
}
tcpp << tab.repeated(depth + 1) << "break;\n";
break;
}
++depth;
current += ich;
bool exact = (tag == current);
if (exact) {
tcpp << tab.repeated(depth + 1) << "if (ch + " << depth << " == e) {\n";
tcpp << tab.repeated(depth + 1) << "\treturn lt_" << tag << ";\n";
tcpp << tab.repeated(depth + 1) << "}\n";
}
QByteArray nexttag = j.key();
if (exact && depth > 0 && nexttag.mid(0, depth) != current) {
current.chop(1);
--depth;
tcpp << tab.repeated(depth + 1) << "break;\n";
break;
} else {
tcpp << tab.repeated(depth + 1) << "if (ch + " << depth << " < e) switch (*(ch + " << depth << ")) {\n";
}
} while (true);
++j;
}
while (QByteArray() != current) {
tcpp << tab.repeated(depth + 1) << "}\n";
current.chop(1);
--depth;
tcpp << tab.repeated(depth + 1) << "break;\n";
}
tcpp << "\t}\n\n";
}
tcpp << "\treturn lngtags_cnt;\n";
tcpp << "}\n\n";
tcpp << "LangKey LangLoader::keyIndex(const QByteArray &key) const {\n";
tcpp << "\tif (key.size() < 5 || !LNG_EQUALS_PART(key, 0, 4, \"lng_\")) return lngkeys_cnt;\n\n";
if (!keys.isEmpty()) {
QString tab("\t");
tcpp << "\tconst char *ch = key.constData(), *e = key.constData() + key.size();\n";
QByteArray current("lng_");
int depth = current.size();
tcpp << "\tswitch (*(ch + " << depth << ")) {\n";
for (LangKeys::const_iterator i = keys.cbegin(), j = i + 1, e = keys.cend(); i != e; ++i) {
QByteArray key = i.key();
while (depth > 0 && key.mid(0, depth) != current) {
tcpp << tab.repeated(depth - 3) << "}\n";
current.chop(1);
--depth;
tcpp << tab.repeated(depth - 3) << "break;\n";
}
do {
if (key == current) break;
char ich = i.key().at(current.size());
tcpp << tab.repeated(current.size() - 3) << "case '" << ich << "':\n";
if (j == e || ich != ((j.key().size() > depth) ? j.key().at(depth) : 0)) {
if (key == current + ich) {
tcpp << tab.repeated(depth - 3) << "\tif (ch + " << (depth + 1) << " == e) return " << key << (keysTags[key].isEmpty() ? "" : "__tagged") << ";\n";
} else {
tcpp << tab.repeated(depth - 3) << "\tif (LNG_EQUALS_TAIL(key, " << (depth + 1) << ", \"" << i.key().mid(depth + 1) << "\")) return " << key << (keysTags[key].isEmpty() ? "" : "__tagged") << ";\n";
}
tcpp << tab.repeated(depth - 3) << "break;\n";
break;
}
++depth;
current += ich;
bool exact = (key == current);
if (exact) {
tcpp << tab.repeated(depth - 3) << "if (ch + " << depth << " == e) {\n";
tcpp << tab.repeated(depth - 3) << "\treturn " << key << (keysTags[key].isEmpty() ? "" : "__tagged") << ";\n";
tcpp << tab.repeated(depth - 3) << "}\n";
}
QByteArray nextkey = j.key();
if (exact && depth > 0 && nextkey.mid(0, depth) != current) {
current.chop(1);
--depth;
tcpp << tab.repeated(depth - 3) << "break;\n";
break;
} else {
tcpp << tab.repeated(depth - 3) << "if (ch + " << depth << " < e) switch (*(ch + " << depth << ")) {\n";
}
} while (true);
++j;
}
while (QByteArray("lng_") != current) {
tcpp << tab.repeated(depth - 3) << "}\n";
current.chop(1);
--depth;
tcpp << tab.repeated(depth - 3) << "break;\n";
}
tcpp << "\t}\n\n";
}
tcpp << "\treturn lngkeys_cnt;\n";
tcpp << "}\n\n";
tcpp << "bool LangLoader::tagReplaced(LangKey key, ushort tag) const {\n";
if (!tags.isEmpty()) {
tcpp << "\tswitch (key) {\n";
for (int i = 0, l = keysOrder.size(); i < l; ++i) {
QVector<QByteArray> &tagsList(keysTags[keysOrder[i]]);
if (tagsList.isEmpty()) continue;
tcpp << "\tcase " << keysOrder[i] << "__tagged: {\n";
tcpp << "\t\tswitch (tag) {\n";
for (int j = 0, s = tagsList.size(); j < s; ++j) {
tcpp << "\t\tcase lt_" << tagsList[j] << ":\n";
}
tcpp << "\t\t\treturn true;\n";
tcpp << "\t\t}\n";
tcpp << "\t} break;\n";
}
tcpp << "\t}\n\n";
}
tcpp << "\treturn false;";
tcpp << "}\n\n";
tcpp << "LangKey LangLoader::subkeyIndex(LangKey key, ushort tag, ushort index) const {\n";
tcpp << "\tif (index >= lngtags_max_counted_values) return lngkeys_cnt;\n\n";
if (!tags.isEmpty()) {
tcpp << "\tswitch (key) {\n";
for (auto key : keysOrder) {
QVector<QByteArray> &tagsList(keysTags[key]);
if (tagsList.isEmpty()) continue;
QMap<QByteArray, QVector<QString> > &countedTags(keysCounted[key]);
bool hasCounted = false;
for (auto tag : tagsList) {
if (!countedTags[tag].isEmpty()) {
hasCounted = true;
break;
}
}
if (!hasCounted) continue;
tcpp << "\tcase " << key << "__tagged: {\n";
tcpp << "\t\tswitch (tag) {\n";
for (auto tag : tagsList) {
if (!countedTags[tag].isEmpty()) {
tcpp << "\t\tcase lt_" << tag << ": return LangKey(" << key << "__" << tag << "0 + index);\n";
}
}
tcpp << "\t\t}\n";
tcpp << "\t} break;\n";
}
tcpp << "\t}\n\n";
}
tcpp << "\treturn lngkeys_cnt;\n";
tcpp << "}\n\n";
tcpp << "bool LangLoader::feedKeyValue(LangKey key, const QString &value) {\n";
tcpp << "\tif (key < lngkeys_cnt) {\n";
tcpp << "\t\t_found[key] = 1;\n";
tcpp << "\t\tif (_langValuesOriginal[key].isEmpty()) {\n";
tcpp << "\t\t\t_langValuesOriginal[key] = _langValues[key].isEmpty() ? qsl(\"{}\") : _langValues[key];\n";
tcpp << "\t\t}\n";
tcpp << "\t\t_langValues[key] = value;\n";
tcpp << "\t\treturn true;\n";
tcpp << "\t}\n";
tcpp << "\treturn false;\n";
tcpp << "}\n\n";
}
QFile cpp(lang_cpp), h(lang_h);
bool write_cpp = true, write_h = true;
if (cpp.open(QIODevice::ReadOnly)) {
QByteArray wasCpp = cpp.readAll();
if (wasCpp.size() == cppText.size()) {
if (!memcmp(wasCpp.constData(), cppText.constData(), cppText.size())) {
write_cpp = false;
}
}
cpp.close();
}
if (write_cpp) {
if (!cpp.open(QIODevice::WriteOnly)) throw Exception("Could not open lang.cpp for writing!");
if (cpp.write(cppText) != cppText.size()) throw Exception("Could not open lang.cpp for writing!");
}
if (h.open(QIODevice::ReadOnly)) {
QByteArray wasH = h.readAll();
if (wasH.size() == hText.size()) {
if (!memcmp(wasH.constData(), hText.constData(), hText.size())) {
write_h = false;
}
}
h.close();
}
if (write_h) {
if (!h.open(QIODevice::WriteOnly)) throw Exception("Could not open lang.h for writing!");
if (h.write(hText) != hText.size()) throw Exception("Could not open lang.h for writing!");
}
} catch (exception &e) {
cout << e.what() << "\n";
QCoreApplication::exit(1);
return false;
}
return true;
}

View File

@@ -1,78 +0,0 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop 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.
It 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.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include <QtCore/QMap>
#include <QtCore/QVector>
#include <QtCore/QFile>
#include <QtCore/QDir>
#include <QtCore/QRegularExpression>
#include <QtGui/QImage>
#include <QtGui/QPainter>
#include <iostream>
#include <exception>
#include <QtCore/QTextStream>
#include <QtCore/QString>
#include <QtCore/QCoreApplication>
using std::string;
using std::cout;
using std::cerr;
using std::exception;
class Exception : public exception {
public:
Exception(const QString &msg) : _msg(msg.toUtf8()) {
}
virtual const char *what() const throw() {
return _msg.constData();
}
virtual ~Exception() throw() {
}
private:
QByteArray _msg;
};
bool genLang(const QString &lang_in, const QString &lang_out);
class GenLang : public QObject {
Q_OBJECT
public:
GenLang(const QString &lang_in, const QString &lang_out) : QObject(0),
_lang_in(lang_in), _lang_out(lang_out) {
}
public slots :
void run() {
if (genLang(_lang_in, _lang_out)) {
emit finished();
}
}
signals:
void finished();
private:
QString _lang_in, _lang_out;
};

View File

@@ -1,54 +0,0 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop 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.
It 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.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "mlmain.h"
int main(int argc, char *argv[]) {
QString lang_in("lang.strings"), lang_out("lang");
for (int i = 0; i < argc; ++i) {
if (string("-lang_in") == argv[i]) {
if (++i < argc) lang_in = argv[i];
} else if (string("-lang_out") == argv[i]) {
if (++i < argc) lang_out = argv[i];
}
}
#ifdef Q_OS_MAC
if (QDir(QString()).absolutePath() == "/") {
QString first = argc ? QString::fromLocal8Bit(argv[0]) : QString();
if (!first.isEmpty()) {
QFileInfo info(first);
if (info.exists()) {
QDir result(info.absolutePath() + "/../../..");
QString basePath = result.absolutePath() + '/';
lang_in = basePath + lang_in;
lang_out = basePath + lang_out;
}
}
}
#endif
QObject *taskImpl = new GenLang(lang_in, lang_out);
QCoreApplication a(argc, argv);
QObject::connect(taskImpl, SIGNAL(finished()), &a, SLOT(quit()));
QTimer::singleShot(0, taskImpl, SLOT(run()));
return a.exec();
}

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "base/timer.h"
#include "core/single_timer.h"
#include "mtproto/sender.h"
namespace Api {
@@ -34,12 +36,9 @@ inline const MTPVector<MTPChat> *getChatsFromMessagesChats(const MTPmessages_Cha
} // namespace Api
class ApiWrap : public QObject, public RPCSender {
Q_OBJECT
class ApiWrap : private MTP::Sender {
public:
ApiWrap(QObject *parent);
void init();
ApiWrap();
using RequestMessageDataCallback = base::lambda<void(ChannelData*, MsgId)>;
void requestMessageData(ChannelData *channel, MsgId msgId, RequestMessageDataCallback callback);
@@ -47,14 +46,16 @@ public:
void requestFullPeer(PeerData *peer);
void requestPeer(PeerData *peer);
void requestPeers(const QList<PeerData*> &peers);
void requestLastParticipants(ChannelData *peer, bool fromStart = true);
void requestBots(ChannelData *peer);
void requestLastParticipants(ChannelData *channel, bool fromStart = true);
void requestBots(ChannelData *channel);
void requestParticipantsCountDelayed(ChannelData *channel);
void processFullPeer(PeerData *peer, const MTPmessages_ChatFull &result);
void processFullPeer(PeerData *peer, const MTPUserFull &result);
void processFullPeer(UserData *user, const MTPUserFull &result);
void requestSelfParticipant(ChannelData *channel);
void kickParticipant(PeerData *peer, UserData *user);
void unblockParticipant(PeerData *peer, UserData *user);
void requestWebPageDelayed(WebPageData *page);
void clearWebPageRequest(WebPageData *page);
@@ -73,6 +74,7 @@ public:
void exportInviteLink(PeerData *peer);
void requestNotifySetting(PeerData *peer);
void saveDraftsToCloud();
void saveDraftToCloudDelayed(History *history);
bool hasUnsavedDrafts() const;
@@ -80,115 +82,82 @@ public:
void handlePrivacyChange(mtpTypeId keyTypeId, const MTPVector<MTPPrivacyRule> &rules);
int onlineTillFromStatus(const MTPUserStatus &status, int currentOnlineTill);
base::Observable<PeerData*> &fullPeerUpdated() {
return _fullPeerUpdated;
}
~ApiWrap();
signals:
void fullPeerUpdated(PeerData *peer);
public slots:
void resolveMessageDatas();
void resolveWebPages();
void delayedRequestParticipantsCount();
void saveDraftsToCloud();
private:
void updatesReceived(const MTPUpdates &updates);
void gotMessageDatas(ChannelData *channel, const MTPmessages_Messages &result, mtpRequestId req);
struct MessageDataRequest {
using Callbacks = QList<RequestMessageDataCallback>;
mtpRequestId req = 0;
mtpRequestId requestId = 0;
Callbacks callbacks;
};
typedef QMap<MsgId, MessageDataRequest> MessageDataRequests;
MessageDataRequests _messageDataRequests;
typedef QMap<ChannelData*, MessageDataRequests> ChannelMessageDataRequests;
ChannelMessageDataRequests _channelMessageDataRequests;
SingleDelayedCall *_messageDataResolveDelayed;
typedef QVector<MTPint> MessageIds;
MessageIds collectMessageIds(const MessageDataRequests &requests);
using MessageDataRequests = QMap<MsgId, MessageDataRequest>;
void updatesReceived(const MTPUpdates &updates);
void resolveMessageDatas();
void gotMessageDatas(ChannelData *channel, const MTPmessages_Messages &result, mtpRequestId requestId);
QVector<MTPint> collectMessageIds(const MessageDataRequests &requests);
MessageDataRequests *messageDataRequests(ChannelData *channel, bool onlyExisting = false);
void gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mtpRequestId req);
void gotUserFull(PeerData *peer, const MTPUserFull &result, mtpRequestId req);
bool gotPeerFullFailed(PeerData *peer, const RPCError &err);
typedef QMap<PeerData*, mtpRequestId> PeerRequests;
PeerRequests _fullPeerRequests;
void gotUserFull(UserData *user, const MTPUserFull &result, mtpRequestId req);
void lastParticipantsDone(ChannelData *peer, const MTPchannels_ChannelParticipants &result, mtpRequestId req);
void resolveWebPages();
void gotWebPages(ChannelData *channel, const MTPmessages_Messages &result, mtpRequestId req);
void gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result);
void gotChat(PeerData *peer, const MTPmessages_Chats &result);
void gotUser(PeerData *peer, const MTPVector<MTPUser> &result);
void gotChats(const MTPmessages_Chats &result);
void gotUsers(const MTPVector<MTPUser> &result);
bool gotPeerFailed(PeerData *peer, const RPCError &err);
PeerData *notifySettingReceived(MTPInputNotifyPeer peer, const MTPPeerNotifySettings &settings);
void stickerSetDisenabled(mtpRequestId requestId);
void stickersSaveOrder();
MessageDataRequests _messageDataRequests;
QMap<ChannelData*, MessageDataRequests> _channelMessageDataRequests;
SingleQueuedInvokation _messageDataResolveDelayed;
using PeerRequests = QMap<PeerData*, mtpRequestId>;
PeerRequests _fullPeerRequests;
PeerRequests _peerRequests;
void lastParticipantsDone(ChannelData *peer, const MTPchannels_ChannelParticipants &result, mtpRequestId req);
bool lastParticipantsFail(ChannelData *peer, const RPCError &error, mtpRequestId req);
PeerRequests _participantsRequests, _botsRequests;
PeerRequests _participantsRequests;
PeerRequests _botsRequests;
base::DelayedCallTimer _participantsCountRequestTimer;
typedef QPair<PeerData*, UserData*> KickRequest;
typedef QMap<KickRequest, mtpRequestId> KickRequests;
void kickParticipantDone(KickRequest kick, const MTPUpdates &updates, mtpRequestId req);
bool kickParticipantFail(KickRequest kick, const RPCError &error, mtpRequestId req);
KickRequests _kickRequests;
void gotSelfParticipant(ChannelData *channel, const MTPchannels_ChannelParticipant &result);
bool gotSelfParticipantFail(ChannelData *channel, const RPCError &error);
typedef QMap<ChannelData*, mtpRequestId> SelfParticipantRequests;
SelfParticipantRequests _selfParticipantRequests;
QMap<ChannelData*, mtpRequestId> _selfParticipantRequests;
void gotWebPages(ChannelData *channel, const MTPmessages_Messages &result, mtpRequestId req);
typedef QMap<WebPageData*, mtpRequestId> WebPagesPending;
WebPagesPending _webPagesPending;
SingleTimer _webPagesTimer;
QMap<WebPageData*, mtpRequestId> _webPagesPending;
base::Timer _webPagesTimer;
QMap<uint64, QPair<uint64, mtpRequestId> > _stickerSetRequests;
void gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result);
bool gotStickerSetFail(uint64 setId, const RPCError &error);
QMap<ChannelData*, mtpRequestId> _channelAmInRequests;
void channelAmInUpdated(ChannelData *channel);
void channelAmInDone(ChannelData *channel, const MTPUpdates &updates);
bool channelAmInFail(ChannelData *channel, const RPCError &error);
QMap<UserData*, mtpRequestId> _blockRequests;
void blockDone(UserData *user, const MTPBool &result);
void unblockDone(UserData *user, const MTPBool &result);
bool blockFail(UserData *user, const RPCError &error);
QMap<PeerData*, mtpRequestId> _exportInviteRequests;
void exportInviteDone(PeerData *peer, const MTPExportedChatInvite &result);
bool exportInviteFail(PeerData *peer, const RPCError &error);
QMap<PeerData*, mtpRequestId> _notifySettingRequests;
void notifySettingDone(MTPInputNotifyPeer peer, const MTPPeerNotifySettings &settings);
PeerData *notifySettingReceived(MTPInputNotifyPeer peer, const MTPPeerNotifySettings &settings);
bool notifySettingFail(PeerData *peer, const RPCError &error);
QMap<History*, mtpRequestId> _draftsSaveRequestIds;
SingleTimer _draftsSaveTimer;
void saveCloudDraftDone(History *history, const MTPBool &result, mtpRequestId requestId);
bool saveCloudDraftFail(History *history, const RPCError &error, mtpRequestId requestId);
base::Timer _draftsSaveTimer;
base::Timer _quitSavingDraftsTimer;
OrderedSet<mtpRequestId> _stickerSetDisenableRequests;
void stickerSetDisenableDone(const MTPmessages_StickerSetInstallResult &result, mtpRequestId req);
bool stickerSetDisenableFail(const RPCError &error, mtpRequestId req);
Stickers::Order _stickersOrder;
mtpRequestId _stickersReorderRequestId = 0;
void stickersSaveOrder();
void stickersReorderDone(const MTPBool &result);
bool stickersReorderFail(const RPCError &result);
mtpRequestId _stickersClearRecentRequestId = 0;
void stickersClearRecentDone(const MTPBool &result);
bool stickersClearRecentFail(const RPCError &result);
QMap<mtpTypeId, mtpRequestId> _privacySaveRequests;
void savePrivacyDone(mtpTypeId keyTypeId, const MTPaccount_PrivacyRules &result);
bool savePrivacyFail(mtpTypeId keyTypeId, const RPCError &error);
mtpRequestId _contactsStatusesRequestId = 0;
void contactsStatusesDone(const MTPVector<MTPContactStatus> &result);
bool contactsStatusesFail(const RPCError &error);
base::Observable<PeerData*> _fullPeerUpdated;
};

View File

@@ -26,7 +26,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "styles/style_overview.h"
#include "styles/style_mediaview.h"
#include "styles/style_stickers.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_history.h"
#include "styles/style_boxes.h"
#include "lang.h"
@@ -191,7 +191,7 @@ namespace App {
}
ApiWrap *api() {
return main() ? main()->api() : 0;
return AuthSession::Exists() ? &AuthSession::Current().api() : nullptr;
}
namespace {
@@ -2466,7 +2466,6 @@ namespace {
if (auto apiwrap = api()) {
if (apiwrap->hasUnsavedDrafts()) {
apiwrap->saveDraftsToCloud();
QTimer::singleShot(SaveDraftBeforeQuitTimeout, QCoreApplication::instance(), SLOT(quit()));
return;
}
}
@@ -2762,12 +2761,19 @@ namespace {
}
void complexOverlayRect(Painter &p, QRect rect, ImageRoundRadius radius, ImageRoundCorners corners) {
auto overlayCorners = (radius == ImageRoundRadius::Small) ? SelectedOverlaySmallCorners : SelectedOverlayLargeCorners;
auto overlayParts = RectPart::Full | RectPart::None;
if (radius == ImageRoundRadius::Large) {
complexAdjustRect(corners, rect, overlayParts);
if (radius == ImageRoundRadius::Ellipse) {
PainterHighQualityEnabler hq(p);
p.setPen(Qt::NoPen);
p.setBrush(p.textPalette().selectOverlay);
p.drawEllipse(rect);
} else {
auto overlayCorners = (radius == ImageRoundRadius::Small) ? SelectedOverlaySmallCorners : SelectedOverlayLargeCorners;
auto overlayParts = RectPart::Full | RectPart::None;
if (radius == ImageRoundRadius::Large) {
complexAdjustRect(corners, rect, overlayParts);
}
roundRect(p, rect, p.textPalette().selectOverlay, overlayCorners, nullptr, overlayParts);
}
roundRect(p, rect, p.textPalette().selectOverlay, overlayCorners, nullptr, overlayParts);
}
void complexLocationRect(Painter &p, QRect rect, ImageRoundRadius radius, ImageRoundCorners corners) {

View File

@@ -26,8 +26,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "storage/localstorage.h"
#include "autoupdater.h"
#include "window/notifications_manager.h"
#include "core/task_queue.h"
#include "messenger.h"
#include "base/timer.h"
namespace {
@@ -347,10 +347,6 @@ void Application::closeApplication() {
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
}
void Application::onMainThreadTask() {
base::TaskQueue::ProcessMainTasks();
}
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
void Application::updateCheck() {
startUpdateCheck(false);
@@ -551,6 +547,7 @@ void adjustSingleTimers() {
if (auto a = application()) {
a->adjustSingleTimers();
}
base::Timer::Adjust();
}
#ifndef TDESKTOP_DISABLE_AUTOUPDATE

View File

@@ -51,8 +51,6 @@ public slots:
void startApplication(); // will be done in exec()
void closeApplication(); // will be done in aboutToQuit()
void onMainThreadTask();
private:
typedef QPair<QLocalSocket*, QByteArray> LocalClient;
typedef QList<LocalClient> LocalClients;

View File

@@ -20,9 +20,18 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "auth_session.h"
#include "apiwrap.h"
#include "messenger.h"
#include "storage/file_download.h"
#include "storage/localstorage.h"
#include "window/notifications_manager.h"
#include "platform/platform_specific.h"
namespace {
constexpr auto kAutoLockTimeoutLateMs = TimeMs(3000);
} // namespace
QByteArray AuthSessionData::serialize() const {
auto size = sizeof(qint32) * 2;
@@ -39,6 +48,7 @@ QByteArray AuthSessionData::serialize() const {
stream.setVersion(QDataStream::Qt_5_1);
stream << static_cast<qint32>(_variables.emojiPanelTab);
stream << qint32(_variables.lastSeenWarningSeen ? 1 : 0);
stream << qint32(_variables.tabbedSelectorSectionEnabled ? 1 : 0);
}
return result;
}
@@ -57,8 +67,12 @@ void AuthSessionData::constructFromSerialized(const QByteArray &serialized) {
stream.setVersion(QDataStream::Qt_5_1);
qint32 emojiPanTab = static_cast<qint32>(EmojiPanelTab::Emoji);
qint32 lastSeenWarningSeen = 0;
qint32 tabbedSelectorSectionEnabled = 1;
stream >> emojiPanTab;
stream >> lastSeenWarningSeen;
if (!stream.atEnd()) {
stream >> tabbedSelectorSectionEnabled;
}
if (stream.status() != QDataStream::Ok) {
LOG(("App Error: Bad data for AuthSessionData::constructFromSerialized()"));
return;
@@ -71,17 +85,30 @@ void AuthSessionData::constructFromSerialized(const QByteArray &serialized) {
case EmojiPanelTab::Gifs: _variables.emojiPanelTab = uncheckedTab; break;
}
_variables.lastSeenWarningSeen = (lastSeenWarningSeen == 1);
_variables.tabbedSelectorSectionEnabled = (tabbedSelectorSectionEnabled == 1);
}
AuthSession::AuthSession(UserId userId)
: _userId(userId)
, _autoLockTimer([this] { checkAutoLock(); })
, _api(std::make_unique<ApiWrap>())
, _downloader(std::make_unique<Storage::Downloader>())
, _notifications(std::make_unique<Window::Notifications::System>(this)) {
Expects(_userId != 0);
_saveDataTimer.setCallback([this] {
Local::writeUserSettings();
});
subscribe(Messenger::Instance().passcodedChanged(), [this] {
_shouldLockAt = 0;
notifications().updateAll();
});
}
bool AuthSession::Exists() {
return (Messenger::Instance().authSession() != nullptr);
if (auto messenger = Messenger::InstancePointer()) {
return (messenger->authSession() != nullptr);
}
return false;
}
AuthSession &AuthSession::Current() {
@@ -107,4 +134,34 @@ bool AuthSession::validateSelf(const MTPUser &user) {
return true;
}
void AuthSession::saveDataDelayed(TimeMs delay) {
Expects(this == &AuthSession::Current());
_saveDataTimer.callOnce(delay);
}
void AuthSession::checkAutoLock() {
if (!Global::LocalPasscode() || App::passcoded()) return;
Messenger::Instance().checkLocalTime();
auto now = getms(true);
auto shouldLockInMs = Global::AutoLock() * 1000LL;
auto idleForMs = psIdleTime();
auto notPlayingVideoForMs = now - data().lastTimeVideoPlayedAt();
auto checkTimeMs = qMin(idleForMs, notPlayingVideoForMs);
if (checkTimeMs >= shouldLockInMs || (_shouldLockAt > 0 && now > _shouldLockAt + kAutoLockTimeoutLateMs)) {
Messenger::Instance().setupPasscode();
} else {
_shouldLockAt = now + (shouldLockInMs - checkTimeMs);
_autoLockTimer.callOnce(shouldLockInMs - checkTimeMs);
}
}
void AuthSession::checkAutoLockIn(TimeMs time) {
if (_autoLockTimer.isActive()) {
auto remain = _autoLockTimer.remainingTime();
if (remain > 0 && remain <= time) return;
}
_autoLockTimer.callOnce(time);
}
AuthSession::~AuthSession() = default;

View File

@@ -20,6 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "base/timer.h"
namespace Storage {
class Downloader;
} // namespace Storage
@@ -30,6 +32,8 @@ class System;
} // namespace Notifications
} // namespace Window
class ApiWrap;
enum class EmojiPanelTab {
Emoji,
Stickers,
@@ -69,11 +73,24 @@ public:
void setEmojiPanelTab(EmojiPanelTab tab) {
_variables.emojiPanelTab = tab;
}
bool tabbedSelectorSectionEnabled() const {
return _variables.tabbedSelectorSectionEnabled;
}
void setTabbedSelectorSectionEnabled(bool enabled) {
_variables.tabbedSelectorSectionEnabled = enabled;
}
void setLastTimeVideoPlayedAt(TimeMs time) {
_lastTimeVideoPlayedAt = time;
}
TimeMs lastTimeVideoPlayedAt() const {
return _lastTimeVideoPlayedAt;
}
private:
struct Variables {
bool lastSeenWarningSeen = false;
EmojiPanelTab emojiPanelTab = EmojiPanelTab::Emoji;
bool tabbedSelectorSectionEnabled = true;
};
base::Variable<bool> _contactsLoaded = { false };
@@ -81,10 +98,11 @@ private:
base::Observable<void> _moreChatsLoaded;
base::Observable<void> _savedGifsUpdated;
Variables _variables;
TimeMs _lastTimeVideoPlayedAt = 0;
};
class AuthSession final {
class AuthSession final : private base::Subscriber {
public:
AuthSession(UserId userId);
@@ -120,13 +138,26 @@ public:
AuthSessionData &data() {
return _data;
}
void saveDataDelayed(TimeMs delay);
ApiWrap &api() {
return *_api;
}
void checkAutoLock();
void checkAutoLockIn(TimeMs time);
~AuthSession();
private:
UserId _userId = 0;
const UserId _userId = 0;
AuthSessionData _data;
base::Timer _saveDataTimer;
TimeMs _shouldLockAt = 0;
base::Timer _autoLockTimer;
const std::unique_ptr<ApiWrap> _api;
const std::unique_ptr<Storage::Downloader> _downloader;
const std::unique_ptr<Window::Notifications::System> _notifications;

View File

@@ -31,7 +31,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#elif defined(_WIN32) // __APPLE__ || __linux__
#define OS_WIN 1
#else // __APPLE__ || __linux__ || _WIN32
#error Please add support for your platform in core/build_config.h
#error Please add support for your platform in base/build_config.h
#endif // else for __APPLE__ || __linux__ || _WIN32
// For access to standard POSIXish features, use OS_POSIX instead of a
@@ -48,7 +48,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#elif defined(_MSC_VER) // __clang__ || __GNUC__
#define COMPILER_MSVC 1
#else // _MSC_VER || __clang__ || __GNUC__
#error Please add support for your compiler in core/build_config.h
#error Please add support for your compiler in base/build_config.h
#endif // else for _MSC_VER || __clang__ || __GNUC__
// Processor architecture detection.
@@ -61,7 +61,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#define ARCH_CPU_X86 1
#define ARCH_CPU_32_BITS 1
#else
#error Please add support for your architecture in core/build_config.h
#error Please add support for your architecture in base/build_config.h
#endif
#if defined(COMPILER_GCC) || defined(COMPILER_CLANG)

View File

@@ -18,7 +18,7 @@ to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "core/observer.h"
#include "base/observer.h"
namespace base {
namespace internal {

View File

@@ -22,7 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include <vector>
#include <deque>
#include "core/type_traits.h"
#include "base/type_traits.h"
namespace base {
namespace internal {

View File

@@ -18,7 +18,7 @@ to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "core/parse_helper.h"
#include "base/parse_helper.h"
namespace base {
namespace parse {

View File

@@ -18,7 +18,7 @@ to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "core/qthelp_url.h"
#include "base/qthelp_url.h"
namespace qthelp {

View File

@@ -18,7 +18,7 @@ to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "core/runtime_composer.h"
#include "base/runtime_composer.h"
struct RuntimeComposerMetadatasMap {
QMap<uint64, RuntimeComposerMetadata*> data;

View File

@@ -18,7 +18,7 @@ to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "core/task_queue.h"
#include "base/task_queue.h"
#include <thread>
#include <condition_variable>

View File

@@ -0,0 +1,141 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop 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.
It 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.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "base/timer.h"
namespace base {
namespace {
QObject *TimersAdjuster() {
static QObject adjuster;
return &adjuster;
}
} // namespace
Timer::Timer(base::lambda<void()> callback) : QObject(nullptr)
, _callback(std::move(callback))
, _type(Qt::PreciseTimer)
, _adjusted(false) {
setRepeat(Repeat::Interval);
connect(TimersAdjuster(), &QObject::destroyed, this, [this] { adjust(); }, Qt::QueuedConnection);
}
void Timer::start(TimeMs timeout, Qt::TimerType type, Repeat repeat) {
cancel();
_type = type;
setRepeat(repeat);
_adjusted = false;
setTimeout(timeout);
_timerId = startTimer(_timeout, _type);
if (_timerId) {
_next = getms(true) + _timeout;
} else {
_next = 0;
}
}
void Timer::cancel() {
if (isActive()) {
killTimer(base::take(_timerId));
}
}
TimeMs Timer::remainingTime() const {
if (!isActive()) {
return -1;
}
auto now = getms(true);
return (_next > now) ? (_next - now) : TimeMs(0);
}
void Timer::Adjust() {
QObject emitter;
connect(&emitter, &QObject::destroyed, TimersAdjuster(), &QObject::destroyed);
}
void Timer::adjust() {
auto remaining = remainingTime();
if (remaining >= 0) {
cancel();
_timerId = startTimer(remaining, _type);
_adjusted = true;
}
}
void Timer::setTimeout(TimeMs timeout) {
Expects(timeout >= 0 && timeout <= std::numeric_limits<int>::max());
_timeout = static_cast<unsigned int>(timeout);
}
int Timer::timeout() const {
return _timeout;
}
void Timer::timerEvent(QTimerEvent *e) {
if (repeat() == Repeat::Interval) {
if (_adjusted) {
start(_timeout, _type, repeat());
} else {
_next = getms(true) + _timeout;
}
} else {
cancel();
}
if (_callback) {
_callback();
}
}
int DelayedCallTimer::call(TimeMs timeout, lambda_once<void()> callback, Qt::TimerType type) {
Expects(timeout >= 0);
if (!callback) {
return 0;
}
auto timerId = startTimer(static_cast<int>(timeout), type);
if (timerId) {
_callbacks.emplace(timerId, std::move(callback));
}
return timerId;
}
void DelayedCallTimer::cancel(int callId) {
if (callId) {
killTimer(callId);
_callbacks.erase(callId);
}
}
void DelayedCallTimer::timerEvent(QTimerEvent *e) {
auto timerId = e->timerId();
killTimer(timerId);
auto it = _callbacks.find(timerId);
if (it != _callbacks.end()) {
auto callback = std::move(it->second);
_callbacks.erase(it);
callback();
}
}
} // namespace base

View File

@@ -0,0 +1,115 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop 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.
It 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.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "base/lambda.h"
#include "base/observer.h"
namespace base {
class Timer final : private QObject {
public:
Timer(base::lambda<void()> callback = base::lambda<void()>());
static Qt::TimerType DefaultType(TimeMs timeout) {
constexpr auto kThreshold = TimeMs(1000);
return (timeout > kThreshold) ? Qt::CoarseTimer : Qt::PreciseTimer;
}
void setCallback(base::lambda<void()> callback) {
_callback = std::move(callback);
}
void callOnce(TimeMs timeout) {
callOnce(timeout, DefaultType(timeout));
}
void callEach(TimeMs timeout) {
callEach(timeout, DefaultType(timeout));
}
void callOnce(TimeMs timeout, Qt::TimerType type) {
start(timeout, type, Repeat::SingleShot);
}
void callEach(TimeMs timeout, Qt::TimerType type) {
start(timeout, type, Repeat::Interval);
}
bool isActive() const {
return (_timerId != 0);
}
void cancel();
TimeMs remainingTime() const;
static void Adjust();
protected:
void timerEvent(QTimerEvent *e) override;
private:
enum class Repeat : unsigned {
Interval = 0,
SingleShot = 1,
};
void start(TimeMs timeout, Qt::TimerType type, Repeat repeat);
void adjust();
void setTimeout(TimeMs timeout);
int timeout() const;
void setRepeat(Repeat repeat) {
_repeat = static_cast<unsigned>(repeat);
}
Repeat repeat() const {
return static_cast<Repeat>(_repeat);
}
base::lambda<void()> _callback;
TimeMs _next = 0;
int _timeout = 0;
int _timerId = 0;
Qt::TimerType _type : 2;
bool _adjusted : 1;
unsigned _repeat : 1;
};
class DelayedCallTimer final : private QObject {
public:
int call(TimeMs timeout, lambda_once<void()> callback) {
return call(timeout, std::move(callback), Timer::DefaultType(timeout));
}
int call(TimeMs timeout, lambda_once<void()> callback, Qt::TimerType type);
void cancel(int callId);
protected:
void timerEvent(QTimerEvent *e) override;
private:
std::map<int, lambda_once<void()>> _callbacks; // Better to use flatmap.
};
} // namespace base

View File

@@ -18,13 +18,13 @@ to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "boxes/aboutbox.h"
#include "boxes/about_box.h"
#include "lang.h"
#include "mainwidget.h"
#include "mainwindow.h"
#include "autoupdater.h"
#include "boxes/confirmbox.h"
#include "boxes/confirm_box.h"
#include "application.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h"

View File

@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "boxes/abstractbox.h"
#include "boxes/abstract_box.h"
namespace Ui {
class LinkButton;

View File

@@ -18,7 +18,7 @@ to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "boxes/abstractbox.h"
#include "boxes/abstract_box.h"
#include "styles/style_boxes.h"
#include "storage/localstorage.h"
@@ -194,7 +194,8 @@ void BoxContent::paintEvent(QPaintEvent *e) {
}
}
AbstractBox::AbstractBox(QWidget *parent, object_ptr<BoxContent> content) : LayerWidget(parent)
AbstractBox::AbstractBox(QWidget *parent, Window::Controller *controller, object_ptr<BoxContent> content) : LayerWidget(parent)
, _controller(controller)
, _content(std::move(content)) {
_content->setParent(this);
_content->setDelegate(this);

View File

@@ -31,6 +31,10 @@ template <typename Widget>
class WidgetFadeWrap;
} // namespace Ui
namespace Window {
class Controller;
} // namespace Window
class BoxLayerTitleShadow : public Ui::PlainShadow {
public:
BoxLayerTitleShadow(QWidget *parent);
@@ -39,6 +43,8 @@ public:
class BoxContentDelegate {
public:
virtual Window::Controller *controller() const = 0;
virtual void setLayerType(bool layerType) = 0;
virtual void setTitle(const QString &title, const QString &additional) = 0;
@@ -61,8 +67,6 @@ public:
BoxContent() {
setAttribute(Qt::WA_OpaquePaintEvent);
}
BoxContent(QWidget*) : BoxContent() {
}
bool isBoxShown() const {
return getDelegate()->isBoxShown();
@@ -107,6 +111,10 @@ public slots:
protected:
virtual void prepare() = 0;
Window::Controller *controller() {
return getDelegate()->controller();
}
void setLayerType(bool layerType) {
getDelegate()->setLayerType(layerType);
}
@@ -165,7 +173,7 @@ private:
object_ptr<TWidget> doTakeInnerWidget();
BoxContentDelegate *getDelegate() const {
t_assert(_delegate != nullptr);
Expects(_delegate != nullptr);
return _delegate;
}
BoxContentDelegate *_delegate = nullptr;
@@ -183,8 +191,11 @@ private:
class AbstractBox : public LayerWidget, public BoxContentDelegate, protected base::Subscriber {
public:
AbstractBox(QWidget *parent, object_ptr<BoxContent> content);
AbstractBox(QWidget *parent, Window::Controller *controller, object_ptr<BoxContent> content);
Window::Controller *controller() const override {
return _controller;
}
void parentResized() override;
void setLayerType(bool layerType) override;
@@ -235,6 +246,7 @@ private:
int countRealHeight() const;
void updateSize();
Window::Controller *_controller = nullptr;
int _fullHeight = 0;
bool _noContentMargin = false;

View File

@@ -18,15 +18,15 @@ to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "boxes/addcontactbox.h"
#include "boxes/add_contact_box.h"
#include "styles/style_boxes.h"
#include "styles/style_dialogs.h"
#include "lang.h"
#include "messenger.h"
#include "boxes/contactsbox.h"
#include "boxes/confirmbox.h"
#include "boxes/photocropbox.h"
#include "boxes/contacts_box.h"
#include "boxes/confirm_box.h"
#include "boxes/photo_crop_box.h"
#include "core/file_utilities.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h"
@@ -1060,7 +1060,7 @@ bool EditChannelBox::onSaveFail(const RPCError &error, mtpRequestId req) {
if (err == qstr("CHAT_ABOUT_NOT_MODIFIED")) {
if (_channel->setAbout(_sentDescription)) {
if (App::api()) {
emit App::api()->fullPeerUpdated(_channel);
App::api()->fullPeerUpdated().notify(_channel);
}
}
saveSign();
@@ -1090,7 +1090,7 @@ void EditChannelBox::onSaveDescriptionDone(const MTPBool &result) {
_saveDescriptionRequestId = 0;
if (_channel->setAbout(_sentDescription)) {
if (App::api()) {
emit App::api()->fullPeerUpdated(_channel);
App::api()->fullPeerUpdated().notify(_channel);
}
}
saveSign();

View File

@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "boxes/abstractbox.h"
#include "boxes/abstract_box.h"
class ConfirmBox;

View File

@@ -18,7 +18,7 @@ to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "boxes/autolockbox.h"
#include "boxes/autolock_box.h"
#include "lang.h"
#include "storage/localstorage.h"
@@ -52,6 +52,6 @@ void AutoLockBox::durationChanged(int seconds) {
Local::writeUserSettings();
Global::RefLocalPasscodeChanged().notify();
App::wnd()->checkAutoLock();
AuthSession::Current().checkAutoLock();
closeBox();
}

View File

@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "boxes/abstractbox.h"
#include "boxes/abstract_box.h"
namespace Ui {
class Radiobutton;

View File

@@ -18,7 +18,7 @@ to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "boxes/backgroundbox.h"
#include "boxes/background_box.h"
#include "lang.h"
#include "mainwidget.h"

View File

@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "boxes/abstractbox.h"
#include "boxes/abstract_box.h"
namespace Ui {
class RoundCheckbox;

View File

@@ -270,6 +270,7 @@ contactsSearchCancel: CrossButton {
crossPosition: point(4px, 4px);
duration: 150;
loadingPeriod: 1000;
ripple: RippleAnimation(defaultRippleAnimation) {
color: windowBgOver;
}
@@ -483,11 +484,6 @@ autoDownloadTopDelta: 10px;
autoDownloadTitlePosition: point(23px, 18px);
autoDownloadTitleFont: font(15px semibold);
editTextArea: InputField(defaultInputField) {
textMargins: margins(1px, 26px, 1px, 4px);
heightMax: 276px;
}
confirmCaptionArea: InputField(defaultInputField) {
textMargins: margins(1px, 26px, 1px, 4px);
heightMax: 78px;

View File

@@ -18,7 +18,7 @@ to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "boxes/calendarbox.h"
#include "boxes/calendar_box.h"
#include "ui/widgets/buttons.h"
#include "styles/style_boxes.h"

View File

@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "abstractbox.h"
#include "abstract_box.h"
namespace Ui {
class IconButton;

View File

@@ -25,9 +25,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "ui/widgets/labels.h"
#include "ui/widgets/input_fields.h"
#include "ui/effects/widget_fade_wrap.h"
#include "boxes/confirmphonebox.h"
#include "boxes/confirm_phone_box.h"
#include "ui/toast/toast.h"
#include "boxes/confirmbox.h"
#include "boxes/confirm_box.h"
namespace {

View File

@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "boxes/abstractbox.h"
#include "boxes/abstract_box.h"
class ChangePhoneBox : public BoxContent {
public:

View File

@@ -18,7 +18,7 @@ to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "boxes/confirmbox.h"
#include "boxes/confirm_box.h"
#include "styles/style_boxes.h"
#include "lang.h"
@@ -312,25 +312,21 @@ void ConvertToSupergroupBox::convertToSupergroup() {
void ConvertToSupergroupBox::convertDone(const MTPUpdates &updates) {
Ui::hideLayer();
App::main()->sentUpdatesReceived(updates);
const QVector<MTPChat> *v = 0;
switch (updates.type()) {
case mtpc_updates: v = &updates.c_updates().vchats.v; break;
case mtpc_updatesCombined: v = &updates.c_updatesCombined().vchats.v; break;
default: LOG(("API Error: unexpected update cons %1 (ConvertToSupergroupBox::convertDone)").arg(updates.type())); break;
}
PeerData *peer = 0;
if (v && !v->isEmpty()) {
for (int32 i = 0, l = v->size(); i < l; ++i) {
if (v->at(i).type() == mtpc_channel) {
peer = App::channel(v->at(i).c_channel().vid.v);
Ui::showPeerHistory(peer, ShowAtUnreadMsgId);
QTimer::singleShot(ReloadChannelMembersTimeout, App::api(), SLOT(delayedRequestParticipantsCount()));
auto handleChats = [](auto &mtpChats) {
for_const (auto &mtpChat, mtpChats.v) {
if (mtpChat.type() == mtpc_channel) {
auto channel = App::channel(mtpChat.c_channel().vid.v);
Ui::showPeerHistory(channel, ShowAtUnreadMsgId);
App::api()->requestParticipantsCountDelayed(channel);
}
}
}
if (!peer) {
LOG(("API Error: channel not found in updates (ProfileInner::migrateDone)"));
};
switch (updates.type()) {
case mtpc_updates: handleChats(updates.c_updates().vchats); break;
case mtpc_updatesCombined: handleChats(updates.c_updatesCombined().vchats); break;
default: LOG(("API Error: unexpected update cons %1 (ConvertToSupergroupBox::convertDone)").arg(updates.type())); break;
}
}

View File

@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "boxes/abstractbox.h"
#include "boxes/abstract_box.h"
namespace Ui {
class Checkbox;

View File

@@ -18,10 +18,10 @@ to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "boxes/confirmphonebox.h"
#include "boxes/confirm_phone_box.h"
#include "styles/style_boxes.h"
#include "boxes/confirmbox.h"
#include "boxes/confirm_box.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "ui/widgets/labels.h"

View File

@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "boxes/abstractbox.h"
#include "boxes/abstract_box.h"
#include "ui/widgets/input_fields.h"
namespace Ui {

View File

@@ -18,7 +18,7 @@ to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "boxes/connectionbox.h"
#include "boxes/connection_box.h"
#include "lang.h"
#include "storage/localstorage.h"
@@ -269,10 +269,9 @@ void AutoDownloadBox::onSave() {
bool enabledGroups = ((cAutoDownloadAudio() & dbiadNoGroups) && !(autoDownloadAudio & dbiadNoGroups));
cSetAutoDownloadAudio(autoDownloadAudio);
if (enabledPrivate || enabledGroups) {
const DocumentsData &data(App::documentsData());
for (DocumentsData::const_iterator i = data.cbegin(), e = data.cend(); i != e; ++i) {
if (i.value()->voice()) {
i.value()->automaticLoadSettingsChanged();
for (auto document : App::documentsData()) {
if (document->voice()) {
document->automaticLoadSettingsChanged();
}
}
}
@@ -284,10 +283,9 @@ void AutoDownloadBox::onSave() {
bool enabledGroups = ((cAutoDownloadGif() & dbiadNoGroups) && !(autoDownloadGif & dbiadNoGroups));
cSetAutoDownloadGif(autoDownloadGif);
if (enabledPrivate || enabledGroups) {
const DocumentsData &data(App::documentsData());
for (DocumentsData::const_iterator i = data.cbegin(), e = data.cend(); i != e; ++i) {
if (i.value()->isAnimation()) {
i.value()->automaticLoadSettingsChanged();
for (auto document : App::documentsData()) {
if (document->isAnimation()) {
document->automaticLoadSettingsChanged();
}
}
}

View File

@@ -20,7 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "boxes/abstractbox.h"
#include "boxes/abstract_box.h"
namespace Ui {
class InputField;

View File

@@ -18,7 +18,7 @@ to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "boxes/contactsbox.h"
#include "boxes/contacts_box.h"
#include "dialogs/dialogs_indexed_list.h"
#include "styles/style_boxes.h"
@@ -26,7 +26,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "styles/style_history.h"
#include "styles/style_profile.h"
#include "lang.h"
#include "boxes/addcontactbox.h"
#include "boxes/add_contact_box.h"
#include "mainwidget.h"
#include "mainwindow.h"
#include "messenger.h"
@@ -37,8 +37,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "ui/widgets/scroll_area.h"
#include "ui/effects/widget_slide_wrap.h"
#include "ui/effects/ripple_animation.h"
#include "boxes/photocropbox.h"
#include "boxes/confirmbox.h"
#include "boxes/photo_crop_box.h"
#include "boxes/confirm_box.h"
#include "window/themes/window_theme.h"
#include "observer_peer.h"
#include "apiwrap.h"

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