Compare commits

...

49 Commits

Author SHA1 Message Date
John Preston
d32e476d96 version 0.8.50.dev fixed crash in Go to FAQ 2015-08-14 19:31:29 +03:00
John Preston
856502a06a Merge branch 'master' of https://github.com/telegramdesktop/tdesktop 2015-08-14 18:50:03 +03:00
John Preston
48ee79ed9d langs updated for 0.8.50.dev 2015-08-14 18:49:49 +03:00
John Preston
1897dad06b Merge branch 'master' of https://github.com/telegramdesktop/tdesktop 2015-08-14 18:48:18 +03:00
John Preston
a95822b2ec version 0.8.50.dev - fixes in Windows toast notifications support, fixes in linux input methods 2015-08-14 18:47:56 +03:00
John Preston
4cb22530ae Merge branch 'master' of https://github.com/telegramdesktop/tdesktop 2015-08-14 18:30:24 +03:00
John Preston
fa501b18e4 crashfix in sending audio files 2015-08-14 18:24:40 +03:00
John Preston
9002a49fcc added patch for fcitx input in linux 2015-08-13 18:26:38 +03:00
John Preston
6621171e60 Merge branch 'master' of https://github.com/telegramdesktop/tdesktop 2015-08-13 18:11:18 +03:00
John Preston
c16ea77c52 altering AppUserModelId in pinned shortcut in Windows 2015-08-13 18:11:07 +03:00
John Preston
efa62ece72 added fcitx inputcontext plugin for linux version 2015-08-13 18:09:04 +03:00
telegramdesktop
869194f16a Merge pull request #819 from ner0x652/patch-1
Update README.md with a new supported OS
2015-08-13 15:36:10 +03:00
telegramdesktop
b5c4c34164 Merge pull request #843 from NgoHuy/ibus
Add Ibus supported by Qt5 officially
2015-08-13 15:23:21 +03:00
John Preston
30e96a1d5e improved translation, 0.8.49.dev 2015-08-12 21:09:03 +03:00
John Preston
82dc07ee42 fixed warnings, version 0.8.49.dev 2015-08-12 21:05:25 +03:00
John Preston
6a41d307bb Merge branch 'master' of https://github.com/telegramdesktop/tdesktop 2015-08-12 21:02:31 +03:00
John Preston
afac237f03 improved window activation in os x 2015-08-12 21:02:20 +03:00
John Preston
8511181508 version 0.8.49.dev - block/unblock users in profile, ask question and faq link in Settings, Windows 8/8.1/10 toast notifications 2015-08-12 21:01:32 +03:00
John Preston
cf9737e762 Windows 8/8.1/10 toast notifications support added 2015-08-11 22:50:48 +03:00
John Preston
1b16064db6 0.8.48 stable version with clear history and conversation search 2015-08-08 12:28:34 +03:00
John Preston
bcd8334263 Merge branch 'master' of https://github.com/telegramdesktop/tdesktop 2015-08-08 12:23:20 +03:00
John Preston
897699dd04 langs updated 2015-08-08 12:22:47 +03:00
John Preston
3a97bfd110 deadlock fixed in mtpConnection 2015-08-08 12:14:47 +03:00
John Preston
9792d5df76 fixed warnings, version 0.8.47.dev 2015-08-07 15:20:19 +03:00
John Preston
5dd8eab606 version 0.8.47.dev - search in conversation, clear history, delete conversation, saving cleared conversations locally, removed contacts from left column 2015-08-07 15:11:50 +03:00
John Preston
61729119c5 Merge branch 'dev' of https://github.com/telegramdesktop/tdesktop 2015-08-05 18:27:09 +03:00
John Preston
6225bd3bcb fixed crash on sticker send, version 0.8.46 2015-08-05 16:48:27 +03:00
John Preston
aabf136690 search in conversation, clear history and delete conversation for all chats 2015-08-04 18:01:47 +03:00
John Preston
ad8e3f36ad fixed pointer, version 0.8.45 2015-08-03 13:22:05 +03:00
John Preston
0d381870a7 Merge branch 'master' of https://github.com/telegramdesktop/tdesktop 2015-08-03 13:05:56 +03:00
John Preston
2a66ab036c Merge branch 'master' of https://github.com/telegramdesktop/tdesktop 2015-08-03 12:59:55 +03:00
John Preston
af948466f4 langs updated, version 0.8.45 2015-08-03 12:59:41 +03:00
John Preston
d50f3f475f fixed crash in send actions 2015-08-03 11:25:25 +03:00
John Preston
df78831592 trying appindicator first in xfce 2015-08-02 22:15:26 +03:00
John Preston
a0dc865bdc version 0.8.45 stable 2015-08-02 21:07:46 +03:00
John Preston
878604225c langs updated 2015-08-02 21:04:53 +03:00
John Preston
85d0c42d73 Merge branch 'master' of https://github.com/telegramdesktop/tdesktop 2015-08-02 20:40:58 +03:00
John Preston
c89ee8224c gnome using custom tray icon, win10 multiple desktops shadow fix 2015-08-02 20:40:44 +03:00
John Preston
bf74d02079 Merge branch 'dev' of https://github.com/telegramdesktop/tdesktop into dev 2015-08-02 11:07:34 +03:00
John Preston
a9a4623c63 fixed photosendbox doc and contact display 2015-08-02 11:07:26 +03:00
John Preston
b9022ada09 Merge branch 'dev' of https://github.com/telegramdesktop/tdesktop into dev 2015-08-01 16:13:00 +03:00
John Preston
f290fef3a3 added XCODEold.md to git 2015-08-01 15:56:30 +03:00
John Preston
29b8596439 instructions updated 2015-08-01 15:56:10 +03:00
John Preston
14ae657073 improved deploy script 2015-08-01 11:34:56 +03:00
John Preston
637b6d9e6e Merge branch 'dev' of https://github.com/telegramdesktop/tdesktop into dev 2015-08-01 11:33:45 +03:00
John Preston
86325e889f 0.8.44 dev version - media typings support 2015-08-01 11:33:00 +03:00
John Preston
84a790f3cd added mac32 version for deploy 2015-07-31 17:26:37 +03:00
Severus
0647bbba0e Add Ibus symbol to Qt5 inputmethod 2015-06-21 10:20:56 +07:00
Cornel Punga
8e1c10463f Update README.md with a new supported OS
It also work on Fedora 22. Tested!
2015-06-11 12:34:35 +03:00
116 changed files with 25460 additions and 876 deletions

View File

@@ -76,6 +76,16 @@ then go to **/home/user/TBuild/Libraries/openal-soft/build** and run
make
sudo make install
####libxkbcommon (required for Fcitx Qt plugin)
In Terminal go to **/home/user/TBuild/Libraries** and run
sudo apt-get install xutils-dev bison python-xcbgen
git clone https://github.com/xkbcommon/libxkbcommon.git
./autogen.sh --disable-x11
make
sudo make install
####Qt 5.5.0, slightly patched
http://download.qt-project.org/official_releases/qt/5.5/5.5.0/single/qt-everywhere-opensource-src-5.5.0.tar.gz

View File

@@ -6,13 +6,15 @@ Source code is published under GPL v3, license is available [here](https://githu
###Supported systems
* Windows XP - Windows 8.1 (**not** RT)
* Mac OS X 10.7 - Mac OS X 10.10
* Windows XP - Windows 10 (**not** RT)
* Mac OS X 10.8 - Mac OS X 10.10
* Mac OS X 10.6 - Mac OS X 10.7 (separate build)
* Ubuntu 12.04 - Ubuntu 14.04
* Fedora 22
###Third-party
* Qt 5.5.0, slightly patched ([LGPL](http://qt-project.org/doc/qt-5/lgpl.html))
* Qt 5.3.2 and 5.5.0, slightly patched ([LGPL](http://qt-project.org/doc/qt-5/lgpl.html))
* OpenSSL 1.0.1g ([OpenSSL License](https://www.openssl.org/source/license.html))
* zlib 1.2.8 ([zlib License](http://www.zlib.net/zlib_license.html))
* libexif 0.6.20 ([LGPL](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html))
@@ -27,6 +29,8 @@ Source code is published under GPL v3, license is available [here](https://githu
###[Build instructions for XCode 6.4](https://github.com/telegramdesktop/tdesktop/blob/master/XCODE.md)
###[Build instructions for XCode 6.4 for OS X 10.6 and 10.7](https://github.com/telegramdesktop/tdesktop/blob/master/XCODEold.md)
###[Build instructions for Qt Creator 3.2.0 Ubuntu](https://github.com/telegramdesktop/tdesktop/blob/master/QTCREATOR.md)
##Projects in Telegram solution
@@ -58,15 +62,12 @@ for Mac:
####MetaEmoji
from two folders
* SourceFiles/art/Emoji
* SourceFiles/art/Emoji_200x
and some inner config creates four sprites and text2emoji replace code
creates four sprites and text2emoji replace code
* SourceFiles/art/emoji.png
* SourceFiles/art/emoji_125x.png
* SourceFiles/art/emoji_150x.png
* SourceFiles/art/emoji_200x.png
* SourceFiles/art/emoji_250x.png
* SourceFiles/gui/emoji_config.cpp
####MetaStyle

View File

@@ -17,6 +17,16 @@ if [ ! -f "./../Mac/Release/deploy/$AppVersionStrMajor/$AppVersionStr$DevPostfix
exit 1
fi
if [ ! -f "./../../tother/tmac32/$AppVersionStrMajor/$AppVersionStr$DevPostfix/tmac32upd$AppVersion" ]; then
echo "tmac32upd$AppVersion not found!"
exit 1
fi
if [ ! -f "./../../tother/tmac32/$AppVersionStrMajor/$AppVersionStr$DevPostfix/tsetup32.$AppVersionStr$DevPostfix.dmg" ]; then
echo "tsetup32.$AppVersionStr$DevPostfix.dmg not found!"
exit 1
fi
if [ ! -f "./../../tother/tsetup/$AppVersionStrMajor/$AppVersionStr$DevPostfix/tupdate$AppVersion" ]; then
echo "tupdate$AppVersion not found!"
exit 1
@@ -38,6 +48,8 @@ fi
scp ./../Mac/Release/deploy/$AppVersionStrMajor/$AppVersionStr$DevPostfix/tmacupd$AppVersion tmaster:tdesktop/www/tmac/
scp ./../Mac/Release/deploy/$AppVersionStrMajor/$AppVersionStr$DevPostfix/tsetup.$AppVersionStr$DevPostfix.dmg tmaster:tdesktop/www/tmac/
scp ./../../tother/tmac32/$AppVersionStrMajor/$AppVersionStr$DevPostfix/tmac32upd$AppVersion tmaster:tdesktop/www/tmac32/
scp ./../../tother/tmac32/$AppVersionStrMajor/$AppVersionStr$DevPostfix/tsetup32.$AppVersionStr$DevPostfix.dmg tmaster:tdesktop/www/tmac32/
scp ./../../tother/tsetup/$AppVersionStrMajor/$AppVersionStr$DevPostfix/tupdate$AppVersion tmaster:tdesktop/www/tsetup/
scp ./../../tother/tsetup/$AppVersionStrMajor/$AppVersionStr$DevPostfix/tportable.$AppVersionStr$DevPostfix.zip tmaster:tdesktop/www/tsetup/
scp ./../../tother/tsetup/$AppVersionStrMajor/$AppVersionStr$DevPostfix/tsetup.$AppVersionStr$DevPostfix.exe tmaster:tdesktop/www/tsetup/
@@ -47,4 +59,7 @@ mv -v ./../../tother/tsetup/$AppVersionStrMajor/$AppVersionStr$DevPostfix ./../.
cp -v ./../Mac/Release/deploy/$AppVersionStrMajor/$AppVersionStr$DevPostfix/tmacupd$AppVersion ./../../../Dropbox/Telegram/deploy/$AppVersionStrMajor/$AppVersionStr$DevPostfix/
cp -v ./../Mac/Release/deploy/$AppVersionStrMajor/$AppVersionStr$DevPostfix/tsetup.$AppVersionStr$DevPostfix.dmg ./../../../Dropbox/Telegram/deploy/$AppVersionStrMajor/$AppVersionStr$DevPostfix/
cp -rv ./../Mac/Release/deploy/$AppVersionStrMajor/$AppVersionStr$DevPostfix/Telegram.app.dSYM ./../../../Dropbox/Telegram/deploy/$AppVersionStrMajor/$AppVersionStr$DevPostfix/
cp -v ./../../tother/tmac32/$AppVersionStrMajor/$AppVersionStr$DevPostfix/tmac32upd$AppVersion ./../../../Dropbox/Telegram/deploy/$AppVersionStrMajor/$AppVersionStr$DevPostfix/
cp -v ./../../tother/tmac32/$AppVersionStrMajor/$AppVersionStr$DevPostfix/tsetup32.$AppVersionStr$DevPostfix.dmg ./../../../Dropbox/Telegram/deploy/$AppVersionStrMajor/$AppVersionStr$DevPostfix/
cp -rv ./../../tother/tmac32/$AppVersionStrMajor/$AppVersionStr$DevPostfix/Telegram.app.dSYM ./../../../Dropbox/Telegram/deploy/$AppVersionStrMajor/$AppVersionStr$DevPostfix/Telegram32.app.dSYM

View File

@@ -46,7 +46,7 @@ if [ ! -d "./../Linux/Release/deploy/$AppVersionStrMajor" ]; then
mkdir "./../Linux/Release/deploy/$AppVersionStrMajor"
fi
echo "Copying Telegram, Updater and tlinuxupd$AppVersion to deploy/$AppVersionStr$DevPostfix..";
echo "Copying Telegram, Updater and tlinuxupd$AppVersion to deploy/$AppVersionStrMajor/$AppVersionStr$DevPostfix..";
mkdir "./../Linux/Release/deploy/$AppVersionStrMajor/$AppVersionStr$DevPostfix"
mkdir "./../Linux/Release/deploy/$AppVersionStrMajor/$AppVersionStr$DevPostfix/Telegram"
mv ./../Linux/Release/Telegram ./../Linux/Release/deploy/$AppVersionStrMajor/$AppVersionStr$DevPostfix/Telegram/

View File

@@ -46,7 +46,7 @@ if [ ! -d "./../Linux/Release/deploy/$AppVersionStrMajor" ]; then
mkdir "./../Linux/Release/deploy/$AppVersionStrMajor"
fi
echo "Copying Telegram, Updater and tlinux32upd$AppVersion to deploy/$AppVersionStr$DevPostfix..";
echo "Copying Telegram, Updater and tlinux32upd$AppVersion to deploy/$AppVersionStrMajor/$AppVersionStr$DevPostfix..";
mkdir "./../Linux/Release/deploy/$AppVersionStrMajor/$AppVersionStr$DevPostfix"
mkdir "./../Linux/Release/deploy/$AppVersionStrMajor/$AppVersionStr$DevPostfix/Telegram"
mv ./../Linux/Release/Telegram ./../Linux/Release/deploy/$AppVersionStrMajor/$AppVersionStr$DevPostfix/Telegram/

View File

@@ -1,11 +1,11 @@
@echo OFF
set "AppVersionStrMajor=0.8"
set "AppVersion=8043"
set "AppVersionStrSmall=0.8.43"
set "AppVersionStr=0.8.43"
set "AppVersionStrFull=0.8.43.0"
set "DevChannel=0"
set "AppVersion=8050"
set "AppVersionStrSmall=0.8.50"
set "AppVersionStr=0.8.50"
set "AppVersionStrFull=0.8.50.0"
set "DevChannel=1"
if %DevChannel% neq 0 goto preparedev

View File

@@ -28,7 +28,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_open_from_tray" = "Open Telegram";
"lng_minimize_to_tray" = "Minimize to tray";
"lng_quit_from_tray" = "Quit Telegram";
"lng_tray_icon_text" = "Telegram is still running here,\nyou can change this from settings page.\n\nIf this icon disappears from tray menu,\nyou can drag it back here from hidden icons.";
"lng_tray_icon_text" = "Telegram is still running here,\nyou can change this from settings page.\nIf this icon disappears from tray menu,\nyou can drag it here from hidden icons.";
"lng_month1" = "January";
"lng_month2" = "February";
@@ -69,6 +69,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_reconnecting_try_now" = "Try now";
"lng_status_service_notifications" = "service notifications";
"lng_status_support" = "support";
"lng_status_bot" = "bot";
"lng_status_bot_reads_all" = "has access to messages";
"lng_status_bot_not_reads_all" = "has no access to messages";
@@ -156,8 +157,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_dlg_new_group_name" = "Group name";
"lng_dlg_create_group" = "Create";
"lng_no_contacts" = "You have no contacts";
"lng_no_chats" = "Your chats will be here";
"lng_contacts_loading" = "Loading..";
"lng_contacts_not_found" = "No contacts found";
"lng_dlg_search_chat" = "Search in this chat";
"lng_dlg_search_for_messages" = "Search for messages";
"lng_settings_save" = "Save";
"lng_settings_upload" = "Set Profile Photo";
@@ -182,6 +186,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_desktop_notify" = "Desktop notifications";
"lng_settings_show_name" = "Show sender's name";
"lng_settings_show_preview" = "Show message preview";
"lng_settings_use_windows" = "Use Windows notifications";
"lng_settings_sound_notify" = "Play sound";
"lng_notification_preview" = "You have a new message";
@@ -320,6 +325,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_reset_one_sure" = "Do you want to terminate this session?";
"lng_settings_reset_button" = "Terminate";
"lng_settings_reset_done" = "Other sessions terminated";
"lng_settings_ask_question" = "Ask a Question";
"lng_settings_ask_sure" = "Please note that Telegram Support is done by volunteers. We try to respond as quickly as possible, but it may take a while.\n\nPlease take a look at the Telegram FAQ: it has important troubleshooting tips and answers to most questions.";
"lng_settings_faq_button" = "Go to FAQ";
"lng_settings_ask_ok" = "Ask";
"lng_settings_faq" = "Telegram FAQ";
"lng_settings_logout" = "Log Out";
"lng_sure_logout" = "Are you sure you want to log out?";
@@ -339,6 +349,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_topbar_info" = "Info";
"lng_profile_about_section" = "About";
"lng_profile_settings_section" = "Settings";
"lng_profile_actions_section" = "Actions";
"lng_profile_bot_settings" = "Settings";
"lng_profile_bot_help" = "Help";
"lng_profile_participants_section" = "Members";
@@ -348,6 +359,13 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_profile_edit_contact" = "Edit";
"lng_profile_enable_notifications" = "Notifications";
"lng_profile_clear_history" = "Clear history";
"lng_profile_delete_conversation" = "Delete conversation";
"lng_profile_clear_and_exit" = "Delete and exit";
"lng_profile_search_messages" = "Search for messages";
"lng_profile_block_user" = "Block user";
"lng_profile_unblock_user" = "Unblock user";
"lng_profile_block_bot" = "Stop and block bot";
"lng_profile_unblock_bot" = "Unblock bot";
"lng_profile_send_message" = "Send Message";
"lng_profile_share_contact" = "Share Contact";
"lng_profile_invite_to_group" = "Add to Group";
@@ -379,9 +397,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_create_group_title" = "New Group";
"lng_failed_add_participant" = "Could not add user. Try again later.";
"lng_failed_add_not_mutual" = "Sorry, if a person left a group, only a\nmutual contact can bring them back\n(they need to have your phone\nnumber, and you need theirs).";
"lng_sure_delete_contact" = "Are you sure, you want to delete {contact} from your contact list?";
"lng_sure_delete_history" = "Are you sure, you want to delete all message history with {contact}?\n\nThis action cannot be undone.";
"lng_sure_delete_group_history" = "Are you sure, you want to delete all message history in «{group}»?\n\nThis action cannot be undone.";
"lng_sure_delete_and_exit" = "Are you sure, you want to delete all message history and leave «{group}»?\n\nThis action cannot be undone.";
@@ -462,10 +482,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_message_ph" = "Write a message..";
"lng_record_cancel" = "Release outside this field to cancel";
"lng_empty_history" = "";
"lng_willbe_history" = "Please select chat to start messaging";
"lng_willbe_history" = "Please select a chat to start messaging";
"lng_message_with_from" = "[c]{from}:[/c] {message}";
"lng_from_you" = "You";
"lng_bot_description" = "What can this bot do?";
"lng_unblock_button" = "Unblock";
"lng_bot_start" = "Start";
"lng_bot_choose_group" = "Choose Group";
@@ -478,6 +499,22 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_user_typing" = "{user} is typing";
"lng_users_typing" = "{user} and {second_user} are typing";
"lng_many_typing" = "{count:_not_used_|# is|# are} typing";
"lng_send_action_record_video" = "recording video";
"lng_user_action_record_video" = "{user} is recording video";
"lng_send_action_upload_video" = "sending video";
"lng_user_action_upload_video" = "{user} is sending video";
"lng_send_action_record_audio" = "recording audio";
"lng_user_action_record_audio" = "{user} is recording audio";
"lng_send_action_upload_audio" = "sending audio";
"lng_user_action_upload_audio" = "{user} is sending audio";
"lng_send_action_upload_photo" = "sending photo";
"lng_user_action_upload_photo" = "{user} is sending photo";
"lng_send_action_upload_file" = "sending file";
"lng_user_action_upload_file" = "{user} is sending file";
"lng_send_action_geo_location" = "picking location";
"lng_user_action_geo_location" = "{user} is picking location";
"lng_send_action_choose_contact" = "choosing contact";
"lng_user_action_choose_contact" = "{user} is choosing contact";
"lng_unread_bar" = "{count:_not_used_|# unread message|# unread messages}";
"lng_maps_point" = "Location";
@@ -604,7 +641,7 @@ Copyright (c) 2014 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" = "— Improved in-app media playback\n— Bug fixes and other minor improvements";
"lng_new_version_text" = "— Block users from their profile page\n— Added support for Windows toast notifications\n— Fixed input methods on Linux (Fcitx and IBus)";
"lng_menu_insert_unicode" = "Insert Unicode control character";

View File

@@ -972,6 +972,11 @@ btnSend: flatButton(btnDefFlat) {
font: font(16px);
overFont: font(16px);
}
btnUnblock: flatButton(btnSend) {
color: #d15948;
overColor: #d15948;
downColor: #db6352;
}
btnAttachDocument: iconedButton(btnDefIconed) {
icon: sprite(218px, 68px, 24px, 24px);

View File

@@ -199,6 +199,7 @@ void ApiWrap::gotUserFull(PeerData *peer, const MTPUserFull &result) {
App::main()->gotNotifySetting(MTP_inputNotifyPeer(peer->input), d.vnotify_settings);
peer->asUser()->setBotInfo(d.vbot_info);
peer->asUser()->blocked = d.vblocked.v ? UserIsBlocked : UserIsNotBlocked;
_fullPeerRequests.remove(peer);
App::clearPeerUpdated(peer);
@@ -225,6 +226,23 @@ void ApiWrap::requestPeer(PeerData *peer) {
_peerRequests.insert(peer, req);
}
void ApiWrap::requestPeers(const QList<PeerData*> &peers) {
QVector<MTPint> chats;
QVector<MTPInputUser> users;
chats.reserve(peers.size());
users.reserve(peers.size());
for (QList<PeerData*>::const_iterator i = peers.cbegin(), e = peers.cend(); i != e; ++i) {
if (!*i || _fullPeerRequests.contains(*i) || _peerRequests.contains(*i)) continue;
if ((*i)->chat) {
chats.push_back(MTP_int(App::chatFromPeer((*i)->id)));
} else {
users.push_back((*i)->asUser()->inputUser);
}
}
if (!chats.isEmpty()) MTP::send(MTPmessages_GetChats(MTP_vector<MTPint>(chats)), rpcDone(&ApiWrap::gotChats));
if (!users.isEmpty()) MTP::send(MTPusers_GetUsers(MTP_vector<MTPInputUser>(users)), rpcDone(&ApiWrap::gotUsers));
}
void ApiWrap::gotChat(PeerData *peer, const MTPmessages_Chats &result) {
_peerRequests.remove(peer);
@@ -249,6 +267,14 @@ void ApiWrap::gotUser(PeerData *peer, const MTPVector<MTPUser> &result) {
}
}
void ApiWrap::gotChats(const MTPmessages_Chats &result) {
App::feedChats(result.c_messages_chats().vchats);
}
void ApiWrap::gotUsers(const MTPVector<MTPUser> &result) {
App::feedUsers(result);
}
bool ApiWrap::gotPeerFailed(PeerData *peer, const RPCError &error) {
if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false;

View File

@@ -32,6 +32,7 @@ public:
void requestFullPeer(PeerData *peer);
void requestPeer(PeerData *peer);
void requestPeers(const QList<PeerData*> &peers);
void requestWebPageDelayed(WebPageData *page);
void clearWebPageRequest(WebPageData *page);
@@ -72,6 +73,8 @@ private:
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);
PeerRequests _peerRequests;

View File

@@ -289,8 +289,10 @@ namespace App {
}
QString onlineText(UserData *user, int32 now, bool precise) {
if (isServiceUser(user->id)) {
if (isNotificationsUser(user->id)) {
return lang(lng_status_service_notifications);
} else if (isServiceUser(user->id)) {
return lang(lng_status_support);
} else if (user->botInfo) {
return lang(lng_status_bot);
}
@@ -370,8 +372,8 @@ namespace App {
PeerId peer(peerFromUser(d.vid.v));
data = App::user(peer);
data->input = MTP_inputPeerContact(d.vid);
data->inputUser = MTP_inputUserContact(d.vid);
data->input = MTP_inputPeerUser(d.vid, MTP_long(0));
data->inputUser = MTP_inputUser(d.vid, MTP_long(0));
data->setName(lang(lng_deleted), QString(), QString(), QString());
data->setPhoto(MTP_userProfilePhotoEmpty());
data->access = UserNoAccess;
@@ -389,12 +391,12 @@ namespace App {
if (flags & MTPDuser_flag_self) {
data->input = MTP_inputPeerSelf();
data->inputUser = MTP_inputUserSelf();
} else if ((flags & (MTPDuser_flag_contact | MTPDuser_flag_mutual_contact)) || !d.has_access_hash()) {
data->input = MTP_inputPeerContact(d.vid);
data->inputUser = MTP_inputUserContact(d.vid);
} else if (!d.has_access_hash()) {
data->input = MTP_inputPeerUser(d.vid, MTP_long((data->access == UserNoAccess) ? 0 : data->access));
data->inputUser = MTP_inputUser(d.vid, MTP_long((data->access == UserNoAccess) ? 0 : data->access));
} else {
data->input = MTP_inputPeerForeign(d.vid, d.vaccess_hash);
data->inputUser = MTP_inputUserForeign(d.vid, d.vaccess_hash);
data->input = MTP_inputPeerUser(d.vid, d.vaccess_hash);
data->inputUser = MTP_inputUser(d.vid, d.vaccess_hash);
}
if (flags & MTPDuser_flag_deleted) {
data->setPhone(QString());
@@ -416,6 +418,8 @@ namespace App {
bool showPhone = !isServiceUser(data->id) && !(flags & (MTPDuser_flag_self | MTPDuser_flag_contact | MTPDuser_flag_mutual_contact));
bool showPhoneChanged = !isServiceUser(data->id) && !(flags & (MTPDuser_flag_self)) && ((showPhone && data->contact) || (!showPhone && !data->contact));
// see also Local::readPeer
QString pname = (showPhoneChanged || phoneChanged || nameChanged) ? ((showPhone && !phone.isEmpty()) ? formatPhone(phone) : QString()) : data->nameOrPhone;
data->setName(fname, lname, pname, uname);
@@ -500,7 +504,6 @@ namespace App {
data->count = d.vparticipants_count.v;
data->left = d.vleft.v;
data->forbidden = false;
data->access = 0;
if (data->version < d.vversion.v) {
data->version = d.vversion.v;
data->participants = ChatData::Participants();
@@ -519,7 +522,6 @@ namespace App {
data->count = -1;
data->left = false;
data->forbidden = true;
data->access = 0;
} break;
case mtpc_geoChat: {
const MTPDgeoChat &d(chat.c_geoChat());
@@ -760,27 +762,23 @@ namespace App {
return ImagePtr();
}
StorageImageLocation imageLocation(int32 w, int32 h, const MTPFileLocation &loc) {
if (loc.type() == mtpc_fileLocation) {
const MTPDfileLocation &l(loc.c_fileLocation());
return StorageImageLocation(w, h, l.vdc_id.v, l.vvolume_id.v, l.vlocal_id.v, l.vsecret.v);
}
return StorageImageLocation(w, h, 0, 0, 0, 0);
}
StorageImageLocation imageLocation(const MTPPhotoSize &size) {
switch (size.type()) {
case mtpc_photoSize: {
const MTPDphotoSize &d(size.c_photoSize());
if (d.vlocation.type() == mtpc_fileLocation) {
const MTPDfileLocation &l(d.vlocation.c_fileLocation());
return StorageImageLocation(d.vw.v, d.vh.v, l.vdc_id.v, l.vvolume_id.v, l.vlocal_id.v, l.vsecret.v);
}
return imageLocation(d.vw.v, d.vh.v, d.vlocation);
} break;
case mtpc_photoCachedSize: {
const MTPDphotoCachedSize &d(size.c_photoCachedSize());
if (d.vlocation.type() == mtpc_fileLocation) {
const MTPDfileLocation &l(d.vlocation.c_fileLocation());
const string &s(d.vbytes.c_string().v);
QByteArray bytes(s.data(), s.size());
return StorageImageLocation(d.vw.v, d.vh.v, l.vdc_id.v, l.vvolume_id.v, l.vlocal_id.v, l.vsecret.v);
} else if (d.vlocation.type() == mtpc_fileLocationUnavailable) {
const string &s(d.vbytes.c_string().v);
QByteArray bytes(s.data(), s.size());
return StorageImageLocation(d.vw.v, d.vh.v, 0, 0, 0, 0);
}
return imageLocation(d.vw.v, d.vh.v, d.vlocation);
} break;
}
return StorageImageLocation();
@@ -872,14 +870,8 @@ namespace App {
if (user->contact > 0) {
if (!wasContact) {
App::main()->addNewContact(App::userFromPeer(user->id), false);
if (user->input.type() != mtpc_inputPeerSelf) user->input = MTP_inputPeerContact(userId);
if (user->inputUser.type() != mtpc_inputUserSelf) user->inputUser = MTP_inputUserContact(userId);
}
} else {
if (user->access && user->access != UserNoAccess) {
if (user->input.type() != mtpc_inputPeerSelf) user->input = MTP_inputPeerForeign(userId, MTP_long(user->access));
if (user->inputUser.type() != mtpc_inputUserSelf) user->inputUser = MTP_inputUserForeign(userId, MTP_long(user->access));
}
if (user->contact < 0 && !user->phone.isEmpty() && App::userFromPeer(user->id) != MTP::authedId()) {
user->contact = 0;
}
@@ -928,7 +920,7 @@ namespace App {
return feedPhoto(photo.c_photo(), convert);
} break;
case mtpc_photoEmpty: {
return App::photoSet(photo.c_photoEmpty().vid.v, convert, 0, 0, 0, ImagePtr(), ImagePtr(), ImagePtr());
return App::photoSet(photo.c_photoEmpty().vid.v, convert, 0, 0, ImagePtr(), ImagePtr(), ImagePtr());
} break;
}
return App::photo(0);
@@ -972,7 +964,7 @@ namespace App {
switch (photo.type()) {
case mtpc_photo: {
const MTPDphoto &ph(photo.c_photo());
return App::photoSet(ph.vid.v, 0, ph.vaccess_hash.v, ph.vuser_id.v, ph.vdate.v, ImagePtr(*thumb, "JPG"), ImagePtr(*medium, "JPG"), ImagePtr(*full, "JPG"));
return App::photoSet(ph.vid.v, 0, ph.vaccess_hash.v, ph.vdate.v, ImagePtr(*thumb, "JPG"), ImagePtr(*medium, "JPG"), ImagePtr(*full, "JPG"));
} break;
case mtpc_photoEmpty: return App::photo(photo.c_photoEmpty().vid.v);
}
@@ -1027,13 +1019,13 @@ namespace App {
}
}
if (thumb && medium && full) {
return App::photoSet(photo.vid.v, convert, photo.vaccess_hash.v, photo.vuser_id.v, photo.vdate.v, App::image(*thumb), App::image(*medium), App::image(*full));
return App::photoSet(photo.vid.v, convert, photo.vaccess_hash.v, photo.vdate.v, App::image(*thumb), App::image(*medium), App::image(*full));
}
return App::photoSet(photo.vid.v, convert, 0, 0, 0, ImagePtr(), ImagePtr(), ImagePtr());
return App::photoSet(photo.vid.v, convert, 0, 0, ImagePtr(), ImagePtr(), ImagePtr());
}
VideoData *feedVideo(const MTPDvideo &video, VideoData *convert) {
return App::videoSet(video.vid.v, convert, video.vaccess_hash.v, video.vuser_id.v, video.vdate.v, video.vduration.v, video.vw.v, video.vh.v, App::image(video.vthumb), video.vdc_id.v, video.vsize.v);
return App::videoSet(video.vid.v, convert, video.vaccess_hash.v, video.vdate.v, video.vduration.v, video.vw.v, video.vh.v, App::image(video.vthumb), video.vdc_id.v, video.vsize.v);
}
AudioData *feedAudio(const MTPaudio &audio, AudioData *convert) {
@@ -1042,14 +1034,14 @@ namespace App {
return feedAudio(audio.c_audio(), convert);
} break;
case mtpc_audioEmpty: {
return App::audioSet(audio.c_audioEmpty().vid.v, convert, 0, 0, 0, QString(), 0, 0, 0);
return App::audioSet(audio.c_audioEmpty().vid.v, convert, 0, 0, QString(), 0, 0, 0);
} break;
}
return App::audio(0);
}
AudioData *feedAudio(const MTPDaudio &audio, AudioData *convert) {
return App::audioSet(audio.vid.v, convert, audio.vaccess_hash.v, audio.vuser_id.v, audio.vdate.v, qs(audio.vmime_type), audio.vduration.v, audio.vdc_id.v, audio.vsize.v);
return App::audioSet(audio.vid.v, convert, audio.vaccess_hash.v, audio.vdate.v, qs(audio.vmime_type), audio.vduration.v, audio.vdc_id.v, audio.vsize.v);
}
DocumentData *feedDocument(const MTPdocument &document, const QPixmap &thumb) {
@@ -1176,7 +1168,7 @@ namespace App {
return i.value();
}
PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 user, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full) {
PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full) {
if (convert) {
if (convert->id != photo) {
PhotosData::iterator i = photosData.find(convert->id);
@@ -1186,8 +1178,7 @@ namespace App {
convert->id = photo;
}
convert->access = access;
if (!convert->user && !convert->date && (user || date)) {
convert->user = user;
if (!convert->date && date) {
convert->date = date;
convert->thumb = thumb;
convert->medium = medium;
@@ -1201,14 +1192,13 @@ namespace App {
if (convert) {
result = convert;
} else {
result = new PhotoData(photo, access, user, date, thumb, medium, full);
result = new PhotoData(photo, access, date, thumb, medium, full);
}
photosData.insert(photo, result);
} else {
result = i.value();
if (result != convert && !result->user && !result->date && (user || date)) {
if (result != convert && !result->date && date) {
result->access = access;
result->user = user;
result->date = date;
result->thumb = thumb;
result->medium = medium;
@@ -1238,7 +1228,7 @@ namespace App {
return i.value();
}
VideoData *videoSet(const VideoId &video, VideoData *convert, const uint64 &access, int32 user, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size) {
VideoData *videoSet(const VideoId &video, VideoData *convert, const uint64 &access, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size) {
if (convert) {
if (convert->id != video) {
VideosData::iterator i = videosData.find(convert->id);
@@ -1249,8 +1239,7 @@ namespace App {
convert->status = FileReady;
}
convert->access = access;
if (!convert->user && !convert->date && (user || date)) {
convert->user = user;
if (!convert->date && date) {
convert->date = date;
convert->duration = duration;
convert->w = w;
@@ -1266,14 +1255,13 @@ namespace App {
if (convert) {
result = convert;
} else {
result = new VideoData(video, access, user, date, duration, w, h, thumb, dc, size);
result = new VideoData(video, access, date, duration, w, h, thumb, dc, size);
}
videosData.insert(video, result);
} else {
result = i.value();
if (result != convert && !result->user && !result->date && (user || date)) {
if (result != convert && !result->date && date) {
result->access = access;
result->user = user;
result->date = date;
result->duration = duration;
result->w = w;
@@ -1294,7 +1282,7 @@ namespace App {
return i.value();
}
AudioData *audioSet(const AudioId &audio, AudioData *convert, const uint64 &access, int32 user, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) {
AudioData *audioSet(const AudioId &audio, AudioData *convert, const uint64 &access, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) {
if (convert) {
if (convert->id != audio) {
AudiosData::iterator i = audiosData.find(convert->id);
@@ -1305,8 +1293,7 @@ namespace App {
convert->status = FileReady;
}
convert->access = access;
if (!convert->user && !convert->date && (user || date)) {
convert->user = user;
if (!convert->date && date) {
convert->date = date;
convert->mime = mime;
convert->duration = duration;
@@ -1320,14 +1307,13 @@ namespace App {
if (convert) {
result = convert;
} else {
result = new AudioData(audio, access, user, date, mime, duration, dc, size);
result = new AudioData(audio, access, date, mime, duration, dc, size);
}
audiosData.insert(audio, result);
} else {
result = i.value();
if (result != convert && !result->user && !result->date && (user || date)) {
if (result != convert && !result->date && date) {
result->access = access;
result->user = user;
result->date = date;
result->mime = mime;
result->duration = duration;
@@ -1551,7 +1537,7 @@ namespace App {
photoSizes.push_back(MTP_photoSize(MTP_string("a"), uphoto.vphoto_small, MTP_int(160), MTP_int(160), MTP_int(0)));
photoSizes.push_back(MTP_photoSize(MTP_string("c"), uphoto.vphoto_big, MTP_int(640), MTP_int(640), MTP_int(0)));
return MTP_photo(uphoto.vphoto_id, MTP_long(0), userId, date, MTP_geoPointEmpty(), MTP_vector<MTPPhotoSize>(photoSizes));
return MTP_photo(uphoto.vphoto_id, MTP_long(0), date, MTP_vector<MTPPhotoSize>(photoSizes));
}
return MTP_photoEmpty(MTP_long(0));
}
@@ -1697,6 +1683,8 @@ namespace App {
randomData.clear();
mutedPeers.clear();
updatedPeers.clear();
cSetSavedPeers(SavedPeers());
cSetSavedPeersByTime(SavedPeersByTime());
for (PeersData::const_iterator i = peersData.cbegin(), e = peersData.cend(); i != e; ++i) {
delete *i;
}
@@ -1752,15 +1740,6 @@ namespace App {
}
}
/* // don't delete history without deleting its' peerdata
void deleteHistory(const PeerId &peer) {
Histories::iterator i = ::histories.find(peer);
if (i != ::histories.end()) {
::histories.typing.remove(i.value());
::histories.erase(i);
}
}
/**/
void historyRegRandom(uint64 randomId, MsgId itemId) {
randomData.insert(randomId, itemId);
}

View File

@@ -127,6 +127,7 @@ namespace App {
int32 maxMsgId();
ImagePtr image(const MTPPhotoSize &size);
StorageImageLocation imageLocation(int32 w, int32 h, const MTPFileLocation &loc);
StorageImageLocation imageLocation(const MTPPhotoSize &size);
PhotoData *feedPhoto(const MTPPhoto &photo, const PreparedPhotoThumbs &thumbs);
@@ -157,11 +158,11 @@ namespace App {
ChatData *chat(int32 chat);
QString peerName(const PeerData *peer, bool forDialogs = false);
PhotoData *photo(const PhotoId &photo);
PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 user, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full);
PhotoData *photoSet(const PhotoId &photo, PhotoData *convert, const uint64 &access, int32 date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full);
VideoData *video(const VideoId &video);
VideoData *videoSet(const VideoId &video, VideoData *convert, const uint64 &access, int32 user, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size);
VideoData *videoSet(const VideoId &video, VideoData *convert, const uint64 &access, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size);
AudioData *audio(const AudioId &audio);
AudioData *audioSet(const AudioId &audio, AudioData *convert, const uint64 &access, int32 user, int32 date, const QString &mime, int32 duration, int32 dc, int32 size);
AudioData *audioSet(const AudioId &audio, AudioData *convert, const uint64 &access, int32 date, const QString &mime, int32 duration, int32 dc, int32 size);
DocumentData *document(const DocumentId &document);
DocumentData *documentSet(const DocumentId &document, DocumentData *convert, const uint64 &access, int32 date, const QVector<MTPDocumentAttribute> &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation);
WebPageData *webPage(const WebPageId &webPage);
@@ -183,7 +184,6 @@ namespace App {
void historyClearItems();
void historyRegReply(HistoryReply *reply, HistoryItem *to);
void historyUnregReply(HistoryReply *reply, HistoryItem *to);
// void deleteHistory(const PeerId &peer);
void historyRegRandom(uint64 randomId, MsgId itemId);
void historyUnregRandom(uint64 randomId);

View File

@@ -110,7 +110,6 @@ Application::Application(int &argc, char **argv) : PsApplication(argc, argv),
}
mainApp = this;
installEventFilter(new EventFilterForKeys(this));
QFontDatabase::addApplicationFont(qsl(":/gui/art/fonts/OpenSans-Regular.ttf"));
@@ -474,7 +473,7 @@ void Application::uploadProfilePhoto(const QImage &tosend, const PeerId &peerId)
PhotoId id = MTP::nonce<PhotoId>();
MTPPhoto photo(MTP_photo(MTP_long(id), MTP_long(0), MTP_int(MTP::authedId()), MTP_int(unixtime()), MTP_geoPointEmpty(), MTP_vector<MTPPhotoSize>(photoSizes)));
MTPPhoto photo(MTP_photo(MTP_long(id), MTP_long(0), MTP_int(unixtime()), MTP_vector<MTPPhotoSize>(photoSizes)));
QString file, filename;
int32 filesize = 0;
@@ -655,13 +654,12 @@ void Application::socketError(QLocalSocket::LocalSocketError e) {
void Application::checkMapVersion() {
if (Local::oldMapVersion() < AppVersion) {
psRegisterCustomScheme();
if (Local::oldMapVersion()) {
QString versionFeatures;
if (cDevVersion() && Local::oldMapVersion() < 8042) {
versionFeatures = QString::fromUtf8("\xe2\x80\x94 Dev version will now get updated to stable as well");// .replace('@', qsl("@") + QChar(0x200D));
} else if (!cDevVersion() && Local::oldMapVersion() < 8043) {
versionFeatures = lang(lng_new_version_minor).trimmed();
if (cDevVersion() && Local::oldMapVersion() < 8050) {
versionFeatures = QString::fromUtf8("\xe2\x80\x94 Bug fixes in Windows notifications\n\xe2\x80\x94 Fixed input methods on Linux (Fcitx and IBus)");// .replace('@', qsl("@") + QChar(0x200D));
} else if (!cDevVersion() && Local::oldMapVersion() < 8048) {
versionFeatures = lang(lng_new_version_text).trimmed();
}
if (!versionFeatures.isEmpty()) {
versionFeatures = lng_new_version_wrap(lt_version, QString::fromStdWString(AppVersionStr), lt_changes, versionFeatures, lt_link, qsl("https://desktop.telegram.org/#changelog"));

View File

@@ -1099,7 +1099,11 @@ public:
}
freq = fmtContext->streams[streamId]->codec->sample_rate;
len = (fmtContext->streams[streamId]->duration * freq * fmtContext->streams[streamId]->time_base.num) / fmtContext->streams[streamId]->time_base.den;
if (fmtContext->streams[streamId]->duration == AV_NOPTS_VALUE) {
len = (fmtContext->duration * freq) / AV_TIME_BASE;
} else {
len = (fmtContext->streams[streamId]->duration * freq * fmtContext->streams[streamId]->time_base.num) / fmtContext->streams[streamId]->time_base.den;
}
uint64_t layout = fmtContext->streams[streamId]->codec->channel_layout;
inputFormat = fmtContext->streams[streamId]->codec->sample_fmt;
switch (layout) {
@@ -2221,7 +2225,9 @@ public:
int res = 0;
char err[AV_ERROR_MAX_STRING_SIZE] = { 0 };
if ((res = avformat_open_input(&fmtContext, 0, 0, 0)) < 0) {
DEBUG_LOG(("Audio Read Error: Unable to avformat_open_input for file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
ioBuffer = 0;
DEBUG_LOG(("Audio Read Error: Unable to avformat_open_input for file '%1', data size '%2', error %3, %4").arg(fname).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res)));
return false;
}
_opened = true;
@@ -2244,7 +2250,11 @@ public:
}
freq = fmtContext->streams[streamId]->codec->sample_rate;
len = (fmtContext->streams[streamId]->duration * freq) / fmtContext->streams[streamId]->time_base.den;
if (fmtContext->streams[streamId]->duration == AV_NOPTS_VALUE) {
len = (fmtContext->duration * freq) / AV_TIME_BASE;
} else {
len = (fmtContext->streams[streamId]->duration * freq * fmtContext->streams[streamId]->time_base.num) / fmtContext->streams[streamId]->time_base.den;
}
for (int32 i = 0, l = fmtContext->nb_streams; i < l; ++i) {
AVStream *stream = fmtContext->streams[i];

View File

@@ -56,19 +56,24 @@ void ConfirmBox::init(const QString &text) {
_confirm.hide();
_cancel.hide();
connect(&_close, SIGNAL(clicked()), this, SLOT(onClose()));
connect(&_close, SIGNAL(clicked()), this, SLOT(onCancel()));
setMouseTracking(_text.hasLinks());
} else {
_close.hide();
connect(&_confirm, SIGNAL(clicked()), this, SIGNAL(confirmed()));
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onCancel()));
}
prepare();
}
void ConfirmBox::onCancel() {
emit cancelPressed();
onClose();
}
void ConfirmBox::mouseMoveEvent(QMouseEvent *e) {
_lastMousePos = e->globalPos();
updateHover();

View File

@@ -35,10 +35,15 @@ public:
void leaveEvent(QEvent *e);
void updateLink();
public slots:
void onCancel();
signals:
void confirmed();
void cancelled();
void cancelPressed();
protected:

View File

@@ -60,7 +60,7 @@ _byUsernameSel(-1),
_addContactLnk(this, lang(lng_add_contact_button)) {
DialogsIndexed &v(App::main()->dialogsList());
for (DialogRow *r = v.list.begin; r != v.list.end; r = r->next) {
if (r->history->peer->chat && !r->history->peer->asChat()->forbidden) {
if (r->history->peer->chat && !r->history->peer->asChat()->forbidden && !r->history->peer->asChat()->left) {
_contacts->addToEnd(r->history);
}
}
@@ -104,7 +104,7 @@ void ContactsInner::onAddBot() {
void ContactsInner::peerUpdated(PeerData *peer) {
if (_chat && (!peer || peer == _chat)) {
if (_chat->forbidden) {
if (_chat->forbidden || _chat->left) {
App::wnd()->hideLayer();
} else if (!_chat->participants.isEmpty() || _chat->count <= 0) {
for (ContactsData::iterator i = _contactsData.begin(), e = _contactsData.end(); i != e; ++i) {
@@ -180,11 +180,11 @@ ContactsInner::ContactData *ContactsInner::contactData(DialogRow *row) {
if (i == _contactsData.cend()) {
_contactsData.insert(peer, data = new ContactData());
data->inchat = (_chat && !peer->chat) ? _chat->participants.contains(peer->asUser()) : false;
data->check = false;
data->check = _checkedContacts.contains(peer);
data->name.setText(st::profileListNameFont, peer->name, _textNameOptions);
if (peer->chat) {
ChatData *chat = peer->asChat();
if (chat->forbidden) {
if (chat->forbidden || chat->left) {
data->online = lang(lng_chat_status_unaccessible);
} else {
data->online = lng_chat_status_members(lt_count, chat->count);
@@ -401,7 +401,7 @@ void ContactsInner::chooseParticipant() {
if (_filter.isEmpty()) {
if (_byUsernameSel >= 0 && _byUsernameSel < _byUsername.size()) {
if (d_byUsername[_byUsernameSel]->inchat) return;
changeCheckState(d_byUsername[_byUsernameSel]);
changeCheckState(d_byUsername[_byUsernameSel], _byUsername[_byUsernameSel]);
} else {
if (!_sel || contactData(_sel)->inchat) return;
changeCheckState(_sel);
@@ -409,7 +409,7 @@ void ContactsInner::chooseParticipant() {
} else {
if (_byUsernameSel >= 0 && _byUsernameSel < _byUsernameFiltered.size()) {
if (d_byUsernameFiltered[_byUsernameSel]->inchat) return;
changeCheckState(d_byUsernameFiltered[_byUsernameSel]);
changeCheckState(d_byUsernameFiltered[_byUsernameSel], _byUsernameFiltered[_byUsernameSel]);
ContactData *moving = d_byUsernameFiltered[_byUsernameSel];
int32 i = 0, l = d_byUsername.size();
@@ -470,15 +470,17 @@ void ContactsInner::chooseParticipant() {
}
void ContactsInner::changeCheckState(DialogRow *row) {
changeCheckState(contactData(row));
changeCheckState(contactData(row), row->history->peer);
}
void ContactsInner::changeCheckState(ContactData *data) {
void ContactsInner::changeCheckState(ContactData *data, PeerData *peer) {
if (data->check) {
data->check = false;
_checkedContacts.remove(peer);
--_selCount;
} else if (_selCount + (_chat ? _chat->count : 0) < cMaxGroupCount()) {
data->check = true;
_checkedContacts.insert(peer, true);
++_selCount;
}
}
@@ -693,7 +695,7 @@ void ContactsInner::peopleReceived(const QString &query, const QVector<MTPContac
ContactData *d = new ContactData();
_byUsernameDatas.push_back(d);
d->inchat = _chat ? _chat->participants.contains(u) : false;
d->check = false;
d->check = _checkedContacts.contains(u);
d->name.setText(st::profileListNameFont, u->name, _textNameOptions);
d->online = '@' + u->username;
@@ -880,6 +882,11 @@ void ContactsInner::selectSkipPage(int32 h, int32 dir) {
QVector<UserData*> ContactsInner::selected() {
QVector<UserData*> result;
for (DialogRow *row = _contacts->list.begin; row->next; row = row->next) {
if (_checkedContacts.contains(row->history->peer)) {
contactData(row); // fill _contactsData
}
}
result.reserve(_contactsData.size());
for (ContactsData::const_iterator i = _contactsData.cbegin(), e = _contactsData.cend(); i != e; ++i) {
if (i.value()->check && !i.key()->chat) {
@@ -896,10 +903,15 @@ QVector<UserData*> ContactsInner::selected() {
QVector<MTPInputUser> ContactsInner::selectedInputs() {
QVector<MTPInputUser> result;
for (DialogRow *row = _contacts->list.begin; row->next; row = row->next) {
if (_checkedContacts.contains(row->history->peer)) {
contactData(row); // fill _contactsData
}
}
result.reserve(_contactsData.size());
for (ContactsData::const_iterator i = _contactsData.cbegin(), e = _contactsData.cend(); i != e; ++i) {
if (i.value()->check && !i.key()->chat) {
result.push_back(i.key()->inputUser);
result.push_back(i.key()->asUser()->inputUser);
}
}
for (int32 i = 0, l = _byUsername.size(); i < l; ++i) {
@@ -911,6 +923,11 @@ QVector<MTPInputUser> ContactsInner::selectedInputs() {
}
PeerData *ContactsInner::selectedUser() {
for (DialogRow *row = _contacts->list.begin; row->next; row = row->next) {
if (_checkedContacts.contains(row->history->peer)) {
contactData(row); // fill _contactsData
}
}
for (ContactsData::const_iterator i = _contactsData.cbegin(), e = _contactsData.cend(); i != e; ++i) {
if (i.value()->check) {
return i.key();

View File

@@ -53,7 +53,7 @@ public:
void loadProfilePhotos(int32 yFrom);
void chooseParticipant();
void changeCheckState(DialogRow *row);
void changeCheckState(ContactData *data);
void changeCheckState(ContactData *data, PeerData *peer);
void peopleReceived(const QString &query, const QVector<MTPContactFound> &people);
@@ -109,6 +109,8 @@ private:
};
typedef QMap<PeerData*, ContactData*> ContactsData;
ContactsData _contactsData;
typedef QMap<PeerData*, bool> CheckedContacts;
CheckedContacts _checkedContacts;
ContactData *contactData(DialogRow *row);

View File

@@ -190,7 +190,11 @@ void PhotoSendBox::hideAll() {
void PhotoSendBox::showAll() {
_sendButton.show();
_cancelButton.show();
_compressed.show();
if (_img && _img->type == ToPreparePhoto) {
_compressed.show();
} else {
_compressed.hide();
}
}
void PhotoSendBox::onSend(bool ctrlShiftEnter) {

View File

@@ -17,9 +17,9 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
*/
#pragma once
static const int32 AppVersion = 8043;
static const wchar_t *AppVersionStr = L"0.8.43";
static const bool DevVersion = false;
static const int32 AppVersion = 8050;
static const wchar_t *AppVersionStr = L"0.8.50";
static const bool DevVersion = true;
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
static const wchar_t *AppName = L"Telegram Desktop";
@@ -144,10 +144,14 @@ enum {
ChoosePeerByDragTimeout = 1000, // 1 second mouse not moved to choose dialog when dragging a file
};
inline bool isServiceUser(uint64 id) {
inline bool isNotificationsUser(uint64 id) {
return (id == 333000) || (id == ServiceUserId);
}
inline bool isServiceUser(uint64 id) {
return !(id % 1000);// (id == 333000) || (id == ServiceUserId);
}
#ifdef Q_OS_WIN
inline const GUID &cGUID() {
static const GUID gGuid = { 0x87a94ab0, 0xe370, 0x4cde, { 0x98, 0xd3, 0xac, 0xc1, 0x10, 0xc5, 0x96, 0x7d } };
@@ -321,6 +325,7 @@ enum {
MemoryForImageCache = 64 * 1024 * 1024, // after 64mb of unpacked images we try to clear some memory
NotifyWindowsCount = 3, // 3 desktop notifies at the same time
NotifySettingSaveTimeout = 1000, // wait 1 second before saving notify setting to server
NotifyDeletePhotoAfter = 60000, // delete notify photo after 1 minute
UpdateChunk = 100 * 1024, // 100kb parts when downloading the update
IdleMsecs = 60 * 1000, // after 60secs without user input we think we are idle

View File

@@ -42,12 +42,16 @@ peopleSel(-1),
_lastSearchId(0),
_state(DefaultState),
_addContactLnk(this, lang(lng_add_contact_button)),
_overDelete(false) {
_cancelSearchInPeer(this, st::btnCancelSearch),
_overDelete(false),
_searchInPeer(0) {
connect(main, SIGNAL(dialogToTop(const History::DialogLinks&)), this, SLOT(onDialogToTop(const History::DialogLinks&)));
connect(main, SIGNAL(peerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)));
connect(main, SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(onPeerPhotoChanged(PeerData*)));
connect(main, SIGNAL(dialogRowReplaced(DialogRow*,DialogRow*)), this, SLOT(onDialogRowReplaced(DialogRow*,DialogRow*)));
connect(&_addContactLnk, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact()));
connect(&_cancelSearchInPeer, SIGNAL(clicked()), this, SIGNAL(cancelSearchInPeer()));
_cancelSearchInPeer.hide();
refresh(false);
}
@@ -60,7 +64,9 @@ int32 DialogsListWidget::peopleOffset() const {
}
int32 DialogsListWidget::searchedOffset() const {
return peopleOffset() + (peopleResults.isEmpty() ? 0 : ((peopleResults.size() * st::dlgHeight) + st::searchedBarHeight));
int32 result = peopleOffset() + (peopleResults.isEmpty() ? 0 : ((peopleResults.size() * st::dlgHeight) + st::searchedBarHeight));
if (_searchInPeer) result += st::dlgHeight;
return result;
}
void DialogsListWidget::paintEvent(QPaintEvent *e) {
@@ -80,12 +86,12 @@ void DialogsListWidget::paintEvent(QPaintEvent *e) {
if (otherStart) {
dialogs.list.paint(p, width(), r.top(), r.bottom(), active, selected);
}
if (contactsNoDialogs.list.count) {
if (contactsNoDialogs.list.count && false) {
contactsNoDialogs.list.paint(p, width(), r.top() - otherStart, r.bottom() - otherStart, active, selected);
} else if (!otherStart) {
p.setFont(st::noContactsFont->f);
p.setPen(st::noContactsColor->p);
p.drawText(QRect(0, 0, width(), st::noContactsHeight - (cContactsReceived() ? st::noContactsFont->height : 0)), lang(cContactsReceived() ? lng_no_contacts : lng_contacts_loading), style::al_center);
p.drawText(QRect(0, 0, width(), st::noContactsHeight - (cContactsReceived() ? st::noContactsFont->height : 0)), lang(cContactsReceived() ? lng_no_chats : lng_contacts_loading), style::al_center);
}
} else if (_state == FilteredState || _state == SearchedState) {
if (!hashtagResults.isEmpty()) {
@@ -181,6 +187,18 @@ void DialogsListWidget::paintEvent(QPaintEvent *e) {
}
}
if (_searchInPeer) {
searchInPeerPaint(p, width());
p.translate(0, st::dlgHeight);
if (_state == FilteredState && searchResults.isEmpty()) {
p.fillRect(0, 0, width(), st::searchedBarHeight, st::searchedBarBG->b);
p.setFont(st::searchedBarFont->f);
p.setPen(st::searchedBarColor->p);
p.drawText(QRect(0, 0, width(), st::searchedBarHeight), lang(lng_dlg_search_for_messages), style::al_center);
p.translate(0, st::searchedBarHeight);
}
}
if (_state == SearchedState || !searchResults.isEmpty()) {
QString text = lng_search_found_results(lt_count, searchResults.isEmpty() ? 0 : searchedCount);
p.fillRect(0, 0, width(), st::searchedBarHeight, st::searchedBarBG->b);
@@ -252,6 +270,31 @@ void DialogsListWidget::peopleResultPaint(UserData *user, QPainter &p, int32 w,
history->nameText.drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
}
void DialogsListWidget::searchInPeerPaint(QPainter &p, int32 w) const {
QRect fullRect(0, 0, w, st::dlgHeight);
p.fillRect(fullRect, st::dlgBG->b);
p.drawPixmap(st::dlgPaddingHor, st::dlgPaddingVer, _searchInPeer->photo->pix(st::dlgPhotoSize));
int32 nameleft = st::dlgPaddingHor + st::dlgPhotoSize + st::dlgPhotoPadding;
int32 namewidth = w - nameleft - st::dlgPaddingHor * 2 - st::btnCancelSearch.width;
QRect rectForName(nameleft, st::dlgPaddingVer + st::dlgNameTop, namewidth, st::msgNameFont->height);
// draw chat icon
if (_searchInPeer->chat) {
p.drawPixmap(QPoint(rectForName.left() + st::dlgChatImgLeft, rectForName.top() + st::dlgChatImgTop), App::sprite(), st::dlgChatImg);
rectForName.setLeft(rectForName.left() + st::dlgChatImgSkip);
}
QRect tr(nameleft, st::dlgPaddingVer + st::dlgFont->height + st::dlgSep, namewidth, st::dlgFont->height);
p.setFont(st::dlgHistFont->f);
p.setPen(st::dlgTextColor->p);
p.drawText(tr.left(), tr.top() + st::dlgHistFont->ascent, st::dlgHistFont->m.elidedText(lang(lng_dlg_search_chat), Qt::ElideRight, tr.width()));
p.setPen(st::dlgNameColor->p);
App::history(_searchInPeer->id)->nameText.drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
}
void DialogsListWidget::activate() {
}
@@ -274,7 +317,7 @@ void DialogsListWidget::onUpdateSelected(bool force) {
if (newSel) {
contactSel = false;
} else {
newSel = contactsNoDialogs.list.rowAtY(mouseY - otherStart, st::dlgHeight);
newSel = 0;// contactsNoDialogs.list.rowAtY(mouseY - otherStart, st::dlgHeight);
contactSel = true;
}
if (newSel != sel) {
@@ -347,6 +390,7 @@ void DialogsListWidget::mousePressEvent(QMouseEvent *e) {
void DialogsListWidget::resizeEvent(QResizeEvent *e) {
_addContactLnk.move((width() - _addContactLnk.width()) / 2, (st::noContactsHeight + st::noContactsFont->height) / 2);
_cancelSearchInPeer.move(width() - st::dlgPaddingHor - st::btnCancelSearch.width, (st::dlgHeight - st::btnCancelSearch.height) / 2);
}
void DialogsListWidget::onDialogRowReplaced(DialogRow *oldRow, DialogRow *newRow) {
@@ -397,9 +441,8 @@ void DialogsListWidget::removePeer(PeerData *peer) {
contactsNoDialogs.addByName(App::history(peer->id));
}
}
// contactsNoDialogs.del(peer);
// contacts.del(peer);
// App::deleteHistory(peer->id);
Local::removeSavedPeer(peer);
emit App::main()->dialogsUpdated();
@@ -440,7 +483,7 @@ void DialogsListWidget::dlgUpdated(History *history) {
if (i != dialogs.list.rowByPeer.cend()) {
update(0, i.value()->pos * st::dlgHeight, width(), st::dlgHeight);
} else {
i = contactsNoDialogs.list.rowByPeer.find(history->peer->id);
i = contactsNoDialogs.list.rowByPeer.end();// find(history->peer->id);
if (i != contactsNoDialogs.list.rowByPeer.cend()) {
update(0, (dialogs.list.count + i.value()->pos) * st::dlgHeight, width(), st::dlgHeight);
}
@@ -489,6 +532,7 @@ void DialogsListWidget::leaveEvent(QEvent *e) {
if (sel || filteredSel >= 0 || hashtagSel >= 0 || searchedSel >= 0 || peopleSel >= 0) {
sel = 0;
filteredSel = searchedSel = peopleSel = hashtagSel = -1;
setCursor(style::cur_default);
parentWidget()->update();
}
}
@@ -538,7 +582,7 @@ void DialogsListWidget::onFilterUpdate(QString newFilter, bool force) {
}
if (newFilter != filter || force) {
filter = newFilter;
if (filter.isEmpty()) {
if (!_searchInPeer && filter.isEmpty()) {
_state = DefaultState;
hashtagResults.clear();
filterResults.clear();
@@ -550,7 +594,7 @@ void DialogsListWidget::onFilterUpdate(QString newFilter, bool force) {
_state = FilteredState;
filterResults.clear();
if (!f.isEmpty()) {
if (!_searchInPeer && !f.isEmpty()) {
DialogsList *dialogsToFilter = 0, *contactsNoDialogsToFilter = 0;
if (dialogs.list.count) {
for (fi = fb; fi != fe; ++fi) {
@@ -629,7 +673,7 @@ void DialogsListWidget::onFilterUpdate(QString newFilter, bool force) {
}
void DialogsListWidget::onHashtagFilterUpdate(QStringRef newFilter) {
if (newFilter.isEmpty() || newFilter.at(0) != '#') {
if (newFilter.isEmpty() || newFilter.at(0) != '#' || _searchInPeer) {
_hashtagFilter = QString();
if (!hashtagResults.isEmpty()) {
hashtagResults.clear();
@@ -729,6 +773,16 @@ void DialogsListWidget::dialogsReceived(const QVector<MTPDialog> &added) {
refresh();
}
void DialogsListWidget::addAllSavedPeers() {
SavedPeersByTime &saved(cRefSavedPeersByTime());
while (!saved.isEmpty()) {
History *history = App::history(saved.last()->id);
history->dialogs = dialogs.addToEnd(history);
contactsNoDialogs.del(history->peer);
saved.remove(saved.lastKey(), saved.last());
}
}
void DialogsListWidget::searchReceived(const QVector<MTPMessage> &messages, bool fromStart, int32 fullCount) {
if (fromStart) {
clearSearchResults(false);
@@ -768,7 +822,7 @@ void DialogsListWidget::contactsReceived(const QVector<MTPContact> &contacts) {
App::self()->contact = 1;
}
}
if (!sel && contactsNoDialogs.list.count) {
if (!sel && contactsNoDialogs.list.count && false) {
sel = contactsNoDialogs.list.begin;
contactSel = true;
}
@@ -785,11 +839,11 @@ int32 DialogsListWidget::addNewContact(int32 uid, bool select) {
if (i == dialogs.list.rowByPeer.cend()) {
DialogRow *added = contactsNoDialogs.addByName(history);
if (!added) return -1;
if (select) {
if (select && false) {
sel = added;
contactSel = true;
}
if (contactsNoDialogs.list.count == 1 && !dialogs.list.count) refresh();
// if (contactsNoDialogs.list.count == 1 && !dialogs.list.count) refresh();
return added ? ((dialogs.list.count + added->pos) * st::dlgHeight) : -1;
}
if (select) {
@@ -802,7 +856,7 @@ int32 DialogsListWidget::addNewContact(int32 uid, bool select) {
void DialogsListWidget::refresh(bool toTop) {
int32 h = 0;
if (_state == DefaultState) {
h = (dialogs.list.count + contactsNoDialogs.list.count) * st::dlgHeight;
h = (dialogs.list.count/* + contactsNoDialogs.list.count*/) * st::dlgHeight;
if (h) {
if (!_addContactLnk.isHidden()) _addContactLnk.hide();
} else {
@@ -816,7 +870,7 @@ void DialogsListWidget::refresh(bool toTop) {
} else {
if (!_addContactLnk.isHidden()) _addContactLnk.hide();
if (_state == FilteredState) {
h = searchedOffset() + (searchResults.count() * st::dlgHeight) + (searchResults.isEmpty() ? 0 : st::searchedBarHeight);
h = searchedOffset() + (searchResults.count() * st::dlgHeight) + ((searchResults.isEmpty() && !_searchInPeer) ? 0 : st::searchedBarHeight);
} else if (_state == SearchedState) {
h = searchedOffset() + (searchResults.count() * st::dlgHeight) + st::searchedBarHeight;
}
@@ -837,6 +891,7 @@ void DialogsListWidget::setMouseSel(bool msel, bool toTop) {
contactSel = !dialogs.list.count && contactsNoDialogs.list.count;
} else if (_state == FilteredState || _state == SearchedState) { // don't select first elem in search
filteredSel = peopleSel = searchedSel = hashtagSel = -1;
setCursor(style::cur_default);
}
}
}
@@ -864,9 +919,23 @@ bool DialogsListWidget::hasFilteredResults() const {
return !filterResults.isEmpty() && hashtagResults.isEmpty();
}
void DialogsListWidget::searchInPeer(PeerData *peer) {
_searchInPeer = peer;
if (_searchInPeer) {
onHashtagFilterUpdate(QStringRef());
_cancelSearchInPeer.show();
} else {
_cancelSearchInPeer.hide();
}
}
void DialogsListWidget::clearFilter() {
if (_state == FilteredState || _state == SearchedState) {
_state = DefaultState;
if (_searchInPeer) {
_state = FilteredState;
} else {
_state = DefaultState;
}
hashtagResults.clear();
filterResults.clear();
peopleResults.clear();
@@ -879,6 +948,15 @@ void DialogsListWidget::clearFilter() {
void DialogsListWidget::addDialog(const MTPDdialog &dialog) {
History *history = App::history(App::peerFromMTP(dialog.vpeer), dialog.vunread_count.v, dialog.vread_inbox_max_id.v);
if (history->lastMsg) {
SavedPeersByTime &saved(cRefSavedPeersByTime());
while (!saved.isEmpty() && history->lastMsg->date < saved.lastKey()) {
History *history = App::history(saved.last()->id);
history->dialogs = dialogs.addToEnd(history);
contactsNoDialogs.del(history->peer);
saved.remove(saved.lastKey(), saved.last());
}
}
History::DialogLinks links = dialogs.addToEnd(history);
history->dialogs = links;
contactsNoDialogs.del(history->peer);
@@ -1388,6 +1466,7 @@ DialogsWidget::DialogsWidget(MainWidget *parent) : QWidget(parent)
, _cancelSearch(this, st::btnCancelSearch)
, scroll(this, st::dlgScroll)
, list(&scroll, parent)
, _searchInPeer(0)
, _searchFull(false)
, _peopleFull(false)
{
@@ -1399,6 +1478,7 @@ DialogsWidget::DialogsWidget(MainWidget *parent) : QWidget(parent)
connect(&list, SIGNAL(searchResultChosen()), this, SLOT(onCancel()));
connect(&list, SIGNAL(completeHashtag(QString)), this, SLOT(onCompleteHashtag(QString)));
connect(&list, SIGNAL(refreshHashtags()), this, SLOT(onFilterCursorMoved()));
connect(&list, SIGNAL(cancelSearchInPeer()), this, SLOT(onCancelSearchInPeer()));
connect(&scroll, SIGNAL(geometryChanged()), &list, SLOT(onParentGeometryChanged()));
connect(&scroll, SIGNAL(scrolled()), &list, SLOT(onUpdateSelected()));
connect(&scroll, SIGNAL(scrolled()), this, SLOT(onListScroll()));
@@ -1494,7 +1574,7 @@ bool DialogsWidget::animStep(float64 ms) {
}
void DialogsWidget::onCancel() {
if (!onCancelSearch() || !App::main()->selectingPeer()) {
if (!onCancelSearch() || (!_searchInPeer && !App::main()->selectingPeer())) {
emit cancelled();
}
}
@@ -1598,10 +1678,10 @@ bool DialogsWidget::onSearchMessages(bool searchCache) {
} else if (_searchQuery != q) {
_searchQuery = q;
_searchFull = false;
_searchRequest = MTP::send(MTPmessages_Search(MTP_inputPeerEmpty(), MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, true), rpcFail(&DialogsWidget::searchFailed));
_searchRequest = MTP::send(MTPmessages_Search(_searchInPeer ? _searchInPeer->input : MTP_inputPeerEmpty(), MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, true), rpcFail(&DialogsWidget::searchFailed));
_searchQueries.insert(_searchRequest, _searchQuery);
}
if (q.size() >= MinUsernameLength) {
if (!_searchInPeer && q.size() >= MinUsernameLength) {
if (searchCache) {
PeopleCache::const_iterator i = _peopleCache.constFind(q);
if (i != _peopleCache.cend()) {
@@ -1645,7 +1725,7 @@ void DialogsWidget::searchMessages(const QString &query) {
void DialogsWidget::onSearchMore(MsgId minMsgId) {
if (!_searchRequest && !_searchFull) {
_searchRequest = MTP::send(MTPmessages_Search(MTP_inputPeerEmpty(), MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(minMsgId), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, !minMsgId), rpcFail(&DialogsWidget::searchFailed));
_searchRequest = MTP::send(MTPmessages_Search(_searchInPeer ? _searchInPeer->input : MTP_inputPeerEmpty(), MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(minMsgId), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, !minMsgId), rpcFail(&DialogsWidget::searchFailed));
if (!minMsgId) {
_searchQueries.insert(_searchRequest, _searchQuery);
}
@@ -1655,6 +1735,7 @@ void DialogsWidget::onSearchMore(MsgId minMsgId) {
void DialogsWidget::loadDialogs() {
if (dlgPreloading) return;
if (dlgCount >= 0 && dlgOffset >= dlgCount) {
list.addAllSavedPeers();
cSetDialogsReceived(true);
return;
}
@@ -1875,6 +1956,14 @@ void DialogsWidget::onFilterUpdate(bool force) {
}
}
void DialogsWidget::searchInPeer(PeerData *peer) {
onCancelSearch();
_searchInPeer = peer;
list.searchInPeer(peer);
onFilterUpdate(true);
list.onFilterUpdate(_filter.text(), true);
}
void DialogsWidget::onFilterCursorMoved(int from, int to) {
if (to < 0) to = _filter.cursorPosition();
QString t = _filter.text();
@@ -2033,6 +2122,14 @@ void DialogsWidget::onNewGroup() {
bool DialogsWidget::onCancelSearch() {
bool clearing = !_filter.text().isEmpty();
if (_searchInPeer && !clearing) {
if (!cWideMode()) {
App::main()->showPeerHistory(_searchInPeer->id, ShowAtUnreadMsgId);
}
_searchInPeer = 0;
list.searchInPeer(0);
clearing = true;
}
list.clearFilter();
_filter.clear();
_filter.updatePlaceholder();
@@ -2040,6 +2137,23 @@ bool DialogsWidget::onCancelSearch() {
return clearing;
}
void DialogsWidget::onCancelSearchInPeer() {
if (_searchInPeer) {
if (!cWideMode()) {
App::main()->showPeerHistory(_searchInPeer->id, ShowAtUnreadMsgId);
}
_searchInPeer = 0;
list.searchInPeer(0);
}
list.clearFilter();
_filter.clear();
_filter.updatePlaceholder();
onFilterUpdate();
if (cWideMode()) {
emit cancelled();
}
}
void DialogsWidget::onDialogToTopFrom(int movedFrom) {
if (scroll.scrollTop() > 0) {
if (movedFrom > scroll.scrollTop()) {

View File

@@ -27,6 +27,7 @@ public:
DialogsListWidget(QWidget *parent, MainWidget *main);
void dialogsReceived(const QVector<MTPDialog> &dialogs);
void addAllSavedPeers();
void searchReceived(const QVector<MTPMessage> &messages, bool fromStart, int32 fullCount);
void peopleReceived(const QString &query, const QVector<MTPContactFound> &people);
void showMore(int32 pixels);
@@ -48,6 +49,7 @@ public:
void leaveEvent(QEvent *e);
void peopleResultPaint(UserData *user, QPainter &p, int32 w, bool act, bool sel) const;
void searchInPeerPaint(QPainter &p, int32 w) const;
void selectSkip(int32 direction);
void selectSkipPage(int32 pixels, int32 direction);
@@ -93,6 +95,8 @@ public:
State state() const;
bool hasFilteredResults() const;
void searchInPeer(PeerData *peer);
void onFilterUpdate(QString newFilter, bool force = false);
void onHashtagFilterUpdate(QStringRef newFilter);
void itemRemoved(HistoryItem *item);
@@ -117,6 +121,7 @@ signals:
void dialogToTopFrom(int movedFrom);
void searchMessages();
void searchResultChosen();
void cancelSearchInPeer();
void completeHashtag(QString tag);
void refreshHashtags();
@@ -156,9 +161,12 @@ private:
void paintDialog(QPainter &p, DialogRow *dialog);
LinkButton _addContactLnk;
IconedButton _cancelSearchInPeer;
bool _overDelete;
PeerData *_searchInPeer;
};
class DialogsWidget : public QWidget, public Animated, public RPCSender {
@@ -183,6 +191,8 @@ public:
void keyPressEvent(QKeyEvent *e);
void paintEvent(QPaintEvent *e);
void searchInPeer(PeerData *peer);
void loadDialogs();
void createDialogAtTop(History *history, int32 unreadCount);
void dlgUpdated(DialogRow *row);
@@ -226,6 +236,7 @@ public slots:
void onAddContact();
void onNewGroup();
bool onCancelSearch();
void onCancelSearchInPeer();
void onFilterCursorMoved(int from = -1, int to = -1);
void onCompleteHashtag(QString tag);
@@ -262,6 +273,8 @@ private:
anim::ivalue a_coord, a_bgCoord;
anim::fvalue a_alpha, a_bgAlpha;
PeerData *_searchInPeer;
QTimer _searchTimer;
QString _searchQuery, _peopleQuery;
bool _searchFull, _peopleFull;

View File

@@ -273,6 +273,7 @@ void FileUploader::partLoaded(const MTPBool &result, mtpRequestId requestId) {
audio->uploadOffset = audio->size;
}
}
emit audioProgress(k.key());
}
}
}

View File

@@ -774,6 +774,8 @@ void FlatTextarea::keyPressEvent(QKeyEvent *e) {
} else {
emit tabbed();
}
} else if (e->key() == Qt::Key_Search || e == QKeySequence::Find) {
e->ignore();
} else {
QTextCursor tc(textCursor());
if (enter && ctrl) {

View File

@@ -29,6 +29,9 @@ struct StorageImageLocation {
}
StorageImageLocation(int32 width, int32 height, const MTPDfileLocation &location) : width(width), height(height), dc(location.vdc_id.v), volume(location.vvolume_id.v), local(location.vlocal_id.v), secret(location.vsecret.v) {
}
bool isNull() const {
return !dc;
}
int32 width, height;
int32 dc;
uint64 volume;
@@ -36,6 +39,13 @@ struct StorageImageLocation {
uint64 secret;
};
inline bool operator==(const StorageImageLocation &a, const StorageImageLocation &b) {
return !memcmp(&a, &b, sizeof(StorageImageLocation));
}
inline bool operator!=(const StorageImageLocation &a, const StorageImageLocation &b) {
return !(a == b);
}
class Image {
public:
@@ -144,6 +154,10 @@ inline StorageKey storageKey(int32 dc, const uint64 &volume, int32 local) {
inline StorageKey storageKey(const MTPDfileLocation &location) {
return storageKey(location.vdc_id.v, location.vvolume_id.v, location.vlocal_id.v);
}
inline StorageKey storageKey(const StorageImageLocation &location) {
return storageKey(location.dc, location.volume, location.local);
}
enum StorageFileType {
StorageFileUnknown = 0xaa963b05, // mtpc_storage_fileUnknown
StorageFileJpeg = 0x7efe0e, // mtpc_storage_fileJpeg

View File

@@ -167,7 +167,7 @@ void DialogRow::paint(QPainter &p, int32 w, bool act, bool sel) const {
if (!last) {
p.setFont(st::dlgHistFont->f);
p.setPen((act ? st::dlgActiveColor : st::dlgSystemColor)->p);
if (history->typing.isEmpty()) {
if (history->typing.isEmpty() && history->sendActions.isEmpty()) {
p.drawText(nameleft, st::dlgPaddingVer + st::dlgFont->height + st::dlgFont->ascent + st::dlgSep, lang(lng_empty_history));
} else {
history->typingText.drawElided(p, nameleft, st::dlgPaddingVer + st::dlgFont->height + st::dlgSep, namewidth);
@@ -223,7 +223,7 @@ void DialogRow::paint(QPainter &p, int32 w, bool act, bool sel) const {
p.setPen((act ? st::dlgActiveUnreadColor : st::dlgUnreadColor)->p);
p.drawText(unreadRectLeft + st::dlgUnreadPaddingHor, unreadRectTop + st::dlgUnreadPaddingVer + st::dlgUnreadFont->ascent, unreadStr);
}
if (history->typing.isEmpty()) {
if (history->typing.isEmpty() && history->sendActions.isEmpty()) {
last->drawInDialog(p, QRect(nameleft, st::dlgPaddingVer + st::dlgFont->height + st::dlgSep, lastWidth, st::dlgFont->height), act, history->textCachedFor, history->lastItemTextCache);
} else {
p.setPen((act ? st::dlgActiveColor : st::dlgSystemColor)->p);
@@ -319,7 +319,6 @@ History::History(const PeerId &peerId) : width(0), height(0)
, lastItemTextCache(st::dlgRichMinWidth)
, posInDialogs(0)
, typingText(st::dlgRichMinWidth)
, myTyping(0)
{
for (int32 i = 0; i < OverviewCount; ++i) {
_overviewCount[i] = -1; // not loaded yet
@@ -347,6 +346,14 @@ bool History::updateTyping(uint64 ms, uint32 dots, bool force) {
++i;
}
}
for (SendActionUsers::iterator i = sendActions.begin(), e = sendActions.end(); i != e;) {
if (ms >= i.value().until) {
i = sendActions.erase(i);
changed = true;
} else {
++i;
}
}
if (changed) {
QString newTypingStr;
int32 cnt = typing.size();
@@ -356,6 +363,17 @@ bool History::updateTyping(uint64 ms, uint32 dots, bool force) {
newTypingStr = lng_users_typing(lt_user, typing.begin().key()->firstName, lt_second_user, (typing.end() - 1).key()->firstName);
} else if (cnt) {
newTypingStr = peer->chat ? lng_user_typing(lt_user, typing.begin().key()->firstName) : lang(lng_typing);
} else if (!sendActions.isEmpty()) {
switch (sendActions.begin().value().type) {
case SendActionRecordVideo: newTypingStr = peer->chat ? lng_user_action_record_video(lt_user, sendActions.begin().key()->firstName) : lang(lng_send_action_record_video); break;
case SendActionUploadVideo: newTypingStr = peer->chat ? lng_user_action_upload_video(lt_user, sendActions.begin().key()->firstName) : lang(lng_send_action_upload_video); break;
case SendActionRecordAudio: newTypingStr = peer->chat ? lng_user_action_record_audio(lt_user, sendActions.begin().key()->firstName) : lang(lng_send_action_record_audio); break;
case SendActionUploadAudio: newTypingStr = peer->chat ? lng_user_action_upload_audio(lt_user, sendActions.begin().key()->firstName) : lang(lng_send_action_upload_audio); break;
case SendActionUploadPhoto: newTypingStr = peer->chat ? lng_user_action_upload_photo(lt_user, sendActions.begin().key()->firstName) : lang(lng_send_action_upload_photo); break;
case SendActionUploadFile: newTypingStr = peer->chat ? lng_user_action_upload_file(lt_user, sendActions.begin().key()->firstName) : lang(lng_send_action_upload_file); break;
case SendActionChooseLocation: newTypingStr = peer->chat ? lng_user_action_geo_location(lt_user, sendActions.begin().key()->firstName) : lang(lng_send_action_geo_location); break;
case SendActionChooseContact: newTypingStr = peer->chat ? lng_user_action_choose_contact(lt_user, sendActions.begin().key()->firstName) : lang(lng_send_action_choose_contact); break;
}
}
if (!newTypingStr.isEmpty()) {
newTypingStr += qsl("...");
@@ -506,9 +524,25 @@ void Histories::clear() {
Parent::clear();
}
void Histories::regTyping(History *history, UserData *user) {
void Histories::regSendAction(History *history, UserData *user, const MTPSendMessageAction &action) {
if (action.type() == mtpc_sendMessageCancelAction) {
history->unregTyping(user);
return;
}
uint64 ms = getms(true);
history->typing[user] = ms + 6000;
switch (action.type()) {
case mtpc_sendMessageTypingAction: history->typing[user] = ms + 6000; break;
case mtpc_sendMessageRecordVideoAction: history->sendActions.insert(user, SendAction(SendActionRecordVideo, ms + 6000)); break;
case mtpc_sendMessageUploadVideoAction: history->sendActions.insert(user, SendAction(SendActionUploadVideo, ms + 6000, action.c_sendMessageUploadVideoAction().vprogress.v)); break;
case mtpc_sendMessageRecordAudioAction: history->sendActions.insert(user, SendAction(SendActionRecordAudio, ms + 6000)); break;
case mtpc_sendMessageUploadAudioAction: history->sendActions.insert(user, SendAction(SendActionUploadAudio, ms + 6000, action.c_sendMessageUploadAudioAction().vprogress.v)); break;
case mtpc_sendMessageUploadPhotoAction: history->sendActions.insert(user, SendAction(SendActionUploadPhoto, ms + 6000, action.c_sendMessageUploadPhotoAction().vprogress.v)); break;
case mtpc_sendMessageUploadDocumentAction: history->sendActions.insert(user, SendAction(SendActionUploadFile, ms + 6000, action.c_sendMessageUploadDocumentAction().vprogress.v)); break;
case mtpc_sendMessageGeoLocationAction: history->sendActions.insert(user, SendAction(SendActionChooseLocation, ms + 6000)); break;
case mtpc_sendMessageChooseContactAction: history->sendActions.insert(user, SendAction(SendActionChooseContact, ms + 6000)); break;
default: return;
}
user->madeAction();
@@ -530,7 +564,7 @@ bool Histories::animStep(float64) {
App::main()->dlgUpdated(i.key());
App::main()->topBar()->update();
}
if (i.key()->typing.isEmpty()) {
if (i.key()->typing.isEmpty() && i.key()->sendActions.isEmpty()) {
i = typing.erase(i);
} else {
++i;
@@ -579,7 +613,7 @@ HistoryItem *Histories::addToBack(const MTPmessage &msg, int msgState) {
if (!h.value()->loadedAtBottom()) {
HistoryItem *item = h.value()->addToHistory(msg);
if (item) {
h.value()->lastMsg = item;
h.value()->setLastMessage(item);
if (msgState > 0) {
h.value()->newItemAdded(item);
}
@@ -874,7 +908,8 @@ HistoryItem *History::doAddToBack(HistoryBlock *to, bool newBlock, HistoryItem *
}
}
to->push_back(adding);
lastMsg = adding;
setLastMessage(adding);
adding->y = to->height;
if (width) {
int32 dh = adding->resize(width);
@@ -885,6 +920,7 @@ HistoryItem *History::doAddToBack(HistoryBlock *to, bool newBlock, HistoryItem *
if (newMsg) {
newItemAdded(adding);
}
HistoryMedia *media = adding->getMedia(true);
if (media) {
HistoryMediaType mt = media->type();
@@ -943,11 +979,22 @@ HistoryItem *History::doAddToBack(HistoryBlock *to, bool newBlock, HistoryItem *
}
void History::unregTyping(UserData *from) {
bool update = false;
uint64 updateAtMs = 0;
TypingUsers::iterator i = typing.find(from);
if (i != typing.end()) {
uint64 ms = getms(true);
i.value() = ms;
updateTyping(ms, 0, true);
updateAtMs = getms(true);
i.value() = updateAtMs;
update = true;
}
SendActionUsers::iterator j = sendActions.find(from);
if (j != sendActions.end()) {
if (!updateAtMs) updateAtMs = getms(true);
j.value().until = updateAtMs;
update = true;
}
if (updateAtMs) {
updateTyping(updateAtMs, 0, true);
App::main()->topBar()->update();
}
}
@@ -1369,14 +1416,24 @@ void History::getReadyFor(MsgId msgId) {
}
}
void History::setLastMessage(HistoryItem *msg) {
if (msg) {
if (!lastMsg) Local::removeSavedPeer(peer);
lastMsg = msg;
lastMsgDate = msg->date;
} else {
lastMsg = 0;
}
}
void History::fixLastMessage(bool wasAtBottom) {
if (wasAtBottom && isEmpty()) {
wasAtBottom = false;
}
if (wasAtBottom) {
lastMsg = back()->back();
setLastMessage(back()->back());
} else {
lastMsg = 0;
setLastMessage(0);
if (App::main()) {
App::main()->checkPeerHistory(peer);
}
@@ -1436,9 +1493,16 @@ void History::clear(bool leaveItems) {
if (showFrom) {
showFrom = 0;
}
if (!leaveItems) {
setLastMessage(0);
}
for (int32 i = 0; i < OverviewCount; ++i) {
if (!_overview[i].isEmpty() || !_overviewIds[i].isEmpty()) {
if (_overviewCount[i] == 0) _overviewCount[i] = _overview[i].size();
if (leaveItems) {
if (_overviewCount[i] == 0) _overviewCount[i] = _overview[i].size();
} else {
_overviewCount[i] = -1; // not loaded yet
}
_overview[i].clear();
_overviewIds[i].clear();
if (App::wnd() && !App::quiting()) App::wnd()->mediaOverviewUpdated(peer, MediaOverviewType(i));
@@ -1456,7 +1520,6 @@ void History::clear(bool leaveItems) {
lastKeyboardInited = false;
} else {
setUnreadCount(0);
lastMsg = 0;
}
height = 0;
oldLoaded = false;

View File

@@ -41,7 +41,7 @@ struct Histories : public QHash<PeerId, History*>, public Animated {
Histories() : unreadFull(0), unreadMuted(0) {
}
void regTyping(History *history, UserData *user);
void regSendAction(History *history, UserData *user, const MTPSendMessageAction &action);
bool animStep(float64 ms);
void clear();
@@ -134,6 +134,25 @@ inline MTPMessagesFilter typeToMediaFilter(MediaOverviewType &type) {
return MTPMessagesFilter();
}
enum SendActionType {
SendActionTyping,
SendActionRecordVideo,
SendActionUploadVideo,
SendActionRecordAudio,
SendActionUploadAudio,
SendActionUploadPhoto,
SendActionUploadFile,
SendActionChooseLocation,
SendActionChooseContact,
};
struct SendAction {
SendAction(SendActionType type, uint64 until, int32 progress = 0) : type(type), until(until), progress(progress) {
}
SendActionType type;
uint64 until;
int32 progress;
};
class HistoryMedia;
class HistoryMessage;
class HistoryUnreadBar;
@@ -185,6 +204,7 @@ struct History : public QList<HistoryBlock*> {
bool isReadyFor(MsgId msgId, bool check = false) const; // has messages for showing history at msgId
void getReadyFor(MsgId msgId);
void setLastMessage(HistoryItem *msg);
void fixLastMessage(bool wasAtBottom);
MsgId minMsgId() const;
@@ -199,6 +219,7 @@ struct History : public QList<HistoryBlock*> {
PeerData *peer;
bool oldLoaded, newLoaded;
HistoryItem *lastMsg;
QDateTime lastMsgDate;
typedef QList<HistoryItem*> NotifyQueue;
NotifyQueue notifies;
@@ -273,11 +294,13 @@ struct History : public QList<HistoryBlock*> {
typedef QMap<UserData*, uint64> TypingUsers;
TypingUsers typing;
typedef QMap<UserData*, SendAction> SendActionUsers;
SendActionUsers sendActions;
QString typingStr;
Text typingText;
uint32 typingFrame;
bool updateTyping(uint64 ms = 0, uint32 dots = 0, bool force = false);
uint64 myTyping;
QMap<SendActionType, uint64> mySendActions;
typedef QList<MsgId> MediaOverview;
typedef QMap<MsgId, NullType> MediaOverviewIds;
@@ -425,11 +448,11 @@ struct DialogsList {
DialogRow *row = addToEnd(history), *change = row;
const QString &peerName(history->peer->name);
while (change->prev && change->prev->history->peer->name > peerName) {
while (change->prev && change->prev->history->peer->name.compare(peerName, Qt::CaseInsensitive) > 0) {
change = change->prev;
}
if (!insertBefore(row, change)) {
while (change->next != end && change->next->history->peer->name < peerName) {
while (change->next != end && change->next->history->peer->name.compare(peerName, Qt::CaseInsensitive) < 0) {
change = change->next;
}
insertAfter(row, change);

View File

@@ -75,7 +75,9 @@ HistoryList::HistoryList(HistoryWidget *historyWidget, ScrollArea *scroll, Histo
_trippleClickTimer.setSingleShot(true);
if (botInfo && !botInfo->inited) App::api()->requestFullPeer(hist->peer);
if (botInfo && !botInfo->inited) {
App::api()->requestFullPeer(hist->peer);
}
setMouseTracking(true);
}
@@ -2200,7 +2202,9 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
, _toHistoryEnd(this, st::historyToEnd)
, _attachMention(this)
, _send(this, lang(lng_send_button), st::btnSend)
, _unblock(this, lang(lng_unblock_button), st::btnUnblock)
, _botStart(this, lang(lng_bot_start), st::btnSend)
, _unblockRequest(0)
, _attachDocument(this, st::btnAttachDocument)
, _attachPhoto(this, st::btnAttachPhoto)
, _attachEmoji(this, st::btnAttachEmoji)
@@ -2233,7 +2237,6 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
, _titlePeerTextWidth(0)
, _showAnim(animFunc(this, &HistoryWidget::showStep))
, _scrollDelta(0)
, _typingRequest(0)
, _saveDraftStart(0)
, _saveDraftText(false) {
_scroll.setFocusPolicy(Qt::NoFocus);
@@ -2244,6 +2247,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
connect(&_toHistoryEnd, SIGNAL(clicked()), this, SLOT(onHistoryToEnd()));
connect(&_replyForwardPreviewCancel, SIGNAL(clicked()), this, SLOT(onReplyForwardPreviewCancel()));
connect(&_send, SIGNAL(clicked()), this, SLOT(onSend()));
connect(&_unblock, SIGNAL(clicked()), this, SLOT(onUnblock()));
connect(&_botStart, SIGNAL(clicked()), this, SLOT(onBotStart()));
connect(&_attachDocument, SIGNAL(clicked()), this, SLOT(onDocumentSelect()));
connect(&_attachPhoto, SIGNAL(clicked()), this, SLOT(onPhotoSelect()));
@@ -2262,7 +2266,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
connect(&_emojiPan, SIGNAL(emojiSelected(EmojiPtr)), &_field, SLOT(onEmojiInsert(EmojiPtr)));
connect(&_emojiPan, SIGNAL(stickerSelected(DocumentData*)), this, SLOT(onStickerSend(DocumentData*)));
connect(&_emojiPan, SIGNAL(updateStickers()), this, SLOT(updateStickers()));
connect(&_typingStopTimer, SIGNAL(timeout()), this, SLOT(cancelTyping()));
connect(&_sendActionStopTimer, SIGNAL(timeout()), this, SLOT(onCancelSendAction()));
connect(&_previewTimer, SIGNAL(timeout()), this, SLOT(onPreviewTimeout()));
if (audioCapture()) {
connect(audioCapture(), SIGNAL(onError()), this, SLOT(onRecordError()));
@@ -2272,7 +2276,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
_scrollTimer.setSingleShot(false);
_typingStopTimer.setSingleShot(true);
_sendActionStopTimer.setSingleShot(true);
_animActiveTimer.setSingleShot(false);
connect(&_animActiveTimer, SIGNAL(timeout()), this, SLOT(onAnimActiveStep()));
@@ -2306,6 +2310,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
_field.hide();
_field.resize(width() - _send.width() - _attachDocument.width() - _attachEmoji.width(), _send.height() - 2 * st::sendPadding);
_send.hide();
_unblock.hide();
_botStart.hide();
_attachDocument.hide();
@@ -2350,7 +2355,7 @@ void HistoryWidget::onMentionHashtagOrBotCommandInsert(QString str) {
}
void HistoryWidget::onTextChange() {
updateTyping();
updateSendAction(_history, SendActionTyping);
if (cHasAudioCapture()) {
if (_field.getLastText().isEmpty() && !App::main()->hasForwardingItems()) {
@@ -2411,22 +2416,55 @@ void HistoryWidget::writeDraft(MsgId *replyTo, const QString *text, const Messag
if (save) Local::writeDraftPositions(_history->peer->id, cursor ? (*cursor) : MessageCursor(_field));
}
void HistoryWidget::cancelTyping() {
if (_typingRequest) {
MTP::cancel(_typingRequest);
_typingRequest = 0;
void HistoryWidget::cancelSendAction(History *history, SendActionType type) {
QMap<QPair<History*, SendActionType>, mtpRequestId>::iterator i = _sendActionRequests.find(qMakePair(history, type));
if (i != _sendActionRequests.cend()) {
MTP::cancel(i.value());
_sendActionRequests.erase(i);
}
}
void HistoryWidget::updateTyping(bool typing) {
uint64 ms = getms(true) + 10000;
if (_synthedTextUpdate || !_history || (typing && (_history->myTyping + 5000 > ms)) || (!typing && (_history->myTyping + 5000 <= ms))) return;
void HistoryWidget::onCancelSendAction() {
cancelSendAction(_history, SendActionTyping);
}
_history->myTyping = typing ? ms : 0;
cancelTyping();
if (typing) {
_typingRequest = MTP::send(MTPmessages_SetTyping(_peer->input, typing ? MTP_sendMessageTypingAction() : MTP_sendMessageCancelAction()), rpcDone(&HistoryWidget::typingDone));
_typingStopTimer.start(5000);
void HistoryWidget::updateSendAction(History *history, SendActionType type, int32 progress) {
if (!history) return;
if (type == SendActionTyping && _synthedTextUpdate) return;
bool doing = (progress >= 0);
uint64 ms = getms(true) + 10000;
QMap<SendActionType, uint64>::iterator i = history->mySendActions.find(type);
if (doing && i != history->mySendActions.cend() && i.value() + 5000 > ms) return;
if (!doing && (i == history->mySendActions.cend() || i.value() + 5000 <= ms)) return;
if (doing) {
if (i == history->mySendActions.cend()) {
history->mySendActions.insert(type, ms);
} else {
i.value() = ms;
}
} else if (i != history->mySendActions.cend()) {
history->mySendActions.erase(i);
}
cancelSendAction(history, type);
if (doing) {
MTPsendMessageAction action;
switch (type) {
case SendActionTyping: action = MTP_sendMessageTypingAction(); break;
case SendActionRecordVideo: action = MTP_sendMessageRecordVideoAction(); break;
case SendActionUploadVideo: action = MTP_sendMessageUploadVideoAction(MTP_int(progress)); break;
case SendActionRecordAudio: action = MTP_sendMessageRecordAudioAction(); break;
case SendActionUploadAudio: action = MTP_sendMessageUploadAudioAction(MTP_int(progress)); break;
case SendActionUploadPhoto: action = MTP_sendMessageUploadPhotoAction(MTP_int(progress)); break;
case SendActionUploadFile: action = MTP_sendMessageUploadDocumentAction(MTP_int(progress)); break;
case SendActionChooseLocation: action = MTP_sendMessageGeoLocationAction(); break;
case SendActionChooseContact: action = MTP_sendMessageChooseContactAction(); break;
}
_sendActionRequests.insert(qMakePair(history, type), MTP::send(MTPmessages_SetTyping(history->peer->input, action), rpcDone(&HistoryWidget::sendActionDone)));
if (type == SendActionTyping) _sendActionStopTimer.start(5000);
}
}
@@ -2438,16 +2476,19 @@ void HistoryWidget::stickersInstalled(uint64 setId) {
_emojiPan.stickersInstalled(setId);
}
void HistoryWidget::typingDone(const MTPBool &result, mtpRequestId req) {
if (_typingRequest == req) {
_typingRequest = 0;
void HistoryWidget::sendActionDone(const MTPBool &result, mtpRequestId req) {
for (QMap<QPair<History*, SendActionType>, mtpRequestId>::iterator i = _sendActionRequests.begin(), e = _sendActionRequests.end(); i != e; ++i) {
if (i.value() == req) {
_sendActionRequests.erase(i);
break;
}
}
}
void HistoryWidget::activate() {
if (_history) updateListSize(0, true);
if (_list) {
if (_selCount || (_list && _list->wasSelectedText()) || _recording || isBotStart()) {
if (_selCount || (_list && _list->wasSelectedText()) || _recording || isBotStart() || isBlocked()) {
_list->setFocus();
} else {
_field.setFocus();
@@ -2480,6 +2521,7 @@ void HistoryWidget::onRecordUpdate(qint16 level, qint32 samples) {
stopRecording(_peer && samples > 0 && _inField);
}
updateField();
updateSendAction(_history, SendActionRecordAudio);
}
void HistoryWidget::updateStickers() {
@@ -2688,7 +2730,7 @@ void HistoryWidget::showPeerHistory(const PeerId &peerId, MsgId showAtMsgId) {
update();
return;
}
updateTyping(false);
if (_history->mySendActions.contains(SendActionTyping)) updateSendAction(_history, SendActionTyping, -1);
}
stopGif();
@@ -2740,6 +2782,7 @@ void HistoryWidget::showPeerHistory(const PeerId &peerId, MsgId showAtMsgId) {
}
_peer = peerId ? App::peer(peerId) : 0;
_unblockRequest = 0;
_titlePeerText = QString();
_titlePeerTextWidth = 0;
@@ -2854,6 +2897,7 @@ void HistoryWidget::updateControlsVisibility() {
_scroll.hide();
_kbScroll.hide();
_send.hide();
_unblock.hide();
_botStart.hide();
_attachMention.hide();
_field.hide();
@@ -2876,9 +2920,27 @@ void HistoryWidget::updateControlsVisibility() {
} else {
_scroll.show();
}
if (!_peer->chat || !_peer->asChat()->forbidden) {
if ((_peer->chat && !_peer->asChat()->forbidden && !_peer->asChat()->left) || (!_peer->chat && _peer->asUser()->access != UserNoAccess)) {
checkMentionDropdown();
if (isBotStart()) {
if (isBlocked()) {
_botStart.hide();
if (_unblock.isHidden()) {
_unblock.clearState();
_unblock.show();
_kbShown = false;
}
_send.hide();
_field.hide();
_attachEmoji.hide();
_kbShow.hide();
_kbHide.hide();
_cmdStart.hide();
_attachDocument.hide();
_attachPhoto.hide();
_kbScroll.hide();
_replyForwardPreviewCancel.hide();
} else if (isBotStart()) {
_unblock.hide();
if (_botStart.isHidden()) {
_botStart.clearState();
_botStart.show();
@@ -2895,6 +2957,7 @@ void HistoryWidget::updateControlsVisibility() {
_kbScroll.hide();
_replyForwardPreviewCancel.hide();
} else {
_unblock.hide();
_botStart.hide();
if (cHasAudioCapture() && _field.getLastText().isEmpty() && !App::main()->hasForwardingItems()) {
_send.hide();
@@ -2971,6 +3034,7 @@ void HistoryWidget::updateControlsVisibility() {
} else {
_attachMention.hide();
_send.hide();
_unblock.hide();
_botStart.hide();
_attachDocument.hide();
_attachPhoto.hide();
@@ -3285,6 +3349,29 @@ void HistoryWidget::onSend(bool ctrlShiftEnter, MsgId replyTo) {
if (!_keyboard.hasMarkup() && _keyboard.forceReply() && !_kbReplyTo) onKbToggle();
}
void HistoryWidget::onUnblock() {
if (_unblockRequest) return;
if (!_peer || _peer->chat || _peer->asUser()->blocked != UserIsBlocked) {
updateControlsVisibility();
return;
}
_unblockRequest = MTP::send(MTPcontacts_Unblock(_peer->asUser()->inputUser), rpcDone(&HistoryWidget::unblockDone, _peer), rpcFail(&HistoryWidget::unblockFail));
}
void HistoryWidget::unblockDone(PeerData *peer, const MTPBool &result) {
if (peer->chat) return;
_unblockRequest = 0;
peer->asUser()->blocked = UserIsNotBlocked;
emit App::main()->peerUpdated(peer);
}
bool HistoryWidget::unblockFail(const RPCError &error) {
if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false;
// _unblockRequest = 0;
return false;
}
void HistoryWidget::onBotStart() {
if (!_peer || _peer->chat || !_peer->asUser()->botInfo) {
updateControlsVisibility();
@@ -3338,7 +3425,7 @@ void HistoryWidget::shareContact(const PeerId &peer, const QString &phone, const
flags |= MTPDmessage::flag_reply_to_msg_id;
sendFlags |= MTPmessages_SendMedia::flag_reply_to_msg_id;
}
h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(peer), MTPint(), MTPint(), MTP_int(replyToId()), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaContact(MTP_string(phone), MTP_string(fname), MTP_string(lname), MTP_int(userId)), MTPnullMarkup));
h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(peer), MTPint(), MTPint(), MTP_int(replyToId()), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaContact(MTP_string(phone), MTP_string(fname), MTP_string(lname), MTP_int(userId)), MTPnullMarkup, MTPnullEntities));
h->sendRequestId = MTP::send(MTPmessages_SendMedia(MTP_int(sendFlags), p->input, MTP_int(replyTo), MTP_inputMediaContact(MTP_string(phone), MTP_string(fname), MTP_string(lname)), MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, h->sendRequestId);
App::historyRegRandom(randomId, newId);
@@ -3382,6 +3469,7 @@ void HistoryWidget::animShow(const QPixmap &bgAnimCache, const QPixmap &bgAnimTo
_field.hide();
_replyForwardPreviewCancel.hide();
_send.hide();
_unblock.hide();
_botStart.hide();
a_coord = back ? anim::ivalue(-st::introSlideShift, 0) : anim::ivalue(st::introSlideShift, 0);
a_alpha = anim::fvalue(0, 1);
@@ -3434,7 +3522,7 @@ void HistoryWidget::animStop() {
bool HistoryWidget::recordStep(float64 ms) {
float64 dt = ms / st::btnSend.duration;
bool res = true;
if (dt >= 1 || !_send.isHidden() || isBotStart()) {
if (dt >= 1 || !_send.isHidden() || isBotStart() || isBlocked()) {
res = false;
a_recordOver.finish();
a_recordDown.finish();
@@ -3602,6 +3690,8 @@ void HistoryWidget::stopRecording(bool send) {
_recording = false;
_recordingSamples = 0;
updateSendAction(_history, SendActionRecordAudio, -1);
updateControlsVisibility();
activate();
@@ -3749,10 +3839,14 @@ bool HistoryWidget::isBotStart() const {
return !_peer->asUser()->botInfo->startToken.isEmpty() || (_history->isEmpty() && !_history->lastMsg);
}
bool HistoryWidget::isBlocked() const {
return _peer && !_peer->chat && _peer->asUser()->blocked == UserIsBlocked;
}
bool HistoryWidget::updateCmdStartShown() {
bool cmdStartShown = false;
if (_history && _peer && ((_peer->chat && _peer->asChat()->botStatus > 0) || (!_peer->chat && _peer->asUser()->botInfo))) {
if (!isBotStart() && !_keyboard.hasMarkup() && !_keyboard.forceReply()) {
if (!isBotStart() && !isBlocked() && !_keyboard.hasMarkup() && !_keyboard.forceReply()) {
if (_field.getLastText().isEmpty()) {
cmdStartShown = true;
}
@@ -3922,7 +4016,7 @@ void HistoryWidget::paintTopBar(QPainter &p, float64 over, int32 decreaseWidth)
decreaseWidth += increaseLeft;
QRect rectForName(st::topBarForwardPadding.left() + increaseLeft, st::topBarForwardPadding.top(), width() - decreaseWidth - st::topBarForwardPadding.left() - st::topBarForwardPadding.right(), st::msgNameFont->height);
p.setFont(st::dlgHistFont->f);
if (_history->typing.isEmpty()) {
if (_history->typing.isEmpty() && _history->sendActions.isEmpty()) {
p.setPen(st::titleStatusColor->p);
p.drawText(rectForName.x(), st::topBarHeight - st::topBarForwardPadding.bottom() - st::dlgHistFont->height + st::dlgHistFont->ascent, _titlePeerText);
} else {
@@ -3964,7 +4058,7 @@ void HistoryWidget::updateOnlineDisplay(int32 x, int32 w) {
int32 t = unixtime();
if (_peer->chat) {
ChatData *chat = _peer->asChat();
if (chat->forbidden) {
if (chat->forbidden || chat->left) {
text = lang(lng_chat_status_unaccessible);
} else if (chat->participants.isEmpty()) {
text = _titlePeerText.isEmpty() ? lng_chat_status_members(lt_count, chat->count < 0 ? 0 : chat->count) : _titlePeerText;
@@ -4031,6 +4125,7 @@ void HistoryWidget::onFieldResize() {
_attachDocument.move(0, height() - kbh - _attachDocument.height());
_attachPhoto.move(_attachDocument.x(), _attachDocument.y());
_botStart.setGeometry(0, _attachDocument.y(), width(), _botStart.height());
_unblock.setGeometry(0, _attachDocument.y(), width(), _unblock.height());
_send.move(width() - _send.width(), _attachDocument.y());
_attachEmoji.move(_send.x() - _attachEmoji.width(), height() - kbh - _attachEmoji.height());
_kbShow.move(_attachEmoji.x() - _kbShow.width(), height() - kbh - _kbShow.height());
@@ -4188,10 +4283,10 @@ void HistoryWidget::confirmSendImage(const ReadyLocalMedia &img) {
connect(App::uploader(), SIGNAL(documentReady(MsgId, const MTPInputFile &)), this, SLOT(onDocumentUploaded(MsgId, const MTPInputFile &)), Qt::UniqueConnection);
connect(App::uploader(), SIGNAL(thumbDocumentReady(MsgId, const MTPInputFile &, const MTPInputFile &)), this, SLOT(onThumbDocumentUploaded(MsgId, const MTPInputFile &, const MTPInputFile &)), Qt::UniqueConnection);
connect(App::uploader(), SIGNAL(audioReady(MsgId, const MTPInputFile &)), this, SLOT(onAudioUploaded(MsgId, const MTPInputFile &)), Qt::UniqueConnection);
// connect(App::uploader(), SIGNAL(photoProgress(MsgId)), this, SLOT(onPhotoProgress(MsgId)), Qt::UniqueConnection);
connect(App::uploader(), SIGNAL(photoProgress(MsgId)), this, SLOT(onPhotoProgress(MsgId)), Qt::UniqueConnection);
connect(App::uploader(), SIGNAL(documentProgress(MsgId)), this, SLOT(onDocumentProgress(MsgId)), Qt::UniqueConnection);
connect(App::uploader(), SIGNAL(audioProgress(MsgId)), this, SLOT(onAudioProgress(MsgId)), Qt::UniqueConnection);
// connect(App::uploader(), SIGNAL(photoFailed(MsgId)), this, SLOT(onPhotoFailed(MsgId)), Qt::UniqueConnection);
connect(App::uploader(), SIGNAL(photoFailed(MsgId)), this, SLOT(onPhotoFailed(MsgId)), Qt::UniqueConnection);
connect(App::uploader(), SIGNAL(documentFailed(MsgId)), this, SLOT(onDocumentFailed(MsgId)), Qt::UniqueConnection);
connect(App::uploader(), SIGNAL(audioFailed(MsgId)), this, SLOT(onAudioFailed(MsgId)), Qt::UniqueConnection);
@@ -4204,11 +4299,11 @@ void HistoryWidget::confirmSendImage(const ReadyLocalMedia &img) {
int32 flags = newMessageFlags(h->peer); // unread, out
if (img.replyTo) flags |= MTPDmessage::flag_reply_to_msg_id;
if (img.type == ToPreparePhoto) {
h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaPhoto(img.photo, MTP_string("")), MTPnullMarkup));
h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaPhoto(img.photo, MTP_string("")), MTPnullMarkup, MTPnullEntities));
} else if (img.type == ToPrepareDocument) {
h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaDocument(img.document), MTPnullMarkup));
h->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaDocument(img.document), MTPnullMarkup, MTPnullEntities));
} else if (img.type == ToPrepareAudio) {
h->addToBack(MTP_message(MTP_int(flags | MTPDmessage_flag_media_unread), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaAudio(img.audio), MTPnullMarkup));
h->addToBack(MTP_message(MTP_int(flags | MTPDmessage_flag_media_unread), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(img.peer), MTPint(), MTPint(), MTP_int(img.replyTo), MTP_int(unixtime()), MTP_string(""), MTP_messageMediaAudio(img.audio), MTPnullMarkup, MTPnullEntities));
}
if (_peer && img.peer == _peer->id) {
@@ -4328,10 +4423,22 @@ void HistoryWidget::onAudioUploaded(MsgId newId, const MTPInputFile &file) {
}
}
void HistoryWidget::onPhotoProgress(MsgId newId) {
if (!MTP::authedId()) return;
HistoryItem *item = App::histItemById(newId);
if (item) {
PhotoData *photo = (item->getMedia() && item->getMedia()->type() == MediaTypePhoto) ? static_cast<HistoryPhoto*>(item->getMedia())->photo() : 0;
updateSendAction(item->history(), SendActionUploadPhoto, 0);
// msgUpdated(item->history()->peer->id, item);
}
}
void HistoryWidget::onDocumentProgress(MsgId newId) {
if (!MTP::authedId()) return;
HistoryItem *item = App::histItemById(newId);
if (item) {
DocumentData *doc = (item->getMedia() && item->getMedia()->type() == MediaTypeDocument) ? static_cast<HistoryDocument*>(item->getMedia())->document() : 0;
updateSendAction(item->history(), SendActionUploadFile, doc ? doc->uploadOffset : 0);
msgUpdated(item->history()->peer->id, item);
}
}
@@ -4340,14 +4447,26 @@ void HistoryWidget::onAudioProgress(MsgId newId) {
if (!MTP::authedId()) return;
HistoryItem *item = App::histItemById(newId);
if (item) {
AudioData *audio = (item->getMedia() && item->getMedia()->type() == MediaTypeAudio) ? static_cast<HistoryAudio*>(item->getMedia())->audio() : 0;
updateSendAction(item->history(), SendActionUploadAudio, audio ? audio->uploadOffset : 0);
msgUpdated(item->history()->peer->id, item);
}
}
void HistoryWidget::onPhotoFailed(MsgId newId) {
if (!MTP::authedId()) return;
HistoryItem *item = App::histItemById(newId);
if (item) {
updateSendAction(item->history(), SendActionUploadPhoto, -1);
// msgUpdated(item->history()->peer->id, item);
}
}
void HistoryWidget::onDocumentFailed(MsgId newId) {
if (!MTP::authedId()) return;
HistoryItem *item = App::histItemById(newId);
if (item) {
updateSendAction(item->history(), SendActionUploadFile, -1);
msgUpdated(item->history()->peer->id, item);
}
}
@@ -4356,6 +4475,7 @@ void HistoryWidget::onAudioFailed(MsgId newId) {
if (!MTP::authedId()) return;
HistoryItem *item = App::histItemById(newId);
if (item) {
updateSendAction(item->history(), SendActionUploadAudio, -1);
msgUpdated(item->history()->peer->id, item);
}
}
@@ -4364,7 +4484,7 @@ void HistoryWidget::peerMessagesUpdated(PeerId peer) {
if (_peer && _list && peer == _peer->id) {
updateListSize();
updateBotKeyboard();
if (!_scroll.isHidden() && _botStart.isHidden() == isBotStart()) {
if (!_scroll.isHidden() && !isBlocked() && _botStart.isHidden() == isBotStart()) {
updateControlsVisibility();
resizeEvent(0);
}
@@ -4405,6 +4525,7 @@ void HistoryWidget::resizeEvent(QResizeEvent *e) {
_send.move(width() - _send.width(), _attachDocument.y());
_botStart.setGeometry(0, _attachDocument.y(), width(), _botStart.height());
_unblock.setGeometry(0, _attachDocument.y(), width(), _unblock.height());
_attachEmoji.move(_send.x() - _attachEmoji.width(), height() - kbh - _attachEmoji.height());
_kbShow.move(_attachEmoji.x() - _kbShow.width(), height() - kbh - _kbShow.height());
_kbHide.move(_attachEmoji.x(), _attachEmoji.y());
@@ -4474,10 +4595,12 @@ void HistoryWidget::updateListSize(int32 addToY, bool initial, bool loadedDown,
}
int32 newScrollHeight = height();
if (isBotStart()) {
if (isBlocked()) {
newScrollHeight -= _unblock.height();
} else if (isBotStart()) {
newScrollHeight -= _botStart.height();
} else {
if (!_peer->chat || !_peer->asChat()->forbidden) {
if ((_peer->chat && !_peer->asChat()->forbidden && !_peer->asChat()->left) || (!_peer->chat && _peer->asUser()->access != UserNoAccess)) {
newScrollHeight -= (_field.height() + 2 * st::sendPadding);
}
if (replyToId() || App::main()->hasForwardingItems() || (_previewData && _previewData->pendingTill >= 0)) {
@@ -4613,7 +4736,7 @@ void HistoryWidget::updateBotKeyboard() {
bool hasMarkup = _keyboard.hasMarkup(), forceReply = _keyboard.forceReply() && !_replyTo;
if (hasMarkup || forceReply) {
if (_keyboard.singleUse() && _keyboard.hasMarkup() && _keyboard.forMsgId() == _history->lastKeyboardId && _history->lastKeyboardUsed) _kbWasHidden = true;
if (!isBotStart() && (wasVisible || _replyTo || (_field.getLastText().isEmpty() && !_kbWasHidden))) {
if (!isBotStart() && !isBlocked() && (wasVisible || _replyTo || (_field.getLastText().isEmpty() && !_kbWasHidden))) {
if (!_showAnim.animating()) {
if (hasMarkup) {
_kbScroll.show();
@@ -4753,6 +4876,8 @@ void HistoryWidget::keyPressEvent(QKeyEvent *e) {
App::main()->peerAfter(_peer, msgid, p, m);
}
if (p) App::main()->showPeerHistory(p->id, m);
} else if (_history && (e->key() == Qt::Key_Search || e == QKeySequence::Find)) {
App::main()->searchInPeer(_history->peer);
} else {
e->ignore();
}
@@ -5029,6 +5154,9 @@ void HistoryWidget::onFullPeerUpdated(PeerData *data) {
updateControlsVisibility();
resizeEvent(0);
update();
} else if (!_scroll.isHidden() && _unblock.isHidden() == isBlocked()) {
updateControlsVisibility();
resizeEvent(0);
}
if (newScrollTop != _scroll.scrollTop()) {
if (_scroll.isVisible()) {
@@ -5045,6 +5173,11 @@ void HistoryWidget::peerUpdated(PeerData *data) {
if (!_showAnim.animating()) updateControlsVisibility();
if (data->chat && data->asChat()->count > 0 && data->asChat()->participants.isEmpty()) {
App::api()->requestFullPeer(data);
} else if (!data->chat && data->asUser()->blocked == UserBlockUnknown) {
App::api()->requestFullPeer(data);
} else if (!_scroll.isHidden() && _unblock.isHidden() == isBlocked()) {
updateControlsVisibility();
resizeEvent(0);
}
App::main()->updateOnlineDisplay();
}
@@ -5160,7 +5293,7 @@ void HistoryWidget::updateTopBarSelection() {
updateControlsVisibility();
updateListSize();
if (!App::wnd()->layerShown() && !App::passcoded()) {
if (_selCount || (_list && _list->wasSelectedText()) || _recording || isBotStart()) {
if (_selCount || (_list && _list->wasSelectedText()) || _recording || isBotStart() || isBlocked()) {
_list->setFocus();
} else {
_field.setFocus();

View File

@@ -386,10 +386,12 @@ public:
QRect historyRect() const;
void updateTyping(bool typing = true);
void updateSendAction(History *history, SendActionType type, int32 progress = 0);
void cancelSendAction(History *history, SendActionType type);
void updateRecentStickers();
void stickersInstalled(uint64 setId);
void typingDone(const MTPBool &result, mtpRequestId req);
void sendActionDone(const MTPBool &result, mtpRequestId req);
void destroyData();
void uploadImage(const QImage &img, bool withText = false, const QString &source = QString());
@@ -489,6 +491,8 @@ public slots:
void onReplyToMessage();
void onReplyForwardPreviewCancel();
void onCancelSendAction();
void onStickerPackInfo();
void onPreviewParse();
@@ -498,22 +502,23 @@ public slots:
void peerUpdated(PeerData *data);
void onFullPeerUpdated(PeerData *data);
void cancelTyping();
void onPhotoUploaded(MsgId msgId, const MTPInputFile &file);
void onDocumentUploaded(MsgId msgId, const MTPInputFile &file);
void onThumbDocumentUploaded(MsgId msgId, const MTPInputFile &file, const MTPInputFile &thumb);
void onAudioUploaded(MsgId msgId, const MTPInputFile &file);
void onPhotoProgress(MsgId msgId);
void onDocumentProgress(MsgId msgId);
void onAudioProgress(MsgId msgId);
void onPhotoFailed(MsgId msgId);
void onDocumentFailed(MsgId msgId);
void onAudioFailed(MsgId msgId);
void onListScroll();
void onHistoryToEnd();
void onSend(bool ctrlShiftEnter = false, MsgId replyTo = -1);
void onUnblock();
void onBotStart();
void onPhotoSelect();
@@ -600,6 +605,9 @@ private:
void addMessagesToFront(const QVector<MTPMessage> &messages);
void addMessagesToBack(const QVector<MTPMessage> &messages);
void unblockDone(PeerData *peer, const MTPBool &result);
bool unblockFail(const RPCError &error);
void countHistoryShowFrom();
void updateToEndVisibility();
@@ -636,9 +644,11 @@ private:
MentionsDropdown _attachMention;
bool isBotStart() const;
bool isBlocked() const;
bool updateCmdStartShown();
FlatButton _send, _botStart;
FlatButton _send, _unblock, _botStart;
mtpRequestId _unblockRequest;
IconedButton _attachDocument, _attachPhoto, _attachEmoji, _kbShow, _kbHide, _cmdStart;
bool _cmdStartShown;
MessageField _field;
@@ -685,8 +695,8 @@ private:
QTimer _animActiveTimer;
float64 _animActiveStart;
mtpRequestId _typingRequest;
QTimer _typingStopTimer;
QMap<QPair<History*, SendActionType>, mtpRequestId> _sendActionRequests;
QTimer _sendActionStopTimer;
uint64 _saveDraftStart;
bool _saveDraftText;

View File

@@ -28,7 +28,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_open_from_tray" = "Telegram öffnen";
"lng_minimize_to_tray" = "Minimieren";
"lng_quit_from_tray" = "Telegram beenden";
"lng_tray_icon_text" = "Telegram ist noch aktiv,\ndu kannst das in den Einstellungen anpassen.\n\nWenn dieses Symbol aus der Taskleiste verschwindet,\nkannst du es wieder hierher ziehen.";
"lng_tray_icon_text" = "Telegram ist minimiert und läuft im Hintergrund,\ndu kannst das in den Einstellungen ändern.\nUm Telegram wieder anzuzeigen, klicke auf \ndas Symbol im Benachrichtigungsfeld.";
"lng_month1" = "Januar";
"lng_month2" = "Februar";
@@ -69,6 +69,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_reconnecting_try_now" = "Jetzt versuchen";
"lng_status_service_notifications" = "Servicemeldungen";
"lng_status_support" = "Support";
"lng_status_bot" = "Bot";
"lng_status_bot_reads_all" = "hat Zugriff auf Nachrichten";
"lng_status_bot_not_reads_all" = "hat keinen Zugriff auf Nachrichten";
@@ -156,8 +157,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_dlg_new_group_name" = "Name der Gruppe";
"lng_dlg_create_group" = "Erstellen";
"lng_no_contacts" = "Du hast keine Kontakte";
"lng_no_chats" = "Noch keine Chats";
"lng_contacts_loading" = "Lade..";
"lng_contacts_not_found" = "Keine Kontakte gefunden";
"lng_dlg_search_chat" = "In diesem Chat suchen";
"lng_dlg_search_for_messages" = "Nach Nachrichten suchen";
"lng_settings_save" = "Speichern";
"lng_settings_upload" = "Profilbild festlegen";
@@ -180,8 +184,9 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_section_notify" = "Benachrichtigungen";
"lng_settings_desktop_notify" = "Desktopbenachrichtigungen";
"lng_settings_show_name" = "Sendername anzeigen";
"lng_settings_show_name" = "Absendername anzeigen";
"lng_settings_show_preview" = "Nachrichtenvorschau anzeigen";
"lng_settings_use_windows" = "Windows Benachrichtigungen";
"lng_settings_sound_notify" = "Ton abspielen";
"lng_notification_preview" = "Du hast eine neue Nachricht";
@@ -289,7 +294,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_cloud_password_bad" = "Kennwort und Hinweis müssen sich unterscheiden.";
"lng_cloud_password_email" = "E-Mail für die Wiederherstellung";
"lng_cloud_password_bad_email" = "Ungültige E-Mai, bitte erneut versuchen.";
"lng_cloud_password_about" = "Du kannst ein eigenes Kennwort festlegen, um dich an einem neuen Gerät anzumelden, zusätzlich zum SMS-Code.";
"lng_cloud_password_about" = "Dieses Kennwort brauchst du, wenn du dich mit einem neuen Gerät anmeldest.";
"lng_cloud_password_about_recover" = "Hinweis! Möchtest du wirklich keine E-Mail\nAdresse hinterlegen? \n\nWenn dir dein Kennwort nicht mehr einfällt, \nverlierst du Zugriff auf dein Telegram Konto.";
"lng_cloud_password_almost" = "Ein Bestätigungslink wurde an\ndeine E-Mail Adresse gesendet.\n\nZweistufige Bestätigung wird aktiviert,\nsobald du den Link öffnest.";
"lng_cloud_password_was_set" = "Zweistufige Bestätigung aktiviert.";
@@ -320,6 +325,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_reset_one_sure" = "Dieses Gerät wirklich abmelden?";
"lng_settings_reset_button" = "Beenden";
"lng_settings_reset_done" = "Alle anderen Sitzungen wurden erfolgreich beendet.";
"lng_settings_ask_question" = "Eine Frage stellen";
"lng_settings_ask_sure" = "Bedenke bitte, dass der Telegram Support von ehrenamtlichen Helfern betreut wird.\n\nKennst du schon die Telegram FAQ? Dort findest du Antworten auf die am häufigsten gestellten Fragen.";
"lng_settings_faq_button" = "FAQ öffnen";
"lng_settings_ask_ok" = "Frage stellen";
"lng_settings_faq" = "Telegram FAQ";
"lng_settings_logout" = "Abmelden";
"lng_sure_logout" = "Du kannst Telegram von all deinen Geräten gleichzeitig nutzen. Wirklich abmelden?";
@@ -339,6 +349,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_topbar_info" = "Info";
"lng_profile_about_section" = "Info";
"lng_profile_settings_section" = "Einstellungen";
"lng_profile_actions_section" = "Aktionen";
"lng_profile_bot_settings" = "Einstellungen";
"lng_profile_bot_help" = "Hilfe";
"lng_profile_participants_section" = "Teilnehmer";
@@ -348,6 +359,13 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_profile_edit_contact" = "Bearbeiten";
"lng_profile_enable_notifications" = "Benachrichtigungen";
"lng_profile_clear_history" = "Chatverlauf löschen";
"lng_profile_delete_conversation" = "Chat entfernen";
"lng_profile_clear_and_exit" = "Löschen und verlassen";
"lng_profile_search_messages" = "In diesem Chat suchen";
"lng_profile_block_user" = "Blockieren";
"lng_profile_unblock_user" = "Freigeben";
"lng_profile_block_bot" = "Bot anhalten und blockieren";
"lng_profile_unblock_bot" = "Bot freigeben";
"lng_profile_send_message" = "Nachricht senden";
"lng_profile_share_contact" = "Kontakt teilen";
"lng_profile_invite_to_group" = "In eine Gruppe einladen";
@@ -379,13 +397,16 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_create_group_title" = "Neue Gruppe erstellen";
"lng_failed_add_participant" = "Kann Teilnehmer nicht hinzufügen. Später erneut versuchen.";
"lng_failed_add_not_mutual" = "Wenn man eine Gruppe verlässt, kann nur \nein gemeinsamer Kontakt die Person erneut \neinladen (beide Seiten müssen die Nummer\n des anderen gespeichert haben).";
"lng_sure_delete_contact" = "Bist du sicher, dass du {contact} von deinen Kontakten löschen willst?";
"lng_sure_delete_history" = "Sicher, dass du den kompletten Verlauf mit {contact} löschen willst?\n\nDas kann man nicht rückgängig machen.";
"lng_sure_delete_group_history" = "Möchtest du wirklich deinen Verlauf von «{group}» löschen?\n\nDas kann man nicht rückgängig machen.";
"lng_sure_delete_and_exit" = "Deinen Verlauf von «{group}» löschen und die Gruppe verlassen?\n\nDas kann man nicht rückgängig machen.";
"lng_message_empty" = "(empty)";
"lng_message_empty" = "Leere Nachricht";
"lng_media_unsupported" = "Format Nicht Unterstützt";
"lng_action_add_user" = "{from} hat {user} hinzugefügt";
"lng_action_kick_user" = "{from} hat {user} entfernt";
@@ -461,10 +482,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_message_ph" = "Schreibe deine Nachricht..";
"lng_record_cancel" = "Zum Abbrechen rausbewegen";
"lng_empty_history" = "";
"lng_willbe_history" = "Wähle einen Chat aus, um zu schreiben";
"lng_willbe_history" = "Chat auswählen um zu schreiben";
"lng_message_with_from" = "[c]{from}:[/c] {message}";
"lng_from_you" = "Ich";
"lng_bot_description" = "Was kann dieser Bot?";
"lng_unblock_button" = "Freigeben";
"lng_bot_start" = "Starten";
"lng_bot_choose_group" = "Gruppe auswählen";
@@ -477,6 +499,22 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_user_typing" = "{user} tippt";
"lng_users_typing" = "{user} und {second_user} tippen";
"lng_many_typing" = "{count:_not_used_|# tippt|# tippen}";
"lng_send_action_record_video" = "schickt Video";
"lng_user_action_record_video" = "{user} sendet Video";
"lng_send_action_upload_video" = "schickt Video";
"lng_user_action_upload_video" = "{user} sendet Video";
"lng_send_action_record_audio" = "nimmt Audio auf";
"lng_user_action_record_audio" = "{user} nimmt Audio auf";
"lng_send_action_upload_audio" = "nimmt Audio auf";
"lng_user_action_upload_audio" = "{user} sendet Audio";
"lng_send_action_upload_photo" = "sendet Bild";
"lng_user_action_upload_photo" = "{user} sendet Bild";
"lng_send_action_upload_file" = "sendet Datei";
"lng_user_action_upload_file" = "{user} sendet Datei";
"lng_send_action_geo_location" = "wählt Standort aus";
"lng_user_action_geo_location" = "{user} wählt Standort aus";
"lng_send_action_choose_contact" = "wählt Kontakt aus";
"lng_user_action_choose_contact" = "{user} wählt Kontakt aus";
"lng_unread_bar" = "{count:_not_used_|# Ungelesene Nachricht|# Ungelesene Nachrichten}";
"lng_maps_point" = "Standort";
@@ -603,7 +641,7 @@ Copyright (c) 2014 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" = "— In-App Medienwiedergabe optimiert\n— Fehlerbehebungen und kleinere Verbesserungen";
"lng_new_version_text" = "— Direkte Suche in Chats (Chat auswählen und STRG+F drücken)\n— Verlauf in Gruppen löschen (in der Gruppe auf den Gruppennamen tippen)\n— Kontakte, mit denen du nicht chattest, werden nicht mehr in der Übersicht gezeigt";
"lng_menu_insert_unicode" = "Unicode-Steuerzeichen einfügen";

View File

@@ -28,7 +28,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_open_from_tray" = "Abrir Telegram";
"lng_minimize_to_tray" = "Minimizar al icono";
"lng_quit_from_tray" = "Salir de Telegram";
"lng_tray_icon_text" = "Telegram sigue funcionando aquí, \npuedes cambiar esto desde los ajustes.\n\nSi este ícono desaparece desde el menú,\npuedes arrastrarlo de regreso desde los iconos ocultos.";
"lng_tray_icon_text" = "Telegram aún está funcionando,\npuedes cambiar esto en los ajustes. \nSi este icono desaparece del menú, \npuedes arrastrarlo aquí desde los iconos ocultos.";
"lng_month1" = "enero";
"lng_month2" = "febrero";
@@ -69,6 +69,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_reconnecting_try_now" = "Intentar ahora";
"lng_status_service_notifications" = "servicio de notificaciones";
"lng_status_support" = "soporte";
"lng_status_bot" = "bot";
"lng_status_bot_reads_all" = "tiene acceso a los mensajes";
"lng_status_bot_not_reads_all" = "no tiene acceso a los mensajes";
@@ -156,8 +157,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_dlg_new_group_name" = "Nombre del grupo";
"lng_dlg_create_group" = "Crear";
"lng_no_contacts" = "No tienes contactos";
"lng_no_chats" = "Tus chats estarán aquí";
"lng_contacts_loading" = "Cargando...";
"lng_contacts_not_found" = "No se encontraron contactos";
"lng_dlg_search_chat" = "Buscar en este chat";
"lng_dlg_search_for_messages" = "Buscar mensajes";
"lng_settings_save" = "Guardar";
"lng_settings_upload" = "Poner foto de perfil";
@@ -182,6 +186,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_desktop_notify" = "Notificaciones de escritorio";
"lng_settings_show_name" = "Mostrar el nombre del remitente";
"lng_settings_show_preview" = "Mostrar la vista previa del mensaje";
"lng_settings_use_windows" = "Usar notificaciones de Windows";
"lng_settings_sound_notify" = "Reproducir sonido";
"lng_notification_preview" = "Tienes un nuevo mensaje";
@@ -289,7 +294,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_cloud_password_bad" = "La contraseña y la pista no pueden ser iguales.";
"lng_cloud_password_email" = "Pon un e-mail de recuperación";
"lng_cloud_password_bad_email" = "E-mail incorrecto. Por favor, prueba otro.";
"lng_cloud_password_about" = "Esta contraseña será requerida cuando inicies sesión en un nuevo dispositivo, además del código de activación.";
"lng_cloud_password_about" = "Necesitarás la contraseña al iniciar sesión en un nuevo dispositivo, además del código de activación.";
"lng_cloud_password_about_recover" = "¡Advertencia! ¿No quieres añadir un e-mail \nde recuperación para la contraseña?\n\nSi olvidas tu contraseña, perderás\nel acceso a tu cuenta de Telegram.";
"lng_cloud_password_almost" = "Un enlace de confirmación fue enviado\nal e-mail que estableciste.\n\nLa verificación en dos pasos se activará\nen cuanto sigas ese enlace.";
"lng_cloud_password_was_set" = "Verificación en dos pasos activada.";
@@ -320,6 +325,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_reset_one_sure" = "¿Quieres cerrar esta sesión?";
"lng_settings_reset_button" = "Cerrar";
"lng_settings_reset_done" = "Se cerraron las otras sesiones";
"lng_settings_ask_question" = "Hacer una pregunta";
"lng_settings_ask_sure" = "Por favor, considera que el soporte de Telegram está hecho por voluntarios. Respondemos lo antes posible, pero puede tomar tiempo.\n\nSi quieres, mira las preguntas frecuentes de Telegram: tienen soluciones a problemas y respuestas para la mayoría de las preguntas.";
"lng_settings_faq_button" = "Preguntas frecuentes";
"lng_settings_ask_ok" = "Preguntar";
"lng_settings_faq" = "Preguntas frecuentes";
"lng_settings_logout" = "Cerrar sesión";
"lng_sure_logout" = "¿Quieres cerrar sesión?";
@@ -339,6 +349,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_topbar_info" = "Información";
"lng_profile_about_section" = "Acerca de";
"lng_profile_settings_section" = "Ajustes";
"lng_profile_actions_section" = "Acciones";
"lng_profile_bot_settings" = "Ajustes";
"lng_profile_bot_help" = "Ayuda";
"lng_profile_participants_section" = "Miembros";
@@ -348,6 +359,13 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_profile_edit_contact" = "Editar";
"lng_profile_enable_notifications" = "Notificaciones";
"lng_profile_clear_history" = "Borrar historial";
"lng_profile_delete_conversation" = "Eliminar chat";
"lng_profile_clear_and_exit" = "Eliminar y salir";
"lng_profile_search_messages" = "Buscar mensajes";
"lng_profile_block_user" = "Bloquear";
"lng_profile_unblock_user" = "Desbloquear";
"lng_profile_block_bot" = "Detener y bloquear el bot";
"lng_profile_unblock_bot" = "Desbloquear el bot";
"lng_profile_send_message" = "Enviar mensaje";
"lng_profile_share_contact" = "Compartir contacto";
"lng_profile_invite_to_group" = "Añadir al grupo";
@@ -359,7 +377,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_profile_sure_kick" = "¿Quieres expulsar a {user} del grupo?";
"lng_profile_loading" = "Cargando...";
"lng_profile_shared_media" = "Todos los archivos";
"lng_profile_no_media" = "No hay multimedia en esta conversación.";
"lng_profile_no_media" = "No hay multimedia en este chat.";
"lng_profile_photos" = "{count:_not_used_|# foto|# fotos} »";
"lng_profile_photos_header" = "Todas las fotos";
"lng_profile_videos" = "{count:_not_used_|# vídeo|# vídeos} »";
@@ -379,13 +397,16 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_create_group_title" = "Nuevo grupo";
"lng_failed_add_participant" = "No se pudo añadir el usuario. Por favor, inténtalo más tarde.";
"lng_failed_add_not_mutual" = "Si una persona dejó el grupo, sólo\nun contacto mutuo puede volver \na invitarlo (necesitan tener tu \nnúmero y tú el de ellos).";
"lng_sure_delete_contact" = "¿Quieres eliminar a {contact} de tu lista de contactos?";
"lng_sure_delete_history" = "¿Quieres eliminar todo el historial de mensajes con {contact}?\n\nEsta acción no se puede deshacer.";
"lng_sure_delete_group_history" = "¿Quieres borrar todo el historial en «{group}»?\n\nEsta acción no se puede deshacer.";
"lng_sure_delete_and_exit" = "¿Quieres eliminar todo el historial de mensajes y dejar el grupo «{group}»?\n\nEsta acción no se puede deshacer.";
"lng_message_empty" = "(vacío)";
"lng_message_empty" = "Mensaje vacío";
"lng_media_unsupported" = "Multimedia no soportada";
"lng_action_add_user" = "{from} añadió a {user}";
"lng_action_kick_user" = "{from} expulsó a {user}";
@@ -461,10 +482,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_message_ph" = "Escribir un mensaje...";
"lng_record_cancel" = "Suelta fuera de aquí para cancelar";
"lng_empty_history" = "";
"lng_willbe_history" = "Por favor, elige un chat para comenzar a conversar";
"lng_willbe_history" = "Por favor, elige un chat para comenzar";
"lng_message_with_from" = "[c]{from}:[/c] {message}";
"lng_from_you" = "Tú";
"lng_bot_description" = "¿Qué puede hacer este bot?";
"lng_unblock_button" = "Desbloquear";
"lng_bot_start" = "Iniciar";
"lng_bot_choose_group" = "Elegir grupo";
@@ -477,6 +499,22 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_user_typing" = "{user} está escribiendo";
"lng_users_typing" = "{user} y {second_user} están escribiendo";
"lng_many_typing" = "{count:_not_used_|# está|# están} escribiendo";
"lng_send_action_record_video" = "grabando vídeo";
"lng_user_action_record_video" = "{user} está grabando un vídeo";
"lng_send_action_upload_video" = "enviando vídeo";
"lng_user_action_upload_video" = "{user} está enviando un vídeo";
"lng_send_action_record_audio" = "grabando audio";
"lng_user_action_record_audio" = "{user} está grabando un audio";
"lng_send_action_upload_audio" = "enviando audio";
"lng_user_action_upload_audio" = "{user} está enviando un audio";
"lng_send_action_upload_photo" = "enviando foto";
"lng_user_action_upload_photo" = "{user} está enviando una foto";
"lng_send_action_upload_file" = "enviando archivo";
"lng_user_action_upload_file" = "{user} está enviando un archivo";
"lng_send_action_geo_location" = "obteniendo ubicación";
"lng_user_action_geo_location" = "{user} está obteniendo una ubicación";
"lng_send_action_choose_contact" = "eligiendo contacto";
"lng_user_action_choose_contact" = "{user} está eligiendo un contacto";
"lng_unread_bar" = "{count:_not_used_|# mensaje sin leer|# mensajes sin leer}";
"lng_maps_point" = "Ubicación";
@@ -603,7 +641,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_new_version_wrap" = "Telegram Desktop fue 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" = "— Reproducción de la multimedia dentro de la aplicación mejorada\n— Corrección de errores y otras mejoras menores";
"lng_new_version_text" = "— Busca mensajes en un chat\n— Borra el historial de mensajes en grupos\n— Los contactos sin mensajes se ocultarán de la lista de chats";
"lng_menu_insert_unicode" = "Insertar caracteres de control Unicode";

View File

@@ -26,9 +26,9 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_menu_back" = "Indietro";
"lng_open_from_tray" = "Apri Telegram";
"lng_minimize_to_tray" = "Minimizza";
"lng_minimize_to_tray" = "Riduci a icona";
"lng_quit_from_tray" = "Chiudi Telegram";
"lng_tray_icon_text" = "Telegram è ancora aperto qui,\npuoi cambiare questo nelle impostazioni.\n\nSe l'icona scompare dall'area di notifica,\npuoi riportarla indietro dalle icone nascoste.";
"lng_tray_icon_text" = "Telegram è ancora attivo qui,\npuoi modificarlo nelle impostazioni.\nSe l'icona scompare dall'area di notifica,\npuoi ripristinarla dalle icone nascoste.";
"lng_month1" = "Gennaio";
"lng_month2" = "Febbraio";
@@ -69,6 +69,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_reconnecting_try_now" = "Prova ora";
"lng_status_service_notifications" = "notifiche di servizio";
"lng_status_support" = "supporto";
"lng_status_bot" = "bot";
"lng_status_bot_reads_all" = "ha accesso ai messaggi";
"lng_status_bot_not_reads_all" = "non ha accesso ai messaggi";
@@ -156,8 +157,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_dlg_new_group_name" = "Nome gruppo";
"lng_dlg_create_group" = "Crea";
"lng_no_contacts" = "Non hai contatti";
"lng_no_chats" = "Le tua chat saranno qui";
"lng_contacts_loading" = "Caricamento..";
"lng_contacts_not_found" = "Nessun contatto trovato";
"lng_dlg_search_chat" = "Cerca in questa chat";
"lng_dlg_search_for_messages" = "Cerca messaggi";
"lng_settings_save" = "Salva";
"lng_settings_upload" = "Imposta foto profilo";
@@ -182,6 +186,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_desktop_notify" = "Notifiche desktop";
"lng_settings_show_name" = "Mostra nome del mittente";
"lng_settings_show_preview" = "Mostra anteprima messaggio";
"lng_settings_use_windows" = "Usa le notifiche di Windows";
"lng_settings_sound_notify" = "Riproduci suono";
"lng_notification_preview" = "Hai un nuovo messaggio";
@@ -267,7 +272,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_passcode_enter_first" = "Inserisci un codice";
"lng_passcode_enter_new" = "Inserisci il nuovo codice";
"lng_passcode_confirm_new" = "Reinserisci il nuovo codice";
"lng_passcode_about" = "Quando imposti un codice, un'icona col lucchetto apparirà nel menu in alto. Premi su di essa per bloccare l'app. \n\nNota: se ti dimentichi il codice, dovrai rifare il login su Telegram Desktop.";
"lng_passcode_about" = "Quando imposti un codice, un'icona col lucchetto apparirà nel menu in alto. Premi su di essa per bloccare l'app. \n\nNota: se dimentichi il codice, dovrai rifare l'accesso su Telegram Desktop.";
"lng_passcode_differ" = "I codici sono diversi";
"lng_passcode_wrong" = "Codice errato";
"lng_passcode_is_same" = "Il codice non è stato cambiato";
@@ -320,6 +325,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_reset_one_sure" = "Vuoi terminare questa sessione?";
"lng_settings_reset_button" = "Chiudi";
"lng_settings_reset_done" = "Altre sessioni terminate";
"lng_settings_ask_question" = "Fai una domanda";
"lng_settings_ask_sure" = "Per favore, considera che il supporto su Telegram è offerto da volontari. Proveremo a risponderti il più velocemente possibile, ma potrebbe volerci un po' di tempo.\n\nDai un'occhiata alle FAQ di Telegram: potrai trovare importanti suggerimenti riguardo alcune problematiche e risposte alla maggior parte delle domande.";
"lng_settings_faq_button" = "Vai alle FAQ";
"lng_settings_ask_ok" = "Chiedi";
"lng_settings_faq" = "FAQ di Telegram";
"lng_settings_logout" = "Disconnetti";
"lng_sure_logout" = "Sicuro di volerti disconnettere?";
@@ -339,6 +349,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_topbar_info" = "Info";
"lng_profile_about_section" = "Info";
"lng_profile_settings_section" = "Impostazioni";
"lng_profile_actions_section" = "Azioni";
"lng_profile_bot_settings" = "Impostazioni";
"lng_profile_bot_help" = "Aiuto";
"lng_profile_participants_section" = "Membri";
@@ -348,6 +359,13 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_profile_edit_contact" = "Modifica";
"lng_profile_enable_notifications" = "Notifiche";
"lng_profile_clear_history" = "Cancella la cronologia";
"lng_profile_delete_conversation" = "Elimina chat";
"lng_profile_clear_and_exit" = "Elimina ed esci";
"lng_profile_search_messages" = "Cerca messaggi";
"lng_profile_block_user" = "Blocca utente";
"lng_profile_unblock_user" = "Sblocca utente";
"lng_profile_block_bot" = "Arresta e blocca bot";
"lng_profile_unblock_bot" = "Sblocca bot";
"lng_profile_send_message" = "Invia messaggio";
"lng_profile_share_contact" = "Condividi contatto";
"lng_profile_invite_to_group" = "Aggiungi a un gruppo";
@@ -379,13 +397,16 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_create_group_title" = "Nuovo gruppo";
"lng_failed_add_participant" = "Impossibile aggiungere l'utente. Riprova più tardi.";
"lng_failed_add_not_mutual" = "Se una persona lascia un gruppo,\nsolo un contatto in comune può reinvitarlo\n(devono avere il tuo numero\ndi telefono, e tu il loro).";
"lng_sure_delete_contact" = "Sicuro di volere eliminare {contact} dalla tua lista dei contatti?";
"lng_sure_delete_history" = "Sicuro di voler eliminare tutta la cronologia dei messaggi con {contact}?\n\nQuesta azione non può essere annullata.";
"lng_sure_delete_group_history" = "Sicuro di voler eliminare tutta la cronologia dei messaggi in «{group}»?\n\nQuesta azione non può essere annullata.";
"lng_sure_delete_and_exit" = "Sicuro di voler eliminare tutta la cronologia dei messaggi e abbandonare «{group}»?\n\nQuesta azione non può essere annullata.";
"lng_message_empty" = "(vuoto)";
"lng_message_empty" = "Messaggio vuoto";
"lng_media_unsupported" = "Media non supportato";
"lng_action_add_user" = "{from} ha aggiunto {user}";
"lng_action_kick_user" = "{from} ha rimosso {user}";
@@ -465,6 +486,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_message_with_from" = "[c]{from}:[/c] {message}";
"lng_from_you" = "Tu";
"lng_bot_description" = "Cosa può fare questo bot?";
"lng_unblock_button" = "Sblocca";
"lng_bot_start" = "Avvia";
"lng_bot_choose_group" = "Scegli gruppo";
@@ -477,6 +499,22 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_user_typing" = "{user} sta scrivendo";
"lng_users_typing" = "{user} e {second_user} stanno scrivendo";
"lng_many_typing" = "{count:_not_used_|# sta|# stanno} scrivendo";
"lng_send_action_record_video" = "registrando un video";
"lng_user_action_record_video" = "{user} sta registrando un video";
"lng_send_action_upload_video" = "inviando un video";
"lng_user_action_upload_video" = "{user} sta inviando un video";
"lng_send_action_record_audio" = "registrando un audio";
"lng_user_action_record_audio" = "{user} sta registrando un audio";
"lng_send_action_upload_audio" = "inviando un audio";
"lng_user_action_upload_audio" = "{user} sta inviando un audio";
"lng_send_action_upload_photo" = "inviando una foto";
"lng_user_action_upload_photo" = "{user} sta inviando una foto";
"lng_send_action_upload_file" = "inviando un file";
"lng_user_action_upload_file" = "{user} sta inviando un file";
"lng_send_action_geo_location" = "selezionando una posizione";
"lng_user_action_geo_location" = "{user} sta selezionando una posizione";
"lng_send_action_choose_contact" = "selezionando un contatto";
"lng_user_action_choose_contact" = "{user} sta selezionando un contatto";
"lng_unread_bar" = "{count:_not_used_|# messaggio non letto|# messaggi non letti}";
"lng_maps_point" = "Posizione";
@@ -603,7 +641,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_new_version_wrap" = "Telegram Desktop si è aggiornato alla versione {version}\n\n{changes}\n\nLa cronologia degli update è disponibile qui:\n{link}";
"lng_new_version_minor" = "— Bug fix e altri miglioramenti minori";
"lng_new_version_text" = "— Riproduzione dei media migliorata\n— Risoluzione di bug e miglioramenti minori";
"lng_new_version_text" = "— Cerca messaggi in una chat\n— Pulisci la cronologia dei messaggi nei gruppi\n— I contatti senza messaggi sono nascosti dalla lista delle chat";
"lng_menu_insert_unicode" = "Inserisci carattere di controllo Unicode";

View File

@@ -28,7 +28,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_open_from_tray" = "텔레그램 실행";
"lng_minimize_to_tray" = "창을 최소화";
"lng_quit_from_tray" = "텔레그램 종료";
"lng_tray_icon_text" = "텔레그램은 아직 실행중입니다.\n설정 화면에서 실행설정을 변경하실 수 있습니다.\n\n트레이메뉴에서 이 아이콘이 사라질 경우.\n숨겨진 아이콘 목록에서 다시 복원할 수 있습니다.";
"lng_tray_icon_text" = "텔레그램은 아직 실행중입니다. \n설정 화면에서 실행설정을 변경하실 수 있습니다. \n트레이메뉴에서 이 아이콘이 사라질 경우. \n숨겨진 아이콘 목록에서 다시 복원할 수 있습니다.";
"lng_month1" = "1월";
"lng_month2" = "2월";
@@ -69,6 +69,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_reconnecting_try_now" = "다시 시도";
"lng_status_service_notifications" = "서비스 알림";
"lng_status_support" = "support";
"lng_status_bot" = "bot";
"lng_status_bot_reads_all" = "메시지 접근 권한이 있습니다.";
"lng_status_bot_not_reads_all" = "메시지 접근 권한이 없습니다.";
@@ -156,8 +157,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_dlg_new_group_name" = "그룹이름";
"lng_dlg_create_group" = "만들기";
"lng_no_contacts" = "연락처가 없습니다.";
"lng_no_chats" = "대화시 대화방이 존재 할 곳입니다.";
"lng_contacts_loading" = "로드중..";
"lng_contacts_not_found" = "연락처를 찾을 수 없음";
"lng_dlg_search_chat" = "이 채팅에서 검색";
"lng_dlg_search_for_messages" = "메시지 검색";
"lng_settings_save" = "저장";
"lng_settings_upload" = "프로필 이미지 선택";
@@ -182,6 +186,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_desktop_notify" = "데스크탑 알림";
"lng_settings_show_name" = "발신인 표시";
"lng_settings_show_preview" = "메시지 미리보기";
"lng_settings_use_windows" = "Use Windows notifications";
"lng_settings_sound_notify" = "소리 재생";
"lng_notification_preview" = "새로운 메시지가 있습니다.";
@@ -320,6 +325,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_reset_one_sure" = "해당 세션을 강제 종료 하시겠습니까?";
"lng_settings_reset_button" = "종료";
"lng_settings_reset_done" = "다른 모든 세션이 강제 종료 되었습니다.";
"lng_settings_ask_question" = "Ask a Question";
"lng_settings_ask_sure" = "Please note that Telegram Support is done by volunteers. We try to respond as quickly as possible, but it may take a while.\n\nPlease take a look at the Telegram FAQ: it has important troubleshooting tips and answers to most questions.";
"lng_settings_faq_button" = "Go to FAQ";
"lng_settings_ask_ok" = "Ask";
"lng_settings_faq" = "Telegram FAQ";
"lng_settings_logout" = "로그아웃";
"lng_sure_logout" = "로그아웃을 하시겠습니까?";
@@ -339,6 +349,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_topbar_info" = "정보";
"lng_profile_about_section" = "취소";
"lng_profile_settings_section" = "환경설정";
"lng_profile_actions_section" = "동작";
"lng_profile_bot_settings" = "환경설정";
"lng_profile_bot_help" = "도움말";
"lng_profile_participants_section" = "사용자";
@@ -348,6 +359,13 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_profile_edit_contact" = "수정";
"lng_profile_enable_notifications" = "알림";
"lng_profile_clear_history" = "히스토리 초기화";
"lng_profile_delete_conversation" = "대화 지우기";
"lng_profile_clear_and_exit" = "삭제 후 종료";
"lng_profile_search_messages" = "메시지 검색";
"lng_profile_block_user" = "Block user";
"lng_profile_unblock_user" = "Unblock user";
"lng_profile_block_bot" = "Stop and block bot";
"lng_profile_unblock_bot" = "Unblock bot";
"lng_profile_send_message" = "메세지 전송";
"lng_profile_share_contact" = "연락처 공유";
"lng_profile_invite_to_group" = "그룹에 추가";
@@ -379,13 +397,16 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_create_group_title" = "새로운 그룹";
"lng_failed_add_participant" = "사용자를 초대할 수 없습니다. 나중에 다시 시도해주세요.";
"lng_failed_add_not_mutual" = "죄송합니다. 그룹방에서 대화상대방이 나갔을 경우,\n상대 전화번호가 있는 분만 초대가 가능합니다.\n(서로 전화번호가 등록되어져 있어야만 가능)";
"lng_sure_delete_contact" = "{contact} 님을 주소록에서 \n삭제하시겠습니까?";
"lng_sure_delete_history" = "{contact} 님과 관련된 모든 메시지를 \n삭제하시겠습니까?\n\n삭제 하실 경우 취소가 불가능합니다.";
"lng_sure_delete_group_history" = "그룹<<{group}>> 방의 모든 메시지 기록을 삭제하시겠습니까?\n\n이 작업은 취소가 불가능합니다.";
"lng_sure_delete_and_exit" = "그룹 «{group}» 방에서 모든 메시지를 \n삭제하시고 퇴장하시겠습니까?\n\n삭제 하실 경우 취소가 불가능합니다.";
"lng_message_empty" = "(없음)";
"lng_message_empty" = "메시지 없음";
"lng_media_unsupported" = "지원하지 않는 미디어";
"lng_action_add_user" = "{from} 님께서 {user} 님을 초대하셨습니다.";
"lng_action_kick_user" = "{from} 님께서 {user} 님을 추방하셨습니다.";
@@ -459,12 +480,13 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_send_button" = "보내기";
"lng_message_ph" = "메시지 쓰기";
"lng_record_cancel" = "이 영역에서 마우스 클릭을 해제하시면 취소가 됩니다.";
"lng_record_cancel" = "이 영역에서 마우스 클릭을 해제하시면 취소가 됩니다.";
"lng_empty_history" = "";
"lng_willbe_history" = "대화하실 방을 선택해주세요.";
"lng_message_with_from" = "[c]{from}:[/c] {message}";
"lng_from_you" = "회원님";
"lng_bot_description" = "봇이 할 수 있는 일은 무엇일까요?";
"lng_unblock_button" = "Unblock";
"lng_bot_start" = "시작";
"lng_bot_choose_group" = "그룹 선택";
@@ -477,6 +499,22 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_user_typing" = "{user}님이 입력중입니다.";
"lng_users_typing" = "{user}님과 {second_user}님이 입력중입니다.";
"lng_many_typing" = "{count:_not_used_|#명이|#명이} 입력중입니다";
"lng_send_action_record_video" = "비디오 녹화 중";
"lng_user_action_record_video" = "{user}님이 녹화중입니다.";
"lng_send_action_upload_video" = "비디오 전송 중";
"lng_user_action_upload_video" = "{user}님이 비디오를 전송 중입니다.";
"lng_send_action_record_audio" = "오디오 녹음 중";
"lng_user_action_record_audio" = "{user}님이 오디오를 녹음 중입니다.";
"lng_send_action_upload_audio" = "오디오 전송 중";
"lng_user_action_upload_audio" = "{user}님이 오디오를 전송 중입니다.";
"lng_send_action_upload_photo" = "사진 전송 중";
"lng_user_action_upload_photo" = "{user}님이 사진을 전송 중입니다.";
"lng_send_action_upload_file" = "파일을 전송 중";
"lng_user_action_upload_file" = "{user}님이 사진을 전송 중입니다.";
"lng_send_action_geo_location" = "위치 선택 중";
"lng_user_action_geo_location" = "{user}님이 위치를 선택 중입니다.";
"lng_send_action_choose_contact" = "연락처 선택 중";
"lng_user_action_choose_contact" = "{user}님이 연락처를 선택 중입니다.";
"lng_unread_bar" = "{count:_not_used_|#개의 읽지 않은 메시지|#개의 읽지 않은 메시지}";
"lng_maps_point" = "위치";
@@ -603,7 +641,7 @@ Copyright (c) 2014 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" = "— 앱내 미디어 재생 기능 향상\n— 버그 수정 및 마이나 기능 향상";
"lng_new_version_text" = "— 대화방내 검색 기능\n— 그룹방 대화내용 삭제\n— 메시지가 없는 대화방은 대화목록에서 숨겨짐";
"lng_menu_insert_unicode" = "유니코드 문자를 입력하세요.";

View File

@@ -28,7 +28,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_open_from_tray" = "Telegram openen";
"lng_minimize_to_tray" = "Minimaliseer naar systeemvak";
"lng_quit_from_tray" = "Telegram afsluiten";
"lng_tray_icon_text" = "Telegram is nog steeds actief,\nJe kunt dit wijzigen via instellingen.\n\nAls dit icoon verdwijnt van het systeemvak,\nkun je deze terugslepen vanaf de verborgen iconen.";
"lng_tray_icon_text" = "Telegram is nog steeds actief, \nje kunt dit wijzigen via instellingen.\nAls dit icoon verdwijnt van het systeemvak,\nkun je deze terugslepen vanaf de verborgen iconen.";
"lng_month1" = "januari";
"lng_month2" = "februari";
@@ -69,8 +69,9 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_reconnecting_try_now" = "Probeer nu";
"lng_status_service_notifications" = "servicemeldingen";
"lng_status_support" = "ondersteuning";
"lng_status_bot" = "bot";
"lng_status_bot_reads_all" = "toegang tot berichten";
"lng_status_bot_reads_all" = "toegang tot berichten";
"lng_status_bot_not_reads_all" = "geen toegang tot berichten";
"lng_status_offline" = "lang geleden gezien";
"lng_status_recently" = "recent gezien";
@@ -156,8 +157,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_dlg_new_group_name" = "Groepsnaam";
"lng_dlg_create_group" = "Maak";
"lng_no_contacts" = "Je hebt geen contacten";
"lng_no_chats" = "Hier komen je chats";
"lng_contacts_loading" = "Bezig met laden";
"lng_contacts_not_found" = "Geen contacten gevonden";
"lng_dlg_search_chat" = "Zoek in deze chat";
"lng_dlg_search_for_messages" = "Zoek berichten";
"lng_settings_save" = "Opslaan";
"lng_settings_upload" = "Profielfoto instellen";
@@ -182,6 +186,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_desktop_notify" = "Desktopmeldingen";
"lng_settings_show_name" = "Afzender weergeven";
"lng_settings_show_preview" = "Voorvertoning weergeven";
"lng_settings_use_windows" = "Windows-berichtgeving gebruiken";
"lng_settings_sound_notify" = "Geluiden afspelen";
"lng_notification_preview" = "Je hebt een nieuw bericht";
@@ -289,7 +294,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_cloud_password_bad" = "De hint moet anders zijn dan je wachtwoord.";
"lng_cloud_password_email" = "Herstel-e-mailadres invoeren";
"lng_cloud_password_bad_email" = "Ongeldig e-mailadres, probeer een andere.";
"lng_cloud_password_about" = "Naast de code die je per SMS ontvangt kun je een extra wachtwoord instellen voor als je inlogt op een nieuw apparaat.";
"lng_cloud_password_about" = "Dit wachtwoord is nodig als je inlogt vanaf een nieuw apparaat, naast de SMS die je ontvangt.";
"lng_cloud_password_about_recover" = "Let op: Echt geen herstel-emailadres\nopgeven voor je wachtwoord?\n\nBij verlies van je wachtwoord ben je\nook de toegang tot Telegram kwijt.";
"lng_cloud_password_almost" = "Een bevestigingslink is naar\nhet e-mailadres verstuurd.\n\ntwee-staps-verificatie is actief\nna het klikken van de e-mail-link.";
"lng_cloud_password_was_set" = "Twee-staps-verificatie ingeschakeld.";
@@ -320,6 +325,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_reset_one_sure" = "Deze sessie beëindigen?";
"lng_settings_reset_button" = "Beëindigen";
"lng_settings_reset_done" = "Alle andere sessies zijn beëindigd";
"lng_settings_ask_question" = "Een vraag stellen";
"lng_settings_ask_sure" = "De ondersteuning voor Telegram wordt gedaan door vrijwilligers. We proberen zo snel mogelijk te reageren maar het kan even duren. \n\nBekijk ook de veelgestelde vragen, deze bevat belangrijke tips en antwoorden op de meest gestelde vragen. ";
"lng_settings_faq_button" = "Veelgestelde vragen";
"lng_settings_ask_ok" = "Vraag";
"lng_settings_faq" = "Veelgestelde vragen";
"lng_settings_logout" = "Uitloggen";
"lng_sure_logout" = "Weet je zeker dat je wilt uitloggen?";
@@ -339,6 +349,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_topbar_info" = "Info";
"lng_profile_about_section" = "Over";
"lng_profile_settings_section" = "Instellingen";
"lng_profile_actions_section" = "Acties";
"lng_profile_bot_settings" = "Instellingen";
"lng_profile_bot_help" = "Help";
"lng_profile_participants_section" = "Deelnemers";
@@ -348,6 +359,13 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_profile_edit_contact" = "Wijzig";
"lng_profile_enable_notifications" = "Meldingen";
"lng_profile_clear_history" = "Geschiedenis wissen";
"lng_profile_delete_conversation" = "Gesprek verwijderen";
"lng_profile_clear_and_exit" = "Verwijder en verlaat";
"lng_profile_search_messages" = "Zoek berichten";
"lng_profile_block_user" = "Blokkeer gebruiker";
"lng_profile_unblock_user" = "Deblokkeer gebruiker";
"lng_profile_block_bot" = "Stop en blokkeer bot";
"lng_profile_unblock_bot" = "Deblokkeer bot";
"lng_profile_send_message" = "Bericht sturen";
"lng_profile_share_contact" = "Contact delen";
"lng_profile_invite_to_group" = "Groepslid maken";
@@ -379,13 +397,16 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_create_group_title" = "Nieuwe groep";
"lng_failed_add_participant" = "Gebruiker toevoegen mislukt. Probeer het later nog eens.";
"lng_failed_add_not_mutual" = "Sorry, als een persoon verlaat, \nKan alleen een wederzijds\ncontact ze weer toevoegen\n(opgeslagen telefoonnummers).";
"lng_sure_delete_contact" = "{contact} echt verwijderen uit contacten?";
"lng_sure_delete_history" = "Geschiedenis met {contact} echt wissen? \n\nDeze actie kan niet ongedaan worden gemaakt.";
"lng_sure_delete_group_history" = "Echt de geschiedenis van «{group}» wissen?\n\nHerstellen is niet mogelijk. ";
"lng_sure_delete_and_exit" = "Wil je de groep «{group}» verlaten en de geschiedenis wissen?\n\nDeze actie kan niet ongedaan worden gemaakt.";
"lng_message_empty" = "(leeg)";
"lng_message_empty" = "Leeg bericht";
"lng_media_unsupported" = "Niet-ondersteunde media";
"lng_action_add_user" = "{from} heeft {user} toegevoegd";
"lng_action_kick_user" = "{from} heeft {user} verwijderd";
@@ -465,6 +486,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_message_with_from" = "[c]{from}:[/c] {message}";
"lng_from_you" = "Jij";
"lng_bot_description" = "Wat kan deze bot? ";
"lng_unblock_button" = "Deblokkeer";
"lng_bot_start" = "Begin";
"lng_bot_choose_group" = "Groep kiezen";
@@ -477,6 +499,22 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_user_typing" = "{user} is aan het typen";
"lng_users_typing" = "{user} en {second_user} zijn aan het typen";
"lng_many_typing" = "{count:_not_used_|# is|# zijn} aan het typen";
"lng_send_action_record_video" = "video opnemen";
"lng_user_action_record_video" = "{user} neemt video op";
"lng_send_action_upload_video" = "video versturen";
"lng_user_action_upload_video" = "{user} verstuurt video";
"lng_send_action_record_audio" = "geluid opnemen";
"lng_user_action_record_audio" = "{user} neemt geluid op";
"lng_send_action_upload_audio" = "geluid versturen";
"lng_user_action_upload_audio" = "{user} verstuurt geluid";
"lng_send_action_upload_photo" = "foto versturen";
"lng_user_action_upload_photo" = "{user} verstuurt een foto";
"lng_send_action_upload_file" = "bestand versturen";
"lng_user_action_upload_file" = "{user} verstuurt een bestand";
"lng_send_action_geo_location" = "locatie kiezen";
"lng_user_action_geo_location" = "{user} kiest een locatie";
"lng_send_action_choose_contact" = "contact kiezen";
"lng_user_action_choose_contact" = "{user} kiest een contact";
"lng_unread_bar" = "{count:_not_used_|# ongelezen bericht|# ongelezen berichten}";
"lng_maps_point" = "Locatie";
@@ -603,7 +641,7 @@ Copyright (c) 2014 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" = "— Media afspelen binnen de app verbeterd\n— Probleemoplossing en kleine verbeteringen";
"lng_new_version_text" = "— Zoek berichten binnen gesprekken\n— Berichtengeschiedenis van groepen wissen\n— Contacten zonder berichten zijn verborgen in de gesprekslijst";
"lng_menu_insert_unicode" = "Unicode-besturingsteken invoegen";

View File

@@ -28,7 +28,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_open_from_tray" = "Abrir Telegram";
"lng_minimize_to_tray" = "Minimizar";
"lng_quit_from_tray" = "Sair do Telegram";
"lng_tray_icon_text" = "Telegram ainda está sendo executado,\nvocê pode mudar isso nas configurações.\n\nSe este ícone desaparecer de sua bandeja,\nvocê pode arrastar de volta dos ícones ocultos.";
"lng_tray_icon_text" = "Telegram ainda está sendo executado,\nvocê pode mudar isso nas configurações.\nSe este ícone desaparecer de sua bandeja,\nvocê pode arrastar de volta dos ícones ";
"lng_month1" = "Janeiro";
"lng_month2" = "Fevereiro";
@@ -69,6 +69,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_reconnecting_try_now" = "Tentar agora";
"lng_status_service_notifications" = "notificações de serviço";
"lng_status_support" = "suporte";
"lng_status_bot" = "bot";
"lng_status_bot_reads_all" = "tem acesso as mensagens";
"lng_status_bot_not_reads_all" = "não tem acesso as mensagens";
@@ -156,8 +157,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_dlg_new_group_name" = "Nome do grupo";
"lng_dlg_create_group" = "Criar";
"lng_no_contacts" = "Você não possui contatos";
"lng_no_chats" = "Seus chats estarão aqui";
"lng_contacts_loading" = "Carregando..";
"lng_contacts_not_found" = "Nenhum contato encontrado";
"lng_dlg_search_chat" = "Buscar nesse chat";
"lng_dlg_search_for_messages" = "Buscar por mensagens";
"lng_settings_save" = "Salvar";
"lng_settings_upload" = "Definir Foto de Perfil";
@@ -182,6 +186,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_desktop_notify" = "Notificações na área de trabalho";
"lng_settings_show_name" = "Mostrar nome de quem enviou";
"lng_settings_show_preview" = "Mostrar pré-visualização da mensagem";
"lng_settings_use_windows" = "Usar notificações do Windows";
"lng_settings_sound_notify" = "Tocar som";
"lng_notification_preview" = "Você tem uma nova mensagem";
@@ -320,6 +325,11 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_settings_reset_one_sure" = "Você deseja terminar essa sessão?";
"lng_settings_reset_button" = "Encerrar";
"lng_settings_reset_done" = "Outras sessões encerradas";
"lng_settings_ask_question" = "Fazer uma Pergunta";
"lng_settings_ask_sure" = "Entenda que o suporte do Telegram é feito por voluntários. Tentaremos responder o mais rápido possível, mas poderemos demorar um pouco.\n\nPor favor verifique a página de Perguntas Frequentes do Telegram: há dicas e respostas para a maioria das perguntas.";
"lng_settings_faq_button" = "Perguntas Frequentes";
"lng_settings_ask_ok" = "Perguntar";
"lng_settings_faq" = "Perguntas Frequentes";
"lng_settings_logout" = "Sair";
"lng_sure_logout" = "Tem certeza que deseja sair?";
@@ -339,6 +349,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_topbar_info" = "Info";
"lng_profile_about_section" = "Sobre";
"lng_profile_settings_section" = "Configurações";
"lng_profile_actions_section" = "Ações";
"lng_profile_bot_settings" = "Configurações";
"lng_profile_bot_help" = "Ajuda";
"lng_profile_participants_section" = "Membros";
@@ -348,6 +359,13 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_profile_edit_contact" = "Editar";
"lng_profile_enable_notifications" = "Notificações";
"lng_profile_clear_history" = "Limpar histórico";
"lng_profile_delete_conversation" = "Apagar conversa";
"lng_profile_clear_and_exit" = "Apagar e sair";
"lng_profile_search_messages" = "Buscar mensagens";
"lng_profile_block_user" = "Bloquear usuário";
"lng_profile_unblock_user" = "Desbloquear usuário";
"lng_profile_block_bot" = "Parar e bloquear o bot";
"lng_profile_unblock_bot" = "Desbloquear bot";
"lng_profile_send_message" = "Enviar Mensagem";
"lng_profile_share_contact" = "Compartilhar";
"lng_profile_invite_to_group" = "Adicionar ao Grupo";
@@ -379,13 +397,16 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_create_group_title" = "Novo Grupo";
"lng_failed_add_participant" = "Não foi possível adicionar o usuário. Tente novamente mais tarde.";
"lng_failed_add_not_mutual" = "Desculpe, se uma pessoa deixou o\ngrupo, apenas um contato mútuo pode\ncolocá-la de volta (eles precisam do seu \ncontato no telefone e você o deles)";
"lng_sure_delete_contact" = "Você tem certeza que deseja remover {contact} da sua lista de contatos?";
"lng_sure_delete_history" = "Você tem certeza que deseja apagar todo o seu histórico de mensagens com {contact}?\n\nEssa ação não pode ser desfeita.";
"lng_sure_delete_group_history" = "Você tem certeza que deseja apagar todo o histórico de «{group}»?\n\nEssa ação não pode ser desfeita.";
"lng_sure_delete_and_exit" = "Você tem certeza que deseja apagar todo o seu histórico de mensagens e deixar «{group}»?\n\nEssa ação não pode ser desfeita.";
"lng_message_empty" = "(vazio)";
"lng_message_empty" = "Mensagem Vazia";
"lng_media_unsupported" = "Mídia Não-Suportada";
"lng_action_add_user" = "{from} adicionou {user}";
"lng_action_kick_user" = "{from} removeu {user}";
@@ -465,6 +486,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_message_with_from" = "[c]{from}:[/c] {message}";
"lng_from_you" = "Você";
"lng_bot_description" = "O que esse bot pode fazer?";
"lng_unblock_button" = "Desbloquear";
"lng_bot_start" = "Iniciar";
"lng_bot_choose_group" = "Escolher Grupo";
@@ -477,6 +499,22 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
"lng_user_typing" = "{user} está escrevendo";
"lng_users_typing" = "{user} e {second_user} estão escrevendo";
"lng_many_typing" = "{count:_not_used_|# está|# estão} escrevendo";
"lng_send_action_record_video" = "gravando vídeo";
"lng_user_action_record_video" = "{user} está gravando vídeo";
"lng_send_action_upload_video" = "enviando vídeo";
"lng_user_action_upload_video" = "{user} está enviando vídeo";
"lng_send_action_record_audio" = "gravando áudio";
"lng_user_action_record_audio" = "{user} está gravando áudio";
"lng_send_action_upload_audio" = "enviando áudio";
"lng_user_action_upload_audio" = "{user} está gravando áudio";
"lng_send_action_upload_photo" = "enviando foto";
"lng_user_action_upload_photo" = "{user} está enviando foto";
"lng_send_action_upload_file" = "enviando arquivo";
"lng_user_action_upload_file" = "{user} está enviando arquivo";
"lng_send_action_geo_location" = "escolhendo local";
"lng_user_action_geo_location" = "{user} está escolhendo local";
"lng_send_action_choose_contact" = "escolhendo contato";
"lng_user_action_choose_contact" = "{user} está escolhendo contato";
"lng_unread_bar" = "{count:_not_used_|# mensagem não lida|# mensagens não lidas}";
"lng_maps_point" = "Localização";
@@ -603,7 +641,7 @@ Copyright (c) 2014 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 menores melhorias";
"lng_new_version_text" = "— Reprodução de mídia no app melhorada\n— Resolução de bugs e menores melhorias";
"lng_new_version_text" = "— Buscar mensagens em uma conversa\n— Limpar histórico de mensagens em grupos\n— Contatos sem mensagens estão ocultos da lista de conversas";
"lng_menu_insert_unicode" = "Inserir caractere de controle Unicode";

View File

@@ -78,12 +78,15 @@ void LocalImageLoaderPrivate::prepareImages() {
type = ToPrepareDocument;
}
}
if (type == ToPrepareDocument) {
mime = mimeTypeForFile(info).name();
}
if (type != ToPrepareAuto && info.size() < MaxUploadPhotoSize) {
bool opaque = (mime != stickerMime);
img = App::readImage(file, 0, opaque, &animated);
if (animated) {
type = ToPrepareDocument;
}
}
if (type == ToPrepareDocument) {
mime = mimeTypeForFile(info).name();
}
filename = info.fileName();
filesize = info.size();
@@ -221,7 +224,7 @@ void LocalImageLoaderPrivate::prepareImages() {
}
if (!filesize) filesize = jpeg.size();
photo = MTP_photo(MTP_long(id), MTP_long(0), MTP_int(user), MTP_int(unixtime()), MTP_geoPointEmpty(), MTP_vector<MTPPhotoSize>(photoSizes));
photo = MTP_photo(MTP_long(id), MTP_long(0), MTP_int(unixtime()), MTP_vector<MTPPhotoSize>(photoSizes));
thumbId = id;
} else if ((type == ToPrepareVideo || type == ToPrepareDocument) && !img.isNull() && !isSong) {
@@ -254,7 +257,7 @@ void LocalImageLoaderPrivate::prepareImages() {
if (type == ToPrepareDocument) {
document = MTP_document(MTP_long(id), MTP_long(0), MTP_int(unixtime()), MTP_string(mime), MTP_int(filesize), thumb, MTP_int(MTP::maindc()), MTP_vector<MTPDocumentAttribute>(attributes));
} else if (type == ToPrepareAudio) {
audio = MTP_audio(MTP_long(id), MTP_long(0), MTP_int(user), MTP_int(unixtime()), MTP_int(duration), MTP_string(mime), MTP_int(filesize), MTP_int(MTP::maindc()));
audio = MTP_audio(MTP_long(id), MTP_long(0), MTP_int(unixtime()), MTP_int(duration), MTP_string(mime), MTP_int(filesize), MTP_int(MTP::maindc()));
}
{

View File

@@ -18,6 +18,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
#include "stdafx.h"
#include "localstorage.h"
#include "mainwidget.h"
#include "window.h"
#include "lang.h"
namespace {
@@ -505,6 +507,7 @@ namespace {
lskUserSettings = 0x09, // no data
lskRecentHashtags = 0x0a, // no data
lskStickers = 0x0b, // no data
lskSavedPeers = 0x0c, // no data
};
typedef QMap<PeerId, FileKey> DraftsMap;
@@ -530,13 +533,15 @@ namespace {
FileKey _recentHashtagsKey = 0;
bool _recentHashtagsWereRead = false;
FileKey _savedPeersKey = 0;
typedef QPair<FileKey, qint32> FileDesc; // file, size
typedef QMap<StorageKey, FileDesc> StorageMap;
StorageMap _imagesMap, _stickerImagesMap, _audiosMap;
int32 _storageImagesSize = 0, _storageStickersSize = 0, _storageAudiosSize = 0;
bool _mapChanged = false;
int32 _oldMapVersion = 0;
int32 _oldMapVersion = 0, _oldSettingsVersion = 0;
enum WriteMapWhen {
WriteMapNow,
@@ -733,6 +738,15 @@ namespace {
cSetDesktopNotify(v == 1);
} break;
case dbiWindowsNotifications: {
qint32 v;
stream >> v;
if (!_checkStreamStatus(stream)) return false;
cSetWindowsNotifications(v == 1);
cSetCustomNotifies((App::wnd() ? App::wnd()->psHasNativeNotifications() : true) && !cWindowsNotifications());
} break;
case dbiWorkMode: {
qint32 v;
stream >> v;
@@ -1265,7 +1279,7 @@ namespace {
_writeMap(WriteMapFast);
}
uint32 size = 12 * (sizeof(quint32) + sizeof(qint32));
uint32 size = 13 * (sizeof(quint32) + sizeof(qint32));
size += sizeof(quint32) + _stringSize(cAskDownloadPath() ? QString() : cDownloadPath());
size += sizeof(quint32) + sizeof(qint32) + (cRecentEmojisPreload().isEmpty() ? cGetRecentEmojis().size() : cRecentEmojisPreload().size()) * (sizeof(uint64) + sizeof(ushort));
size += sizeof(quint32) + sizeof(qint32) + cEmojiVariants().size() * (sizeof(uint32) + sizeof(uint64));
@@ -1281,6 +1295,7 @@ namespace {
data.stream << quint32(dbiSoundNotify) << qint32(cSoundNotify());
data.stream << quint32(dbiDesktopNotify) << qint32(cDesktopNotify());
data.stream << quint32(dbiNotifyView) << qint32(cNotifyView());
data.stream << quint32(dbiWindowsNotifications) << qint32(cWindowsNotifications());
data.stream << quint32(dbiAskDownloadPath) << qint32(cAskDownloadPath());
data.stream << quint32(dbiDownloadPath) << (cAskDownloadPath() ? QString() : cDownloadPath());
data.stream << quint32(dbiCompressPastedImage) << qint32(cCompressPastedImage());
@@ -1432,7 +1447,7 @@ namespace {
DraftsNotReadMap draftsNotReadMap;
StorageMap imagesMap, stickerImagesMap, audiosMap;
qint64 storageImagesSize = 0, storageStickersSize = 0, storageAudiosSize = 0;
quint64 locationsKey = 0, recentStickersKeyOld = 0, stickersKey = 0, backgroundKey = 0, userSettingsKey = 0, recentHashtagsKey = 0;
quint64 locationsKey = 0, recentStickersKeyOld = 0, stickersKey = 0, backgroundKey = 0, userSettingsKey = 0, recentHashtagsKey = 0, savedPeersKey = 0;
while (!map.stream.atEnd()) {
quint32 keyType;
map.stream >> keyType;
@@ -1512,6 +1527,9 @@ namespace {
case lskStickers: {
map.stream >> stickersKey;
} break;
case lskSavedPeers: {
map.stream >> savedPeersKey;
} break;
default:
LOG(("App Error: unknown key type in encrypted map: %1").arg(keyType));
return Local::ReadMapFailed;
@@ -1535,6 +1553,7 @@ namespace {
_locationsKey = locationsKey;
_recentStickersKeyOld = recentStickersKeyOld;
_stickersKey = stickersKey;
_savedPeersKey = savedPeersKey;
_backgroundKey = backgroundKey;
_userSettingsKey = userSettingsKey;
_recentHashtagsKey = recentHashtagsKey;
@@ -1554,6 +1573,9 @@ namespace {
_readMtpData();
LOG(("Map read time: %1").arg(getms() - ms));
if (_oldSettingsVersion < AppVersion) {
Local::writeSettings();
}
return Local::ReadMapDone;
}
@@ -1599,6 +1621,7 @@ namespace {
if (_locationsKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_recentStickersKeyOld) mapSize += sizeof(quint32) + sizeof(quint64);
if (_stickersKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_savedPeersKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_backgroundKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_userSettingsKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_recentHashtagsKey) mapSize += sizeof(quint32) + sizeof(quint64);
@@ -1642,6 +1665,9 @@ namespace {
if (_stickersKey) {
mapData.stream << quint32(lskStickers) << quint64(_stickersKey);
}
if (_savedPeersKey) {
mapData.stream << quint32(lskSavedPeers) << quint64(_savedPeersKey);
}
if (_backgroundKey) {
mapData.stream << quint32(lskBackground) << quint64(_backgroundKey);
}
@@ -1797,6 +1823,7 @@ namespace Local {
cSetDcOptions(dcOpts);
}
_oldSettingsVersion = settingsData.version;
_settingsSalt = salt;
}
@@ -1900,7 +1927,7 @@ namespace Local {
_draftsNotReadMap.clear();
_stickerImagesMap.clear();
_audiosMap.clear();
_locationsKey = _recentStickersKeyOld = _stickersKey = _backgroundKey = _userSettingsKey = _recentHashtagsKey = 0;
_locationsKey = _recentStickersKeyOld = _stickersKey = _backgroundKey = _userSettingsKey = _recentHashtagsKey = _savedPeersKey = 0;
_mapChanged = true;
_writeMap(WriteMapNow);
@@ -1939,6 +1966,10 @@ namespace Local {
return _oldMapVersion;
}
int32 oldSettingsVersion() {
return _oldSettingsVersion;
}
void writeDraft(const PeerId &peer, const MessageDraft &draft) {
if (!_working()) return;
@@ -2293,6 +2324,23 @@ namespace Local {
return _storageAudiosSize;
}
void _writeStorageImageLocation(QDataStream &stream, const StorageImageLocation &loc) {
stream << qint32(loc.width) << qint32(loc.height);
stream << qint32(loc.dc) << quint64(loc.volume) << qint32(loc.local) << quint64(loc.secret);
}
uint32 _storageImageLocationSize() {
// width + height + dc + volume + local + secret
return sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(quint64) + sizeof(qint32) + sizeof(quint64);
}
StorageImageLocation _readStorageImageLocation(FileReadDescriptor &from) {
qint32 thumbWidth, thumbHeight, thumbDc, thumbLocal;
quint64 thumbVolume, thumbSecret;
from.stream >> thumbWidth >> thumbHeight >> thumbDc >> thumbVolume >> thumbLocal >> thumbSecret;
return StorageImageLocation(thumbWidth, thumbHeight, thumbDc, thumbVolume, thumbLocal, thumbSecret);
}
void _writeStickerSet(QDataStream &stream, uint64 setId) {
StickerSets::const_iterator it = cStickerSets().constFind(setId);
if (it == cStickerSets().cend()) return;
@@ -2321,8 +2369,7 @@ namespace Local {
stream << qint32(StickerSetTypeEmpty);
} break;
}
const StorageImageLocation &loc(doc->sticker()->loc);
stream << qint32(loc.width) << qint32(loc.height) << qint32(loc.dc) << quint64(loc.volume) << qint32(loc.local) << quint64(loc.secret);
_writeStorageImageLocation(stream, doc->sticker()->loc);
}
}
@@ -2358,8 +2405,8 @@ namespace Local {
// id + access + date + namelen + name + mimelen + mime + dc + size + width + height + type + alt + type-of-set
size += sizeof(quint64) + sizeof(quint64) + sizeof(qint32) + _stringSize(doc->name) + _stringSize(doc->mime) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + _stringSize(doc->sticker()->alt) + sizeof(qint32);
// thumb-width + thumb-height + thumb-dc + thumb-volume + thumb-local + thumb-secret
size += sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(quint64) + sizeof(qint32) + sizeof(quint64);
// loc
size += _storageImageLocationSize();
}
++setsCount;
}
@@ -2519,9 +2566,7 @@ namespace Local {
qint32 date, dc, size, width, height, type, typeOfSet;
stickers.stream >> id >> access >> date >> name >> mime >> dc >> size >> width >> height >> type >> alt >> typeOfSet;
qint32 thumbWidth, thumbHeight, thumbDc, thumbLocal;
quint64 thumbVolume, thumbSecret;
stickers.stream >> thumbWidth >> thumbHeight >> thumbDc >> thumbVolume >> thumbLocal >> thumbSecret;
StorageImageLocation thumb(_readStorageImageLocation(stickers));
if (read.contains(id)) continue;
read.insert(id, true);
@@ -2552,7 +2597,6 @@ namespace Local {
attributes.push_back(MTP_documentAttributeImageSize(MTP_int(width), MTP_int(height)));
}
StorageImageLocation thumb(thumbWidth, thumbHeight, thumbDc, thumbVolume, thumbLocal, thumbSecret);
DocumentData *doc = App::documentSet(id, 0, access, date, attributes, mime, thumb.dc ? ImagePtr(thumb) : ImagePtr(), dc, size, thumb);
if (!doc->sticker()) continue;
@@ -2705,6 +2749,190 @@ namespace Local {
cSetRecentSearchHashtags(search);
}
uint32 _peerSize(PeerData *peer) {
uint32 result = sizeof(quint64) + sizeof(quint64) + _storageImageLocationSize();
if (peer->chat) {
ChatData *chat = peer->asChat();
// name + count + date + version + admin + forbidden + left + invitationUrl
result += _stringSize(chat->name) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32) + _stringSize(chat->invitationUrl);
} else {
UserData *user = peer->asUser();
// first + last + phone + username + access + onlineTill + contact + botInfoVersion
result += _stringSize(user->firstName) + _stringSize(user->lastName) + _stringSize(user->phone) + _stringSize(user->username) + sizeof(quint64) + sizeof(qint32) + sizeof(qint32) + sizeof(qint32);
}
return result;
}
void _writePeer(QDataStream &stream, PeerData *peer) {
stream << quint64(peer->id) << quint64(peer->photoId);
_writeStorageImageLocation(stream, peer->photoLoc);
if (peer->chat) {
ChatData *chat = peer->asChat();
stream << chat->name << qint32(chat->count) << qint32(chat->date) << qint32(chat->version) << qint32(chat->admin);
stream << qint32(chat->forbidden ? 1 : 0) << qint32(chat->left ? 1 : 0) << chat->invitationUrl;
} else {
UserData *user = peer->asUser();
stream << user->firstName << user->lastName << user->phone << user->username << quint64(user->access) << qint32(user->onlineTill) << qint32(user->contact) << qint32(user->botInfo ? user->botInfo->version : -1);
}
}
PeerData *_readPeer(FileReadDescriptor &from) {
PeerData *result = 0;
quint64 peerId = 0, photoId = 0;
from.stream >> peerId >> photoId;
StorageImageLocation photoLoc(_readStorageImageLocation(from));
result = App::peer(peerId);
result->loaded = true;
if (result->chat) {
ChatData *chat = result->asChat();
QString name, invitationUrl;
qint32 count, date, version, admin, forbidden, left;
from.stream >> name >> count >> date >> version >> admin >> forbidden >> left >> invitationUrl;
chat->updateName(name, QString(), QString());
chat->count = count;
chat->date = date;
chat->version = version;
chat->admin = admin;
chat->forbidden = (forbidden == 1);
chat->left = (left == 1);
chat->invitationUrl = invitationUrl;
chat->input = MTP_inputPeerChat(MTP_int(App::chatFromPeer(chat->id)));
chat->photo = photoLoc.isNull() ? ImagePtr(chatDefPhoto(chat->colorIndex)) : ImagePtr(photoLoc);
} else {
UserData *user = result->asUser();
QString first, last, phone, username;
quint64 access;
qint32 onlineTill, contact, botInfoVersion;
from.stream >> first >> last >> phone >> username >> access >> onlineTill >> contact >> botInfoVersion;
bool showPhone = !isServiceUser(user->id) && (App::userFromPeer(user->id) != MTP::authedId()) && (contact <= 0);
QString pname = (showPhone && !phone.isEmpty()) ? App::formatPhone(phone) : QString();
user->setName(first, last, pname, username);
user->access = access;
user->onlineTill = onlineTill;
user->contact = contact;
user->setBotInfoVersion(botInfoVersion);
if (App::userFromPeer(user->id) == MTP::authedId()) {
user->input = MTP_inputPeerSelf();
user->inputUser = MTP_inputUserSelf();
} else {
user->input = MTP_inputPeerUser(MTP_int(App::userFromPeer(user->id)), MTP_long((user->access == UserNoAccess) ? 0 : user->access));
user->inputUser = MTP_inputUser(MTP_int(App::userFromPeer(user->id)), MTP_long((user->access == UserNoAccess) ? 0 : user->access));
}
user->photo = photoLoc.isNull() ? ImagePtr(userDefPhoto(user->colorIndex)) : ImagePtr(photoLoc);
}
App::markPeerUpdated(result);
emit App::main()->peerPhotoChanged(result);
return result;
}
void writeSavedPeers() {
if (!_working()) return;
const SavedPeers &saved(cSavedPeers());
if (saved.isEmpty()) {
if (_savedPeersKey) {
clearKey(_savedPeersKey);
_savedPeersKey = 0;
_mapChanged = true;
}
_writeMap();
} else {
if (!_savedPeersKey) {
_savedPeersKey = genKey();
_mapChanged = true;
_writeMap(WriteMapFast);
}
quint32 size = sizeof(quint32);
for (SavedPeers::const_iterator i = saved.cbegin(); i != saved.cend(); ++i) {
size += _peerSize(i.key()) + _dateTimeSize();
}
EncryptedDescriptor data(size);
data.stream << quint32(saved.size());
for (SavedPeers::const_iterator i = saved.cbegin(); i != saved.cend(); ++i) {
_writePeer(data.stream, i.key());
data.stream << i.value();
}
FileWriteDescriptor file(_savedPeersKey);
file.writeEncrypted(data);
}
}
void readSavedPeers() {
if (!_savedPeersKey) return;
FileReadDescriptor saved;
if (!readEncryptedFile(saved, _savedPeersKey)) {
clearKey(_savedPeersKey);
_savedPeersKey = 0;
_writeMap();
return;
}
quint32 count = 0;
saved.stream >> count;
cRefSavedPeers().clear();
cRefSavedPeersByTime().clear();
QList<PeerData*> peers;
peers.reserve(count);
for (uint32 i = 0; i < count; ++i) {
PeerData *peer = _readPeer(saved);
if (!peer) break;
QDateTime t;
saved.stream >> t;
cRefSavedPeers().insert(peer, t);
cRefSavedPeersByTime().insert(t, peer);
peers.push_back(peer);
}
App::emitPeerUpdated();
App::api()->requestPeers(peers);
}
void addSavedPeer(PeerData *peer, const QDateTime &position) {
SavedPeers &savedPeers(cRefSavedPeers());
SavedPeers::iterator i = savedPeers.find(peer);
if (i == savedPeers.cend()) {
savedPeers.insert(peer, position);
} else if (i.value() != position) {
cRefSavedPeersByTime().remove(i.value(), peer);
i.value() = position;
cRefSavedPeersByTime().insert(i.value(), peer);
}
writeSavedPeers();
}
void removeSavedPeer(PeerData *peer) {
SavedPeers &savedPeers(cRefSavedPeers());
if (savedPeers.isEmpty()) return;
SavedPeers::iterator i = savedPeers.find(peer);
if (i != savedPeers.cend()) {
cRefSavedPeersByTime().remove(i.value(), peer);
savedPeers.erase(i);
writeSavedPeers();
}
}
struct ClearManagerData {
QThread *thread;
StorageMap images, stickers, audios;
@@ -2764,6 +2992,10 @@ namespace Local {
_recentHashtagsKey = 0;
_mapChanged = true;
}
if (_savedPeersKey) {
_savedPeersKey = 0;
_mapChanged = true;
}
_writeMap();
} else {
if (task & ClearManagerStorage) {

View File

@@ -100,6 +100,8 @@ namespace Local {
ReadMapState readMap(const QByteArray &pass);
int32 oldMapVersion();
int32 oldSettingsVersion();
struct MessageDraft {
MessageDraft(MsgId replyTo = 0, QString text = QString(), bool previewCancelled = false) : replyTo(replyTo), text(text), previewCancelled(previewCancelled) {
}
@@ -141,4 +143,8 @@ namespace Local {
void writeRecentHashtags();
void readRecentHashtags();
void addSavedPeer(PeerData *peer, const QDateTime &position);
void removeSavedPeer(PeerData *peer);
void readSavedPeers();
};

View File

@@ -39,6 +39,9 @@ int main(int argc, char *argv[]) {
logsInit();
Local::readSettings();
if (Local::oldSettingsVersion() < AppVersion) {
psNewVersion();
}
if (cFromAutoStart() && !cAutoStart()) {
psAutoStart(false, true);
Local::stop();

View File

@@ -122,7 +122,7 @@ void TopBarWidget::onDeleteAndExitSure() {
if (c) {
App::main()->showDialogs();
App::wnd()->hideLayer();
MTP::send(MTPmessages_DeleteChatUser(MTP_int(p->id & 0xFFFFFFFF), App::self()->inputUser), App::main()->rpcDone(&MainWidget::deleteHistory, p), App::main()->rpcFail(&MainWidget::leaveChatFailed, p));
MTP::send(MTPmessages_DeleteChatUser(MTP_int(p->id & 0xFFFFFFFF), App::self()->inputUser), App::main()->rpcDone(&MainWidget::deleteHistoryAfterLeave, p), App::main()->rpcFail(&MainWidget::leaveChatFailed, p));
}
}
@@ -738,20 +738,20 @@ bool MainWidget::leaveChatFailed(PeerData *peer, const RPCError &error) {
showDialogs();
}
dialogs.removePeer(peer);
App::histories().remove(peer->id);
App::history(peer->id)->clear();
MTP::send(MTPmessages_DeleteHistory(peer->input, MTP_int(0)), rpcDone(&MainWidget::deleteHistoryPart, peer));
return true;
}
return false;
}
void MainWidget::deleteHistory(PeerData *peer, const MTPUpdates &updates) {
void MainWidget::deleteHistoryAfterLeave(PeerData *peer, const MTPUpdates &updates) {
sentUpdatesReceived(updates);
if ((profile && profile->peer() == peer) || (overview && overview->peer() == peer) || _stack.contains(peer) || history.peer() == peer) {
showDialogs();
}
dialogs.removePeer(peer);
App::histories().remove(peer->id);
App::history(peer->id)->clear();
MTP::send(MTPmessages_DeleteHistory(peer->input, MTP_int(0)), rpcDone(&MainWidget::deleteHistoryPart, peer));
}
@@ -776,26 +776,23 @@ void MainWidget::deletedContact(UserData *user, const MTPcontacts_Link &result)
App::emitPeerUpdated();
}
void MainWidget::deleteHistoryAndContact(UserData *user, const MTPcontacts_Link &result) {
const MTPDcontacts_link &d(result.c_contacts_link());
App::feedUsers(MTP_vector<MTPUser>(1, d.vuser), false);
App::feedUserLink(MTP_int(user->id & 0xFFFFFFFF), d.vmy_link, d.vforeign_link, false);
App::emitPeerUpdated();
if ((profile && profile->peer() == user) || (overview && overview->peer() == user) || _stack.contains(user) || history.peer() == user) {
showDialogs();
}
dialogs.removePeer(user);
MTP::send(MTPmessages_DeleteHistory(user->input, MTP_int(0)), rpcDone(&MainWidget::deleteHistoryPart, (PeerData*)user));
void MainWidget::deleteConversation(PeerData *peer) {
dialogs.removePeer(peer);
History *h = App::history(peer->id);
h->clear();
h->newLoaded = h->oldLoaded = true;
showDialogs();
MTP::send(MTPmessages_DeleteHistory(peer->input, MTP_int(0)), rpcDone(&MainWidget::deleteHistoryPart, peer));
}
void MainWidget::clearHistory(PeerData *peer) {
if (!peer->chat && peer->asUser()->contact <= 0) {
dialogs.removePeer(peer->asUser());
History *h = App::history(peer->id);
if (h->lastMsg) {
Local::addSavedPeer(h->peer, h->lastMsg->date);
}
dialogsToUp();
dialogs.update();
App::history(peer->id)->clear();
h->clear();
h->newLoaded = h->oldLoaded = true;
showPeerHistory(peer->id, ShowAtUnreadMsgId);
MTP::send(MTPmessages_DeleteHistory(peer->input, MTP_int(0)), rpcDone(&MainWidget::deleteHistoryPart, peer));
}
@@ -816,6 +813,8 @@ bool MainWidget::addParticipantFail(UserData *user, const RPCError &error) {
QString text = lang(lng_failed_add_participant);
if (error.type() == "USER_LEFT_CHAT") { // trying to return banned user to his group
} else if (error.type() == "USER_NOT_MUTUAL_CONTACT") { // trying to return user who does not have me in contacts
text = lang(lng_failed_add_not_mutual);
} else if (error.type() == "USER_ALREADY_PARTICIPANT" && user->botInfo) {
text = lang(lng_bot_already_in_group);
}
@@ -859,7 +858,12 @@ void MainWidget::checkedHistory(PeerData *peer, const MTPmessages_Messages &resu
if ((profile && profile->peer() == peer) || (overview && overview->peer() == peer) || _stack.contains(peer) || history.peer() == peer) {
showDialogs();
}
dialogs.removePeer(peer);
if (peer->chat && peer->asChat()->left) {
dialogs.removePeer(peer);
} else {
History *h = App::historyLoaded(peer->id);
if (h) Local::addSavedPeer(peer, h->lastMsgDate);
}
} else {
History *h = App::historyLoaded(peer->id);
if (!h->lastMsg) {
@@ -1002,8 +1006,8 @@ void MainWidget::sendPreparedText(History *hist, const QString &text, MsgId repl
WebPageData *page = App::webPage(webPageId);
media = MTP_messageMediaWebPage(MTP_webPagePending(MTP_long(page->id), MTP_int(page->pendingTill)));
}
hist->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(hist->peer->id), MTPint(), MTPint(), MTP_int(replyTo), MTP_int(unixtime()), msgText, media, MTPnullMarkup));
hist->sendRequestId = MTP::send(MTPmessages_SendMessage(MTP_int(sendFlags), hist->peer->input, MTP_int(replyTo), msgText, MTP_long(randomId), MTPnullMarkup), App::main()->rpcDone(&MainWidget::sentDataReceived, randomId), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId);
hist->addToBack(MTP_message(MTP_int(flags), MTP_int(newId), MTP_int(MTP::authedId()), App::peerToMTP(hist->peer->id), MTPint(), MTPint(), MTP_int(replyTo), MTP_int(unixtime()), msgText, media, MTPnullMarkup, MTPnullEntities));
hist->sendRequestId = MTP::send(MTPmessages_SendMessage(MTP_int(sendFlags), hist->peer->input, MTP_int(replyTo), msgText, MTP_long(randomId), MTPnullMarkup, MTPnullEntities), App::main()->rpcDone(&MainWidget::sentDataReceived, randomId), RPCFailHandlerPtr(), 0, 0, hist->sendRequestId);
}
finishForwarding(hist);
@@ -1730,7 +1734,7 @@ void MainWidget::serviceNotification(const QString &msg, const MTPMessageMedia &
QString sendingText, leftText = msg;
HistoryItem *item = 0;
while (textSplit(sendingText, leftText, MaxMessageSize)) {
item = App::histories().addToBack(MTP_message(MTP_int(flags), MTP_int(clientMsgId()), MTP_int(ServiceUserId), MTP_peerUser(MTP_int(MTP::authedId())), MTPint(), MTPint(), MTPint(), MTP_int(unixtime()), MTP_string(sendingText), media, MTPnullMarkup), unread ? 1 : 2);
item = App::histories().addToBack(MTP_message(MTP_int(flags), MTP_int(clientMsgId()), MTP_int(ServiceUserId), MTP_peerUser(MTP_int(MTP::authedId())), MTPint(), MTPint(), MTPint(), MTP_int(unixtime()), MTP_string(sendingText), media, MTPnullMarkup, MTPnullEntities), unread ? 1 : 2);
}
if (item) {
history.peerMessagesUpdated(item->history()->peer->id);
@@ -2530,6 +2534,16 @@ void MainWidget::onPeerShown(PeerData *peer) {
if (animating()) _topBar.hide();
}
void MainWidget::searchInPeer(PeerData *peer) {
dialogs.searchInPeer(peer);
if (cWideMode()) {
dialogs.activate();
} else {
dialogsToUp();
showDialogs();
}
}
void MainWidget::onUpdateNotifySettings() {
if (this != App::main()) return;
while (!updateNotifySettingPeers.isEmpty()) {
@@ -2750,6 +2764,8 @@ void MainWidget::start(const MTPUser &user) {
Local::writeMtpData();
}
Local::readSavedPeers();
cSetOtherOnline(0);
App::feedUsers(MTP_vector<MTPUser>(1, user));
App::app()->startUpdateCheck();
@@ -3024,8 +3040,7 @@ void MainWidget::gotNotifySetting(MTPInputNotifyPeer peer, const MTPPeerNotifySe
switch (peer.c_inputNotifyPeer().vpeer.type()) {
case mtpc_inputPeerEmpty: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(MTP_int(0))), settings); break;
case mtpc_inputPeerSelf: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(MTP_int(MTP::authedId()))), settings); break;
case mtpc_inputPeerContact: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(peer.c_inputNotifyPeer().vpeer.c_inputPeerContact().vuser_id)), settings); break;
case mtpc_inputPeerForeign: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(peer.c_inputNotifyPeer().vpeer.c_inputPeerForeign().vuser_id)), settings); break;
case mtpc_inputPeerUser: applyNotifySetting(MTP_notifyPeer(MTP_peerUser(peer.c_inputNotifyPeer().vpeer.c_inputPeerUser().vuser_id)), settings); break;
case mtpc_inputPeerChat: applyNotifySetting(MTP_notifyPeer(MTP_peerChat(peer.c_inputNotifyPeer().vpeer.c_inputPeerChat().vchat_id)), settings); break;
}
break;
@@ -3334,7 +3349,7 @@ void MainWidget::handleUpdates(const MTPUpdates &updates) {
return;
}
bool out = (d.vflags.v & MTPDmessage_flag_out);
HistoryItem *item = App::histories().addToBack(MTP_message(d.vflags, d.vid, out ? MTP_int(MTP::authedId()) : d.vuser_id, MTP_peerUser(out ? d.vuser_id : MTP_int(MTP::authedId())), d.vfwd_from_id, d.vfwd_date, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup));
HistoryItem *item = App::histories().addToBack(MTP_message(d.vflags, d.vid, out ? MTP_int(MTP::authedId()) : d.vuser_id, MTP_peerUser(out ? d.vuser_id : MTP_int(MTP::authedId())), d.vfwd_from_id, d.vfwd_date, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup, MTPnullEntities));
if (item) {
history.peerMessagesUpdated(item->history()->peer->id);
}
@@ -3354,7 +3369,7 @@ void MainWidget::handleUpdates(const MTPUpdates &updates) {
_byPtsUpdates.insert(ptsKey(SkippedUpdates), updates);
return;
}
HistoryItem *item = App::histories().addToBack(MTP_message(d.vflags, d.vid, d.vfrom_id, MTP_peerChat(d.vchat_id), d.vfwd_from_id, d.vfwd_date, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup));
HistoryItem *item = App::histories().addToBack(MTP_message(d.vflags, d.vid, d.vfrom_id, MTP_peerChat(d.vchat_id), d.vfwd_from_id, d.vfwd_date, d.vreply_to_msg_id, d.vdate, d.vmessage, MTP_messageMediaEmpty(), MTPnullMarkup, MTPnullEntities));
if (item) {
history.peerMessagesUpdated(item->history()->peer->id);
}
@@ -3483,11 +3498,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
History *history = App::historyLoaded(App::peerFromUser(d.vuser_id));
UserData *user = App::userLoaded(d.vuser_id.v);
if (history && user) {
if (d.vaction.type() == mtpc_sendMessageTypingAction) {
App::histories().regTyping(history, user);
} else if (d.vaction.type() == mtpc_sendMessageCancelAction) {
history->unregTyping(user);
}
App::histories().regSendAction(history, user, d.vaction);
}
} break;
@@ -3496,7 +3507,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
History *history = App::historyLoaded(App::peerFromChat(d.vchat_id));
UserData *user = (d.vuser_id.v == MTP::authedId()) ? 0 : App::userLoaded(d.vuser_id.v);
if (history && user) {
App::histories().regTyping(history, user);
App::histories().regSendAction(history, user, d.vaction);
}
} break;
@@ -3638,6 +3649,10 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
case mtpc_updateUserBlocked: {
const MTPDupdateUserBlocked &d(update.c_updateUserBlocked());
if (UserData *user = App::userLoaded(d.vuser_id.v)) {
user->blocked = d.vblocked.v ? UserIsBlocked : UserIsNotBlocked;
App::markPeerUpdated(user);
}
} break;
case mtpc_updateNewAuthorization: {

View File

@@ -281,11 +281,11 @@ public:
DragState getDragState(const QMimeData *mime);
bool leaveChatFailed(PeerData *peer, const RPCError &e);
void deleteHistory(PeerData *peer, const MTPUpdates &updates);
void deleteHistoryAfterLeave(PeerData *peer, const MTPUpdates &updates);
void deleteHistoryPart(PeerData *peer, const MTPmessages_AffectedHistory &result);
void deleteMessages(const QVector<MTPint> &ids);
void deletedContact(UserData *user, const MTPcontacts_Link &result);
void deleteHistoryAndContact(UserData *user, const MTPcontacts_Link &result);
void deleteConversation(PeerData *peer);
void clearHistory(PeerData *peer);
void removeContact(UserData *user);
@@ -421,6 +421,8 @@ public slots:
void onTopBarClick();
void onPeerShown(PeerData *peer);
void searchInPeer(PeerData *peer);
void onUpdateNotifySettings();
void onPhotosSelect();

View File

@@ -775,18 +775,14 @@ void MediaView::displayPhoto(PhotoData *photo, HistoryItem *item) {
_x = (width() - _w) / 2;
_y = (height() - _h) / 2;
_width = _w;
if (_photo->user == WebPageUserId && _msgid) {
if (HistoryItem *item = App::histItemById(_msgid)) {
if (dynamic_cast<HistoryForwarded*>(item)) {
_from = static_cast<HistoryForwarded*>(item)->fromForwarded();
} else {
_from = item->from();
}
if (_msgid && item) {
if (HistoryForwarded *fwd = item->toHistoryForwarded()) {
_from = fwd->fromForwarded();
} else {
_from = App::user(_photo->user);
_from = item->from();
}
} else {
_from = App::user(_photo->user);
_from = _user;
}
updateControls();
_photo->full->load();
@@ -955,10 +951,10 @@ void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) { // empty
}
_x = (width() - _w) / 2;
_y = (height() - _h) / 2;
if (HistoryForwarded *fwd = dynamic_cast<HistoryForwarded*>(item)) {
_from = fwd->fromForwarded()->asUser();
if (HistoryForwarded *fwd = item->toHistoryForwarded()) {
_from = fwd->fromForwarded();
} else {
_from = item->from()->asUser();
_from = item->from();
}
_full = 1;
updateControls();
@@ -1850,7 +1846,7 @@ void MediaView::loadBack() {
if (App::main()) App::main()->loadMediaBack(_history->peer, _overview);
} else if (_user && _user->photosCount != 0) {
int32 limit = (_index < MediaOverviewStartPerPage && _user->photos.size() > MediaOverviewStartPerPage) ? SearchPerPage : MediaOverviewStartPerPage;
_loadRequest = MTP::send(MTPphotos_GetUserPhotos(_user->inputUser, MTP_int(_user->photos.size()), MTP_int(0), MTP_int(limit)), rpcDone(&MediaView::userPhotosLoaded, _user));
_loadRequest = MTP::send(MTPphotos_GetUserPhotos(_user->inputUser, MTP_int(_user->photos.size()), MTP_long(0), MTP_int(limit)), rpcDone(&MediaView::userPhotosLoaded, _user));
}
}

View File

@@ -150,6 +150,13 @@ with open('scheme.tl') as f:
print('Bad param found: "' + param + '" in line: ' + line);
continue;
ptype = pmasktype.group(3);
if (ptype.find('<') >= 0):
templ = re.match(r'^([vV]ector<)([A-Za-z0-9\._]+)>$', ptype);
if (templ):
ptype = templ.group(1) + 'MTP' + templ.group(2).replace('.', '_') + '>';
else:
print('Bad template type: ' + ptype);
continue;
if (not pname in conditions):
conditionsList.append(pname);
conditions[pname] = pmasktype.group(2);

View File

@@ -1253,6 +1253,7 @@ MTProtoConnectionPrivate::MTProtoConnectionPrivate(QThread *thread, MTProtoConne
, _pingMsgId(0)
, restarted(false)
, keyId(0)
// , sessionDataMutex(QReadWriteLock::Recursive)
, sessionData(data)
, myKeyLock(false)
, authKeyData(0)
@@ -1856,7 +1857,7 @@ void MTProtoConnectionPrivate::tryToSend() {
}
}
mtpRequestData::padding(toSendRequest);
sendRequest(toSendRequest, needAnyResponse);
sendRequest(toSendRequest, needAnyResponse, lockFinished);
}
void MTProtoConnectionPrivate::retryByTimer() {
@@ -1971,8 +1972,11 @@ void MTProtoConnectionPrivate::restart(bool maybeBadKey) {
}
}
lockFinished.unlock();
doDisconnect();
if (_needSessionReset) {
lockFinished.relock();
if (sessionData && _needSessionReset) {
resetSession();
}
restarted = true;
@@ -2089,7 +2093,12 @@ void MTProtoConnectionPrivate::onWaitIPv4Failed() {
void MTProtoConnectionPrivate::doDisconnect() {
destroyConn();
unlockKey();
{
QReadLocker lockFinished(&sessionDataMutex);
if (sessionData) {
unlockKey();
}
}
clearAuthKeyData();
@@ -2113,12 +2122,16 @@ void MTProtoConnectionPrivate::handleReceived() {
DEBUG_LOG(("MTP Error: auth_key for dc %1 busy, cant lock").arg(dc));
clearMessages();
keyId = 0;
lockFinished.unlock();
return restart();
}
mtpAuthKeyPtr key(sessionData->getKey());
if (!key || key->keyId() != keyId) {
DEBUG_LOG(("MTP Error: auth_key id for dc %1 changed").arg(dc));
lockFinished.unlock();
return restart();
}
@@ -2129,11 +2142,15 @@ void MTProtoConnectionPrivate::handleReceived() {
if (len < 18) { // 2 auth_key_id, 4 msg_key, 2 salt, 2 session, 2 msg_id, 1 seq_no, 1 length, (1 data + 3 padding) min
LOG(("TCP Error: bad message received, len %1").arg(len * sizeof(mtpPrime)));
TCP_LOG(("TCP Error: bad message %1").arg(mb(encrypted, len * sizeof(mtpPrime)).str()));
lockFinished.unlock();
return restart();
}
if (keyId != *(uint64*)encrypted) {
LOG(("TCP Error: bad auth_key_id %1 instead of %2 received").arg(keyId).arg(*(uint64*)encrypted));
TCP_LOG(("TCP Error: bad message %1").arg(mb(encrypted, len * sizeof(mtpPrime)).str()));
lockFinished.unlock();
return restart();
}
@@ -2152,6 +2169,8 @@ void MTProtoConnectionPrivate::handleReceived() {
LOG(("TCP Error: bad msg_len received %1, data size: %2").arg(msgLen).arg(dataBuffer.size()));
TCP_LOG(("TCP Error: bad message %1").arg(mb(encrypted, len * sizeof(mtpPrime)).str()));
_conn->received().pop_front();
lockFinished.unlock();
return restart();
}
uchar sha1Buffer[20];
@@ -2159,6 +2178,8 @@ void MTProtoConnectionPrivate::handleReceived() {
LOG(("TCP Error: bad SHA1 hash after aesDecrypt in message"));
TCP_LOG(("TCP Error: bad message %1").arg(mb(encrypted, len * sizeof(mtpPrime)).str()));
_conn->received().pop_front();
lockFinished.unlock();
return restart();
}
TCP_LOG(("TCP Info: decrypted message %1,%2,%3 is %4 len").arg(msgId).arg(seqNo).arg(logBool(needAck)).arg(msgLen + 8 * sizeof(mtpPrime)));
@@ -2168,6 +2189,8 @@ void MTProtoConnectionPrivate::handleReceived() {
LOG(("MTP Error: bad server session received"));
TCP_LOG(("MTP Error: bad server session %1 instead of %2 in message received").arg(session).arg(serverSession));
_conn->received().pop_front();
lockFinished.unlock();
return restart();
}
@@ -2177,6 +2200,8 @@ void MTProtoConnectionPrivate::handleReceived() {
bool isReply = ((msgId & 0x03) == 1);
if (!isReply && ((msgId & 0x03) != 3)) {
LOG(("MTP Error: bad msg_id %1 in message received").arg(msgId));
lockFinished.unlock();
return restart();
}
@@ -2252,6 +2277,8 @@ void MTProtoConnectionPrivate::handleReceived() {
if (res < 0) {
_needSessionReset = (res < -1);
lockFinished.unlock();
return restart();
}
retryTimeout = 1; // reset restart() timer
@@ -3022,6 +3049,8 @@ void MTProtoConnectionPrivate::onConnected4() {
disconnect(_conn4, SIGNAL(connected()), this, SLOT(onConnected4()));
if (!_conn4->isConnected()) {
LOG(("Connection Error: not connected in onConnected4(), state: %1").arg(_conn4->debugState()));
lockFinished.unlock();
return restart();
}
@@ -3030,6 +3059,7 @@ void MTProtoConnectionPrivate::onConnected4() {
DEBUG_LOG(("MTP Info: connection through IPv4 succeed."));
lockFinished.unlock();
updateAuthKey();
}
@@ -3043,6 +3073,8 @@ void MTProtoConnectionPrivate::onConnected6() {
disconnect(_conn6, SIGNAL(connected()), this, SLOT(onConnected6()));
if (!_conn6->isConnected()) {
LOG(("Connection Error: not connected in onConnected(), state: %1").arg(_conn6->debugState()));
lockFinished.unlock();
return restart();
}
@@ -3121,6 +3153,7 @@ void MTProtoConnectionPrivate::updateAuthKey() {
connect(_conn, SIGNAL(receivedData()), this, SLOT(pqAnswered()));
DEBUG_LOG(("AuthKey Info: sending Req_pq.."));
lockFinished.unlock();
sendRequestNotSecure(req_pq);
}
@@ -3424,6 +3457,7 @@ void MTProtoConnectionPrivate::dhClientParamsAnswered() {
MTPSet_client_DH_params::ResponseType res_client_DH_params;
if (!readResponseNotSecure(res_client_DH_params)) {
lockFinished.unlock();
return restart();
}
@@ -3433,11 +3467,15 @@ void MTProtoConnectionPrivate::dhClientParamsAnswered() {
if (resDH.vnonce != authKeyData->nonce) {
LOG(("AuthKey Error: received nonce <> sent nonce (in dh_gen_ok)!"));
DEBUG_LOG(("AuthKey Error: received nonce: %1, sent nonce: %2").arg(mb(&resDH.vnonce, 16).str()).arg(mb(&authKeyData->nonce, 16).str()));
lockFinished.unlock();
return restart();
}
if (resDH.vserver_nonce != authKeyData->server_nonce) {
LOG(("AuthKey Error: received server_nonce <> sent server_nonce (in dh_gen_ok)!"));
DEBUG_LOG(("AuthKey Error: received server_nonce: %1, sent server_nonce: %2").arg(mb(&resDH.vserver_nonce, 16).str()).arg(mb(&authKeyData->server_nonce, 16).str()));
lockFinished.unlock();
return restart();
}
authKeyData->new_nonce_buf[32] = 1;
@@ -3445,6 +3483,8 @@ void MTProtoConnectionPrivate::dhClientParamsAnswered() {
if (resDH.vnew_nonce_hash1 != *(MTPint128*)(hashSha1(authKeyData->new_nonce_buf, 41, sha1Buffer) + 1)) {
LOG(("AuthKey Error: received new_nonce_hash1 did not match!"));
DEBUG_LOG(("AuthKey Error: received new_nonce_hash1: %1, new_nonce_buf: %2").arg(mb(&resDH.vnew_nonce_hash1, 16).str()).arg(mb(authKeyData->new_nonce_buf, 41).str()));
lockFinished.unlock();
return restart();
}
@@ -3467,11 +3507,15 @@ void MTProtoConnectionPrivate::dhClientParamsAnswered() {
if (resDH.vnonce != authKeyData->nonce) {
LOG(("AuthKey Error: received nonce <> sent nonce (in dh_gen_retry)!"));
DEBUG_LOG(("AuthKey Error: received nonce: %1, sent nonce: %2").arg(mb(&resDH.vnonce, 16).str()).arg(mb(&authKeyData->nonce, 16).str()));
lockFinished.unlock();
return restart();
}
if (resDH.vserver_nonce != authKeyData->server_nonce) {
LOG(("AuthKey Error: received server_nonce <> sent server_nonce (in dh_gen_retry)!"));
DEBUG_LOG(("AuthKey Error: received server_nonce: %1, sent server_nonce: %2").arg(mb(&resDH.vserver_nonce, 16).str()).arg(mb(&authKeyData->server_nonce, 16).str()));
lockFinished.unlock();
return restart();
}
authKeyData->new_nonce_buf[32] = 2;
@@ -3479,6 +3523,8 @@ void MTProtoConnectionPrivate::dhClientParamsAnswered() {
if (resDH.vnew_nonce_hash2 != *(MTPint128*)(hashSha1(authKeyData->new_nonce_buf, 41, sha1Buffer) + 1)) {
LOG(("AuthKey Error: received new_nonce_hash2 did not match!"));
DEBUG_LOG(("AuthKey Error: received new_nonce_hash2: %1, new_nonce_buf: %2").arg(mb(&resDH.vnew_nonce_hash2, 16).str()).arg(mb(authKeyData->new_nonce_buf, 41).str()));
lockFinished.unlock();
return restart();
}
authKeyData->retry_id = authKeyData->auth_key_aux_hash;
@@ -3489,11 +3535,15 @@ void MTProtoConnectionPrivate::dhClientParamsAnswered() {
if (resDH.vnonce != authKeyData->nonce) {
LOG(("AuthKey Error: received nonce <> sent nonce (in dh_gen_fail)!"));
DEBUG_LOG(("AuthKey Error: received nonce: %1, sent nonce: %2").arg(mb(&resDH.vnonce, 16).str()).arg(mb(&authKeyData->nonce, 16).str()));
lockFinished.unlock();
return restart();
}
if (resDH.vserver_nonce != authKeyData->server_nonce) {
LOG(("AuthKey Error: received server_nonce <> sent server_nonce (in dh_gen_fail)!"));
DEBUG_LOG(("AuthKey Error: received server_nonce: %1, sent server_nonce: %2").arg(mb(&resDH.vserver_nonce, 16).str()).arg(mb(&authKeyData->server_nonce, 16).str()));
lockFinished.unlock();
return restart();
}
authKeyData->new_nonce_buf[32] = 3;
@@ -3501,13 +3551,20 @@ void MTProtoConnectionPrivate::dhClientParamsAnswered() {
if (resDH.vnew_nonce_hash3 != *(MTPint128*)(hashSha1(authKeyData->new_nonce_buf, 41, sha1Buffer) + 1)) {
LOG(("AuthKey Error: received new_nonce_hash3 did not match!"));
DEBUG_LOG(("AuthKey Error: received new_nonce_hash3: %1, new_nonce_buf: %2").arg(mb(&resDH.vnew_nonce_hash3, 16).str()).arg(mb(authKeyData->new_nonce_buf, 41).str()));
lockFinished.unlock();
return restart();
}
LOG(("AuthKey Error: dh_gen_fail received!"));
} return restart();
}
lockFinished.unlock();
return restart();
}
LOG(("AuthKey Error: unknown set_client_DH_params_answer received, typeId = %1").arg(res_client_DH_params.type()));
lockFinished.unlock();
return restart();
}
@@ -3646,7 +3703,7 @@ bool MTProtoConnectionPrivate::readResponseNotSecure(TResponse &response) {
return true;
}
bool MTProtoConnectionPrivate::sendRequest(mtpRequest &request, bool needAnyResponse) {
bool MTProtoConnectionPrivate::sendRequest(mtpRequest &request, bool needAnyResponse, QReadLocker &lockFinished) {
uint32 fullSize = request->size();
if (fullSize < 9) return false;
@@ -3656,6 +3713,8 @@ bool MTProtoConnectionPrivate::sendRequest(mtpRequest &request, bool needAnyResp
ReadLockerAttempt lock(sessionData->keyMutex());
if (!lock) {
DEBUG_LOG(("MTP Info: could not lock key for read in sendBuffer(), dc %1, restarting..").arg(dc));
lockFinished.unlock();
restart();
return false;
}
@@ -3663,6 +3722,8 @@ bool MTProtoConnectionPrivate::sendRequest(mtpRequest &request, bool needAnyResp
mtpAuthKeyPtr key(sessionData->getKey());
if (!key || key->keyId() != keyId) {
DEBUG_LOG(("MTP Error: auth_key id for dc %1 changed").arg(dc));
lockFinished.unlock();
restart();
return false;
}
@@ -3729,9 +3790,6 @@ void MTProtoConnectionPrivate::lockKey() {
}
void MTProtoConnectionPrivate::unlockKey() {
QReadLocker lockFinished(&sessionDataMutex);
if (!sessionData) return;
if (myKeyLock) {
myKeyLock = false;
sessionData->keyMutex()->unlock();

View File

@@ -52,6 +52,7 @@ enum {
};
static const MTPReplyMarkup MTPnullMarkup = MTP_replyKeyboardMarkup(MTP_int(0), MTP_vector<MTPKeyboardButtonRow>(0));
static const MTPVector<MTPMessageEntity> MTPnullEntities = MTP_vector<MTPMessageEntity>(0);
#include "mtproto/mtpPublicRSA.h"
#include "mtproto/mtpAuthKey.h"
@@ -410,7 +411,6 @@ public slots:
void onError4(bool maybeBadKey = false);
void onError6(bool maybeBadKey = false);
void doDisconnect();
void doFinish();
// Auth key creation packet receive slots
@@ -430,6 +430,8 @@ public slots:
private:
void doDisconnect();
void createConn(bool createIPv4, bool createIPv6);
void destroyConn(MTPabstractConnection **conn = 0); // 0 - destory all
@@ -437,7 +439,7 @@ private:
mtpMsgId prepareToSend(mtpRequest &request, mtpMsgId currentLastId);
mtpMsgId replaceMsgId(mtpRequest &request, mtpMsgId newId);
bool sendRequest(mtpRequest &request, bool needAnyResponse);
bool sendRequest(mtpRequest &request, bool needAnyResponse, QReadLocker &lockFinished);
mtpRequestId wasSent(mtpMsgId msgId) const;
int32 handleOneReceived(const mtpPrime *from, const mtpPrime *end, uint64 msgId, int32 serverTime, uint64 serverSalt, bool badTime);

View File

@@ -366,7 +366,7 @@ static const mtpTypeId mtpLayers[] = {
mtpc_invokeWithLayer17,
mtpc_invokeWithLayer18,
}, mtpLayerMaxSingle = sizeof(mtpLayers) / sizeof(mtpLayers[0]);
static const mtpPrime mtpCurrentLayer = 32;
static const mtpPrime mtpCurrentLayer = 34;
template <typename bareT>
class MTPBoxed : public bareT {

View File

@@ -487,33 +487,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
to.add("{ inputPeerSelf }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
break;
case mtpc_inputPeerContact:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ inputPeerContact");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_inputPeerForeign:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ inputPeerForeign");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_inputPeerChat:
if (stage) {
to.add(",\n").addSpaces(lev);
@@ -527,6 +500,20 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
}
break;
case mtpc_inputPeerUser:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ inputPeerUser");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_inputUserEmpty:
to.add("{ inputUserEmpty }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
break;
@@ -535,24 +522,11 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
to.add("{ inputUserSelf }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
break;
case mtpc_inputUserContact:
case mtpc_inputUser:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ inputUserContact");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_inputUserForeign:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ inputUserForeign");
to.add("{ inputUser");
to.add("\n").addSpaces(lev);
}
switch (stage) {
@@ -1374,6 +1348,7 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
case 8: to.add(" message: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 9: to.add(" media: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 10: to.add(" reply_markup: "); ++stages.back(); if (flag & MTPDmessage::flag_reply_markup) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 6 IN FIELD flags ]"); } break;
case 11: to.add(" entities: "); ++stages.back(); if (flag & MTPDmessage::flag_entities) { types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 7 IN FIELD flags ]"); } break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
@@ -1662,10 +1637,8 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
switch (stage) {
case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" geo: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 5: to.add(" sizes: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" sizes: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
@@ -1740,9 +1713,9 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
switch (stage) {
case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" duration: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" duration: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" mime_type: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 5: to.add(" size: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 6: to.add(" thumb: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 7: to.add(" dc_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
@@ -2221,10 +2194,6 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
}
break;
case mtpc_messages_messageEmpty:
to.add("{ messages_messageEmpty }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
break;
case mtpc_messages_sentMessage:
if (stage) {
to.add(",\n").addSpaces(lev);
@@ -2236,8 +2205,9 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" media: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" pts: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" pts_count: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" entities: "); ++stages.back(); types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" pts: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 5: to.add(" pts_count: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
@@ -2336,6 +2306,10 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
to.add("{ inputMessagesFilterAudioDocuments }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
break;
case mtpc_inputMessagesFilterUrl:
to.add("{ inputMessagesFilterUrl }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
break;
case mtpc_updateNewMessage:
if (stage) {
to.add(",\n").addSpaces(lev);
@@ -2847,6 +2821,7 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
case 7: to.add(" fwd_from_id: "); ++stages.back(); if (flag & MTPDupdateShortMessage::flag_fwd_from_id) { types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
case 8: to.add(" fwd_date: "); ++stages.back(); if (flag & MTPDupdateShortMessage::flag_fwd_date) { types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
case 9: to.add(" reply_to_msg_id: "); ++stages.back(); if (flag & MTPDupdateShortMessage::flag_reply_to_msg_id) { types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 3 IN FIELD flags ]"); } break;
case 10: to.add(" entities: "); ++stages.back(); if (flag & MTPDupdateShortMessage::flag_entities) { types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 7 IN FIELD flags ]"); } break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
@@ -2870,6 +2845,7 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
case 8: to.add(" fwd_from_id: "); ++stages.back(); if (flag & MTPDupdateShortChatMessage::flag_fwd_from_id) { types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
case 9: to.add(" fwd_date: "); ++stages.back(); if (flag & MTPDupdateShortChatMessage::flag_fwd_date) { types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
case 10: to.add(" reply_to_msg_id: "); ++stages.back(); if (flag & MTPDupdateShortChatMessage::flag_reply_to_msg_id) { types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 3 IN FIELD flags ]"); } break;
case 11: to.add(" entities: "); ++stages.back(); if (flag & MTPDupdateShortChatMessage::flag_entities) { types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 7 IN FIELD flags ]"); } break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
@@ -3513,12 +3489,11 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
switch (stage) {
case 0: to.add(" id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" access_hash: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" duration: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 5: to.add(" mime_type: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 6: to.add(" size: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 7: to.add(" dc_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" date: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" duration: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" mime_type: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 5: to.add(" size: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 6: to.add(" dc_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
@@ -4389,6 +4364,179 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
}
break;
case mtpc_help_appChangelogEmpty:
to.add("{ help_appChangelogEmpty }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();
break;
case mtpc_help_appChangelog:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ help_appChangelog");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" text: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_messageEntityUnknown:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messageEntityUnknown");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" length: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_messageEntityMention:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messageEntityMention");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" length: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_messageEntityHashtag:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messageEntityHashtag");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" length: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_messageEntityBotCommand:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messageEntityBotCommand");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" length: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_messageEntityUrl:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messageEntityUrl");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" length: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_messageEntityEmail:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messageEntityEmail");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" length: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_messageEntityBold:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messageEntityBold");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" length: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_messageEntityItalic:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messageEntityItalic");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" length: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_messageEntityCode:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messageEntityCode");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" length: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_messageEntityPre:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messageEntityPre");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" length: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" language: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_messageEntityTextUrl:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ messageEntityTextUrl");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" length: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" url: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_req_pq:
if (stage) {
to.add(",\n").addSpaces(lev);
@@ -5442,6 +5590,7 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
case 3: to.add(" message: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" random_id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 5: to.add(" reply_markup: "); ++stages.back(); if (flag & MTPmessages_sendMessage::flag_reply_markup) { types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 2 IN FIELD flags ]"); } break;
case 6: to.add(" entities: "); ++stages.back(); if (flag & MTPmessages_sendMessage::flag_entities) { types.push_back(00); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 3 IN FIELD flags ]"); } break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
@@ -5786,7 +5935,7 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
switch (stage) {
case 0: to.add(" user_id: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" offset: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" max_id: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" max_id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" limit: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
@@ -6201,6 +6350,22 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
}
break;
case mtpc_help_getAppChangelog:
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
to.add("{ help_getAppChangelog");
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" device_model: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" system_version: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" app_version: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" lang_code: "); ++stages.back(); types.push_back(mtpc_string); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
break;
case mtpc_rpc_result:
if (stage) {
to.add(",\n").addSpaces(lev);

File diff suppressed because it is too large Load Diff

View File

@@ -132,14 +132,10 @@ null#56730bcc = Null;
inputPeerEmpty#7f3b18ea = InputPeer;
inputPeerSelf#7da07ec9 = InputPeer;
inputPeerContact#1023dbe8 user_id:int = InputPeer;
inputPeerForeign#9b447325 user_id:int access_hash:long = InputPeer;
inputPeerChat#179be863 chat_id:int = InputPeer;
inputUserEmpty#b98886cf = InputUser;
inputUserSelf#f7c1b13f = InputUser;
inputUserContact#86e94f65 user_id:int = InputUser;
inputUserForeign#655e74ff user_id:int access_hash:long = InputUser;
inputPhoneContact#f392b7f4 client_id:long phone:string first_name:string last_name:string = InputContact;
@@ -216,7 +212,7 @@ chatPhotoEmpty#37c1011c = ChatPhoto;
chatPhoto#6153276a photo_small:FileLocation photo_big:FileLocation = ChatPhoto;
messageEmpty#83e5de54 id:int = Message;
message#c3060325 flags:# id:int from_id:int to_id:Peer fwd_from_id:flags.2?int fwd_date:flags.2?int reply_to_msg_id:flags.3?int date:int message:string media:MessageMedia reply_markup:flags.6?ReplyMarkup = Message;
message#f07814c8 flags:# id:int from_id:int to_id:Peer fwd_from_id:flags.2?int fwd_date:flags.2?int reply_to_msg_id:flags.3?int date:int message:string media:MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> = Message;
messageService#1d86f70e flags:int id:int from_id:int to_id:Peer date:int action:MessageAction = Message;
messageMediaEmpty#3ded6320 = MessageMedia;
@@ -237,14 +233,14 @@ messageActionChatDeleteUser#b2ae9b0c user_id:int = MessageAction;
dialog#c1dd804a peer:Peer top_message:int read_inbox_max_id:int unread_count:int notify_settings:PeerNotifySettings = Dialog;
photoEmpty#2331b22d id:long = Photo;
photo#c3838076 id:long access_hash:long user_id:int date:int geo:GeoPoint sizes:Vector<PhotoSize> = Photo;
photo#cded42fe id:long access_hash:long date:int sizes:Vector<PhotoSize> = Photo;
photoSizeEmpty#e17e23c type:string = PhotoSize;
photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = PhotoSize;
photoCachedSize#e9a734fa type:string location:FileLocation w:int h:int bytes:bytes = PhotoSize;
videoEmpty#c10658a8 id:long = Video;
video#ee9f4a4d id:long access_hash:long user_id:int date:int duration:int size:int thumb:PhotoSize dc_id:int w:int h:int = Video;
video#f72887d3 id:long access_hash:long date:int duration:int mime_type:string size:int thumb:PhotoSize dc_id:int w:int h:int = Video;
geoPointEmpty#1117dd5f = GeoPoint;
geoPoint#2049d70c long:double lat:double = GeoPoint;
@@ -307,9 +303,7 @@ messages.dialogsSlice#71e094f3 count:int dialogs:Vector<Dialog> messages:Vector<
messages.messages#8c718e87 messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
messages.messagesSlice#b446ae3 count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
messages.messageEmpty#3f4e0648 = messages.Message;
messages.sentMessage#4c3d47f3 id:int date:int media:MessageMedia pts:int pts_count:int = messages.SentMessage;
messages.sentMessage#8a99d8e0 id:int date:int media:MessageMedia entities:Vector<MessageEntity> pts:int pts_count:int = messages.SentMessage;
messages.chats#64ff9fd5 chats:Vector<Chat> = messages.Chats;
@@ -325,6 +319,7 @@ inputMessagesFilterPhotoVideoDocuments#d95e73bb = MessagesFilter;
inputMessagesFilterDocument#9eddf188 = MessagesFilter;
inputMessagesFilterAudio#cfc87522 = MessagesFilter;
inputMessagesFilterAudioDocuments#5afbf764 = MessagesFilter;
inputMessagesFilterUrl#7ef0dd87 = MessagesFilter;
updateNewMessage#1f2b0afd message:Message pts:int pts_count:int = Update;
updateMessageID#4e90bfd6 id:int random_id:long = Update;
@@ -346,8 +341,8 @@ updates.difference#f49ca0 new_messages:Vector<Message> new_encrypted_messages:Ve
updates.differenceSlice#a8fb1981 new_messages:Vector<Message> new_encrypted_messages:Vector<EncryptedMessage> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> intermediate_state:updates.State = updates.Difference;
updatesTooLong#e317af7e = Updates;
updateShortMessage#ed5c2127 flags:# id:int user_id:int message:string pts:int pts_count:int date:int fwd_from_id:flags.2?int fwd_date:flags.2?int reply_to_msg_id:flags.3?int = Updates;
updateShortChatMessage#52238b3c flags:# id:int from_id:int chat_id:int message:string pts:int pts_count:int date:int fwd_from_id:flags.2?int fwd_date:flags.2?int reply_to_msg_id:flags.3?int = Updates;
updateShortMessage#3f32d858 flags:# id:int user_id:int message:string pts:int pts_count:int date:int fwd_from_id:flags.2?int fwd_date:flags.2?int reply_to_msg_id:flags.3?int entities:flags.7?Vector<MessageEntity> = Updates;
updateShortChatMessage#f9409b3d flags:# id:int from_id:int chat_id:int message:string pts:int pts_count:int date:int fwd_from_id:flags.2?int fwd_date:flags.2?int reply_to_msg_id:flags.3?int entities:flags.7?Vector<MessageEntity> = Updates;
updateShort#78d4dec1 update:Update date:int = Updates;
updatesCombined#725b04c3 updates:Vector<Update> users:Vector<User> chats:Vector<Chat> date:int seq_start:int seq:int = Updates;
updates#74ae4240 updates:Vector<Update> users:Vector<User> chats:Vector<Chat> date:int seq:int = Updates;
@@ -454,7 +449,7 @@ inputAudioFileLocation#74dc404d id:long access_hash:long = InputFileLocation;
inputDocumentFileLocation#4e45abe9 id:long access_hash:long = InputFileLocation;
audioEmpty#586988d8 id:long = Audio;
audio#c7ac6496 id:long access_hash:long user_id:int date:int duration:int mime_type:string size:int dc_id:int = Audio;
audio#f9e35055 id:long access_hash:long date:int duration:int mime_type:string size:int dc_id:int = Audio;
documentEmpty#36f8c871 id:long = Document;
document#f9a39f4f id:long access_hash:long date:int mime_type:string size:int thumb:PhotoSize dc_id:int attributes:Vector<DocumentAttribute> = Document;
@@ -607,6 +602,25 @@ replyKeyboardHide#a03e5b85 flags:# = ReplyMarkup;
replyKeyboardForceReply#f4108aa0 flags:# = ReplyMarkup;
replyKeyboardMarkup#3502758c flags:# rows:Vector<KeyboardButtonRow> = ReplyMarkup;
inputPeerUser#7b8e7de6 user_id:int access_hash:long = InputPeer;
inputUser#d8292816 user_id:int access_hash:long = InputUser;
help.appChangelogEmpty#af7e0394 = help.AppChangelog;
help.appChangelog#4668e6bd text:string = help.AppChangelog;
messageEntityUnknown#bb92ba95 offset:int length:int = MessageEntity;
messageEntityMention#fa04579d offset:int length:int = MessageEntity;
messageEntityHashtag#6f635b0d offset:int length:int = MessageEntity;
messageEntityBotCommand#6cef8ac7 offset:int length:int = MessageEntity;
messageEntityUrl#6ed02538 offset:int length:int = MessageEntity;
messageEntityEmail#64e475c2 offset:int length:int = MessageEntity;
messageEntityBold#bd610bc9 offset:int length:int = MessageEntity;
messageEntityItalic#826f8b60 offset:int length:int = MessageEntity;
messageEntityCode#28a20571 offset:int length:int = MessageEntity;
messageEntityPre#73924be0 offset:int length:int language:string = MessageEntity;
messageEntityTextUrl#76a6d327 offset:int length:int url:string = MessageEntity;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@@ -658,7 +672,7 @@ messages.deleteHistory#f4f8fb61 peer:InputPeer offset:int = messages.AffectedHis
messages.deleteMessages#a5f18925 id:Vector<int> = messages.AffectedMessages;
messages.receivedMessages#5a954c0 max_id:int = Vector<ReceivedNotifyMessage>;
messages.setTyping#a3825e50 peer:InputPeer action:SendMessageAction = Bool;
messages.sendMessage#fc55e6b5 flags:# peer:InputPeer reply_to_msg_id:flags.0?int message:string random_id:long reply_markup:flags.2?ReplyMarkup = messages.SentMessage;
messages.sendMessage#df12390 flags:# peer:InputPeer reply_to_msg_id:flags.0?int message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> = messages.SentMessage;
messages.sendMedia#c8f16791 flags:# peer:InputPeer reply_to_msg_id:flags.0?int media:InputMedia random_id:long reply_markup:flags.2?ReplyMarkup = Updates;
messages.forwardMessages#55e1728d peer:InputPeer id:Vector<int> random_id:Vector<long> = Updates;
messages.getChats#3c6aa187 id:Vector<int> = messages.Chats;
@@ -685,7 +699,7 @@ help.getAppUpdate#c812ac7e device_model:string system_version:string app_version
help.saveAppLog#6f02f748 events:Vector<InputAppEvent> = Bool;
help.getInviteText#a4a95186 lang_code:string = help.InviteText;
photos.getUserPhotos#b7ee553c user_id:InputUser offset:int max_id:int limit:int = photos.Photos;
photos.getUserPhotos#91cd32a8 user_id:InputUser offset:int max_id:long limit:int = photos.Photos;
messages.forwardMessage#33963bf9 peer:InputPeer id:int random_id:long = Updates;
messages.sendBroadcast#bf73f4da contacts:Vector<InputUser> random_id:Vector<long> message:string media:InputMedia = Updates;
@@ -770,3 +784,5 @@ messages.getStickerSet#2619a90e stickerset:InputStickerSet = messages.StickerSet
messages.installStickerSet#7b30c3a6 stickerset:InputStickerSet disabled:Bool = Bool;
messages.uninstallStickerSet#f96e55de stickerset:InputStickerSet = Bool;
messages.startBot#1b3e0ffc bot:InputUser chat_id:int random_id:long start_param:string = Updates;
help.getAppChangelog#5bab7fb2 device_model:string system_version:string app_version:string lang_code:string = help.AppChangelog;

View File

@@ -55,7 +55,6 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
// settings
_enableNotifications(this, lang(lng_profile_enable_notifications)),
_clearHistory(this, lang(lng_profile_clear_history)),
// shared media
_allMediaTypes(false),
@@ -65,6 +64,14 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
_mediaDocuments(this, QString()),
_mediaAudios(this, QString()),
// actions
_searchInPeer(this, lang(lng_profile_search_messages)),
_clearHistory(this, lang(lng_profile_clear_history)),
_deleteConversation(this, lang(_peer->chat ? lng_profile_clear_and_exit : lng_profile_delete_conversation)),
_wasBlocked(_peerUser ? _peerUser->blocked : UserBlockUnknown),
_blockRequest(0),
_blockUser(this, lang((_peerUser && _peerUser->botInfo) ? lng_profile_block_bot : lng_profile_block_user), st::btnRedLink),
// participants
_pHeight(st::profileListPhotoSize + st::profileListPadding.height() * 2),
_kickWidth(st::linkFont->m.width(lang(lng_profile_kick))),
@@ -76,12 +83,15 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
connect(App::api(), SIGNAL(fullPeerUpdated(PeerData*)), this, SLOT(onFullPeerUpdated(PeerData*)));
if (_peerUser) {
if (_peerUser->blocked == UserIsBlocked) {
_blockUser.setText(lang(_peerUser->botInfo ? lng_profile_unblock_bot : lng_profile_unblock_user));
}
_phoneText = App::formatPhone(_peerUser->phone);
PhotoData *userPhoto = (_peerUser->photoId && _peerUser->photoId != UnknownPeerPhotoId) ? App::photo(_peerUser->photoId) : 0;
if (userPhoto && userPhoto->date) {
_photoLink = TextLinkPtr(new PhotoLink(userPhoto, _peer));
}
if ((_peerUser->botInfo && !_peerUser->botInfo->inited) || (_peerUser->photoId == UnknownPeerPhotoId) || (_peerUser->photoId && !userPhoto->date)) {
if ((_peerUser->botInfo && !_peerUser->botInfo->inited) || (_peerUser->photoId == UnknownPeerPhotoId) || (_peerUser->photoId && !userPhoto->date) || (_peerUser->blocked == UserBlockUnknown)) {
App::api()->requestFullPeer(_peer);
}
} else {
@@ -96,7 +106,6 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
// profile
_nameText.setText(st::profileNameFont, _nameCache, _textNameOptions);
connect(&_uploadPhoto, SIGNAL(clicked()), this, SLOT(onUpdatePhoto()));
connect(&_addParticipant, SIGNAL(clicked()), this, SLOT(onAddParticipant()));
connect(&_sendMessage, SIGNAL(clicked()), this, SLOT(onSendMessage()));
@@ -149,7 +158,6 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
// settings
connect(&_enableNotifications, SIGNAL(clicked()), this, SLOT(onEnableNotifications()));
connect(&_clearHistory, SIGNAL(clicked()), this, SLOT(onClearHistory()));
// shared media
connect(&_mediaShowAll, SIGNAL(clicked()), this, SLOT(onMediaShowAll()));
@@ -163,6 +171,12 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee
_mediaLinks[OverviewAudios] = &_mediaAudios;
App::main()->preloadOverviews(_peer);
// actions
connect(&_searchInPeer, SIGNAL(clicked()), this, SLOT(onSearchInPeer()));
connect(&_clearHistory, SIGNAL(clicked()), this, SLOT(onClearHistory()));
connect(&_deleteConversation, SIGNAL(clicked()), this, SLOT(onDeleteConversation()));
connect(&_blockUser, SIGNAL(clicked()), this, SLOT(onBlockUser()));
App::contextItem(0);
resizeEvent(0);
@@ -181,6 +195,10 @@ void ProfileInner::onSendMessage() {
App::main()->showPeerHistory(_peer->id, ShowAtUnreadMsgId);
}
void ProfileInner::onSearchInPeer() {
App::main()->searchInPeer(_peer);
}
void ProfileInner::onEnableNotifications() {
App::main()->updateNotifySetting(_peer, _enableNotifications.checked());
}
@@ -244,17 +262,54 @@ void ProfileInner::onUpdatePhoto() {
}
void ProfileInner::onClearHistory() {
ConfirmBox *box = new ConfirmBox(lng_sure_delete_history(lt_contact, _peer->name));
ConfirmBox *box = new ConfirmBox(_peer->chat ? lng_sure_delete_group_history(lt_group, _peer->name) : lng_sure_delete_history(lt_contact, _peer->name));
connect(box, SIGNAL(confirmed()), this, SLOT(onClearHistorySure()));
App::wnd()->showLayer(box);
}
void ProfileInner::onClearHistorySure() {
App::main()->showDialogs();
App::wnd()->hideLayer();
App::main()->clearHistory(_peer);
}
void ProfileInner::onDeleteConversation() {
ConfirmBox *box = new ConfirmBox(_peer->chat ? lng_sure_delete_and_exit(lt_group, _peer->name) : lng_sure_delete_history(lt_contact, _peer->name));
connect(box, SIGNAL(confirmed()), this, SLOT(onDeleteConversationSure()));
App::wnd()->showLayer(box);
}
void ProfileInner::onDeleteConversationSure() {
if (_peer->chat) {
App::wnd()->hideLayer();
App::main()->showDialogs();
MTP::send(MTPmessages_DeleteChatUser(MTP_int(_peer->id & 0xFFFFFFFF), App::self()->inputUser), App::main()->rpcDone(&MainWidget::deleteHistoryAfterLeave, _peer), App::main()->rpcFail(&MainWidget::leaveChatFailed, _peer));
} else {
App::main()->deleteConversation(_peer);
}
}
void ProfileInner::onBlockUser() {
if (!_peerUser || _blockRequest) return;
if (_peerUser->blocked == UserIsBlocked) {
_blockRequest = MTP::send(MTPcontacts_Unblock(_peerUser->inputUser), rpcDone(&ProfileInner::blockDone, false), rpcFail(&ProfileInner::blockFail));
} else {
_blockRequest = MTP::send(MTPcontacts_Block(_peerUser->inputUser), rpcDone(&ProfileInner::blockDone, true), rpcFail(&ProfileInner::blockFail));
}
}
void ProfileInner::blockDone(bool blocked, const MTPBool &result) {
_blockRequest = 0;
if (!_peerUser) return;
_peerUser->blocked = blocked ? UserIsBlocked : UserIsNotBlocked;
emit App::main()->peerUpdated(_peerUser);
}
bool ProfileInner::blockFail(const RPCError &error) {
if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false;
//_blockRequest = 0;
return false;
}
void ProfileInner::onAddParticipant() {
App::wnd()->showLayer(new ContactsBox(_peerChat));
}
@@ -384,6 +439,10 @@ void ProfileInner::peerUpdated(PeerData *data) {
if (_peerUser) {
_phoneText = App::formatPhone(_peerUser->phone);
if (_peerUser->photoId && _peerUser->photoId != UnknownPeerPhotoId) photo = App::photo(_peerUser->photoId);
if (_wasBlocked != _peerUser->blocked) {
_wasBlocked = _peerUser->blocked;
_blockUser.setText(lang((_peerUser->blocked == UserIsBlocked) ? (_peerUser->botInfo ? lng_profile_unblock_bot : lng_profile_unblock_user) : (_peerUser->botInfo ? lng_profile_block_bot : lng_profile_block_user)));
}
} else {
if (_peerChat->photoId && _peerChat->photoId != UnknownPeerPhotoId) photo = App::photo(_peerChat->photoId);
}
@@ -610,6 +669,15 @@ void ProfileInner::paintEvent(QPaintEvent *e) {
top += _mediaLinks[OverviewPhotos]->height();
}
// actions
p.setFont(st::profileHeaderFont->f);
p.setPen(st::profileHeaderColor->p);
p.drawText(_left + st::profileHeaderLeft, top + st::profileHeaderTop + st::profileHeaderFont->ascent, lang(lng_profile_actions_section));
top += st::profileHeaderSkip;
top += _searchInPeer.height() + st::setLittleSkip + _clearHistory.height() + st::setLittleSkip + _deleteConversation.height();
if (_peerUser && App::userFromPeer(_peerUser->id) != MTP::authedId()) top += st::setSectionSkip + _blockUser.height();
// participants
if (_peerChat && (_peerChat->count > 0 || !_participants.isEmpty())) {
QString sectionHeader = lang(_participants.isEmpty() ? lng_profile_loading : lng_profile_participants_section);
@@ -707,7 +775,7 @@ void ProfileInner::updateSelected() {
update(QRect(_left, _aboutTop, _width, _aboutHeight));
}
int32 partfrom = _mediaAudios.y() + _mediaAudios.height() + st::profileHeaderSkip;
int32 partfrom = _deleteConversation.y() + _deleteConversation.height() + st::profileHeaderSkip;
int32 newSelected = (lp.x() >= _left - st::profileListPadding.width() && lp.x() < _left + _width + st::profileListPadding.width() && lp.y() >= partfrom) ? (lp.y() - partfrom) / _pHeight : -1;
UserData *newKickOver = 0;
@@ -874,6 +942,16 @@ void ProfileInner::resizeEvent(QResizeEvent *e) {
}
top += _mediaLinks[OverviewPhotos]->height();
// actions
top += st::profileHeaderSkip;
_searchInPeer.move(_left, top); top += _searchInPeer.height() + st::setLittleSkip;
_clearHistory.move(_left, top); top += _clearHistory.height() + st::setLittleSkip;
_deleteConversation.move(_left, top); top += _deleteConversation.height();
if (_peerUser && App::userFromPeer(_peerUser->id) != MTP::authedId()) {
top += st::setSectionSkip;
_blockUser.move(_left, top); top += _blockUser.height();
}
// participants
if (_peerChat && (_peerChat->count > 0 || !_participants.isEmpty())) {
top += st::profileHeaderSkip;
@@ -883,7 +961,6 @@ void ProfileInner::resizeEvent(QResizeEvent *e) {
}
}
top += st::profileHeaderTop + st::profileHeaderFont->ascent - st::linkFont->ascent;
_clearHistory.move(_left, top);
}
void ProfileInner::contextMenuEvent(QContextMenuEvent *e) {
@@ -970,6 +1047,9 @@ void ProfileInner::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type)
}
void ProfileInner::showAll() {
_searchInPeer.show();
_clearHistory.show();
_deleteConversation.show();
if (_peerChat) {
_sendMessage.hide();
_shareContact.hide();
@@ -1005,8 +1085,7 @@ void ProfileInner::showAll() {
_addParticipant.hide();
}
}
_enableNotifications.show();
_clearHistory.hide();
_blockUser.hide();
} else {
_uploadPhoto.hide();
_cancelPhoto.hide();
@@ -1025,9 +1104,14 @@ void ProfileInner::showAll() {
_shareContact.show();
_inviteToGroup.hide();
}
_enableNotifications.show();
_clearHistory.show();
if (App::userFromPeer(_peerUser->id) != MTP::authedId()) {
_blockUser.show();
} else {
_blockUser.hide();
}
}
_enableNotifications.show();
updateNotifySettings();
// shared media
@@ -1070,9 +1154,13 @@ void ProfileInner::showAll() {
reorderParticipants();
int32 h;
if (_peerUser) {
h = _clearHistory.y() + _clearHistory.height() + st::profileHeaderSkip;
if (App::userFromPeer(_peerUser->id) == MTP::authedId()) {
h = _deleteConversation.y() + _deleteConversation.height() + st::profileHeaderSkip;
} else {
h = _blockUser.y() + _blockUser.height() + st::profileHeaderSkip;
}
} else {
h = _mediaAudios.y() + _mediaAudios.height() + st::profileHeaderSkip;
h = _deleteConversation.y() + _deleteConversation.height() + st::profileHeaderSkip;
if (!_participants.isEmpty()) {
h += st::profileHeaderSkip + _participants.size() * _pHeight;
} else if (_peerChat->count > 0) {

View File

@@ -68,10 +68,14 @@ public slots:
void onShareContact();
void onInviteToGroup();
void onSendMessage();
void onSearchInPeer();
void onEnableNotifications();
void onClearHistory();
void onClearHistorySure();
void onDeleteConversation();
void onDeleteConversationSure();
void onBlockUser();
void onAddParticipant();
void onUpdatePhoto();
@@ -142,7 +146,6 @@ private:
// settings
FlatCheckbox _enableNotifications;
LinkButton _clearHistory;
// shared media
bool _allMediaTypes;
@@ -150,6 +153,12 @@ private:
LinkButton *_mediaLinks[OverviewCount];
QString overviewLinkText(int32 type, int32 count);
// actions
LinkButton _searchInPeer, _clearHistory, _deleteConversation;
UserBlockedStatus _wasBlocked;
mtpRequestId _blockRequest;
LinkButton _blockUser;
// participants
int32 _pHeight;
int32 _kickWidth, _selectedRow, _lastPreload;
@@ -171,6 +180,9 @@ private:
QString _onlineText;
ContextMenu *_menu;
void blockDone(bool blocked, const MTPBool &result);
bool blockFail(const RPCError &error);
};
class ProfileWidget : public QWidget, public RPCSender, public Animated {

View File

@@ -68,7 +68,7 @@ namespace {
bool frameless = true;
bool finished = true;
bool noQtTrayIcon = false, noTryUnity = false;
bool noQtTrayIcon = false, noTryUnity = false, tryAppIndicator = false;
bool useGtkBase = false, useAppIndicator = false, useStatusIcon = false, trayIconChecked = false, useUnityCount = false;
AppIndicator *_trayIndicator = 0;
@@ -356,7 +356,8 @@ namespace {
inited = true;
QString cdesktop = QString(getenv("XDG_CURRENT_DESKTOP")).toLower();
noQtTrayIcon = (cdesktop == qstr("pantheon"));// || (cdesktop == qstr("gnome"));
noQtTrayIcon = (cdesktop == qstr("pantheon")) || (cdesktop == qstr("gnome"));
tryAppIndicator = (cdesktop == qstr("xfce"));
noTryUnity = (cdesktop != qstr("unity"));
if (noQtTrayIcon) cSetSupportTray(false);
@@ -401,6 +402,9 @@ namespace {
if (!loadFunction(lib_gtk, "g_type_check_instance_cast", ps_g_type_check_instance_cast)) return;
if (!loadFunction(lib_gtk, "g_signal_connect_data", ps_g_signal_connect_data)) return;
if (!loadFunction(lib_gtk, "g_object_ref_sink", ps_g_object_ref_sink)) return;
if (!loadFunction(lib_gtk, "g_object_unref", ps_g_object_unref)) return;
useGtkBase = true;
std::cout << "loaded gtk funcs!\n";
}
@@ -416,7 +420,7 @@ namespace {
void setupGtk() {
QLibrary lib_gtk, lib_indicator;
if (!noQtTrayIcon) {
if (!noQtTrayIcon && !tryAppIndicator) {
if (!noTryUnity) {
if (loadLibrary(lib_gtk, "gtk-3", 0)) {
setupGtkBase(lib_gtk);
@@ -448,6 +452,14 @@ namespace {
}
}
}
if (tryAppIndicator) {
if (useGtkBase && useAppIndicator) {
noQtTrayIcon = true;
cSetSupportTray(false);
}
return;
}
if (!useGtkBase && lib_gtk.isLoaded()) {
std::cout << "no appindicator, trying to load gtk..\n";
setupGtkBase(lib_gtk);
@@ -471,8 +483,6 @@ namespace {
if (!loadFunction(lib_gtk, "gtk_status_icon_position_menu", ps_gtk_status_icon_position_menu)) return;
if (!loadFunction(lib_gtk, "gtk_menu_popup", ps_gtk_menu_popup)) return;
if (!loadFunction(lib_gtk, "gtk_get_current_event_time", ps_gtk_get_current_event_time)) return;
if (!loadFunction(lib_gtk, "g_object_ref_sink", ps_g_object_ref_sink)) return;
if (!loadFunction(lib_gtk, "g_object_unref", ps_g_object_unref)) return;
if (!loadFunction(lib_gtk, "g_idle_add", ps_g_idle_add)) return;
useStatusIcon = true;
std::cout << "status icon api loaded\n";
@@ -1239,6 +1249,10 @@ void psRegisterCustomScheme() {
}
}
void psNewVersion() {
psRegisterCustomScheme();
}
bool _execUpdater(bool update = true) {
static const int MaxLen = 65536, MaxArgsCount = 128;

View File

@@ -68,6 +68,10 @@ public:
void psUpdateCounter();
bool psHasNativeNotifications() {
return false;
}
virtual QImage iconWithCounter(int size, int count, style::color bg, bool smallIcon) = 0;
~PsMainWindow();
@@ -159,7 +163,7 @@ void psShowInFolder(const QString &name);
void psStart();
void psFinish();
void psRegisterCustomScheme();
void psNewVersion();
void psUpdateOverlayed(QWidget *widget);
inline QString psConvertFileUrl(const QString &url) {

View File

@@ -564,7 +564,9 @@ void psClearInitLogs() {
}
void psActivateProcess(uint64 pid) {
objc_activateProgram();
if (!pid) {
objc_activateProgram(App::wnd() ? App::wnd()->winId() : 0);
}
}
QString psCurrentCountry() {
@@ -651,7 +653,7 @@ void psFinish() {
objc_finish();
}
void psRegisterCustomScheme() {
void psNewVersion() {
objc_registerCustomScheme();
}

View File

@@ -83,6 +83,10 @@ public:
void psUpdateCounter();
bool psHasNativeNotifications() {
return !(QSysInfo::macVersion() < QSysInfo::MV_10_8);
}
virtual QImage iconWithCounter(int size, int count, style::color bg, bool smallIcon) = 0;
~PsMainWindow();
@@ -189,7 +193,7 @@ void psShowInFolder(const QString &name);
void psStart();
void psFinish();
void psRegisterCustomScheme();
void psNewVersion();
void psUpdateOverlayed(QWidget *widget);
QString psConvertFileUrl(const QString &url);

View File

@@ -73,7 +73,7 @@ void objc_execTelegram();
void objc_registerCustomScheme();
void objc_activateProgram();
void objc_activateProgram(WId winId);
bool objc_moveFile(const QString &from, const QString &to);
void objc_deleteDir(const QString &dir);

View File

@@ -982,8 +982,12 @@ void objc_execTelegram() {
_execUpdater(NO);
}
void objc_activateProgram() {
void objc_activateProgram(WId winId) {
[NSApp activateIgnoringOtherApps:YES];
if (winId) {
NSWindow *w = [reinterpret_cast<NSView*>(winId) window];
[w makeKeyAndOrderFront:NSApp];
}
}
bool objc_moveFile(const QString &from, const QString &to) {

File diff suppressed because it is too large Load Diff

View File

@@ -67,6 +67,9 @@ public:
void psUpdateCounter();
bool psHasNativeNotifications();
void psCleanNotifyPhotosIn(int32 dt);
virtual QImage iconWithCounter(int size, int count, style::color bg, bool smallIcon) = 0;
~PsMainWindow();
@@ -77,6 +80,8 @@ public slots:
void psSavePosition(Qt::WindowState state = Qt::WindowActive);
void psShowTrayMenu();
void psCleanNotifyPhotos();
protected:
bool psHasTrayIcon() const {
@@ -100,6 +105,8 @@ private:
HMENU ps_menu;
HICON ps_iconBig, ps_iconSmall, ps_iconOverlay;
SingleTimer ps_cleanNotifyPhotosTimer;
void psDestroyIcons();
};
@@ -161,7 +168,7 @@ void psShowInFolder(const QString &name);
void psStart();
void psFinish();
void psRegisterCustomScheme();
void psNewVersion();
void psUpdateOverlayed(TWidget *widget);
inline QString psConvertFileUrl(const QString &url) {

View File

@@ -42,6 +42,7 @@ QString gDialogLastPath, gDialogHelperPath; // optimize QFileDialog
bool gSoundNotify = true;
bool gDesktopNotify = true;
DBINotifyView gNotifyView = dbinvShowPreview;
bool gWindowsNotifications = true;
bool gStartMinimized = false;
bool gStartInTray = false;
bool gAutoStart = false;
@@ -119,11 +120,7 @@ QString gLangFile;
bool gRetina = false;
float64 gRetinaFactor = 1.;
int32 gIntRetinaFactor = 1;
#ifdef Q_OS_MAC
bool gCustomNotifies = false;
#else
bool gCustomNotifies = true;
#endif
uint64 gInstance = 0.;
#ifdef Q_OS_WIN
@@ -159,8 +156,10 @@ int gOtherOnline = 0;
float64 gSongVolume = 0.9;
SavedPeers gSavedPeers;
SavedPeersByTime gSavedPeersByTime;
void settingsParseArgs(int argc, char *argv[]) {
gCustomNotifies = true;
#ifdef Q_OS_MAC
if (QSysInfo::macVersion() < QSysInfo::MV_10_8) {
gUpdateURL = QUrl(qsl("http://tdesktop.com/mac32/tupdates/current"));

View File

@@ -101,6 +101,8 @@ DeclareSetting(bool, DesktopNotify);
DeclareSetting(DBINotifyView, NotifyView);
DeclareSetting(bool, AutoUpdate);
DeclareSetting(bool, WindowsNotifications);
struct TWindowPos {
TWindowPos() : moncrc(0), maximized(0), x(0), y(0), w(0), h(0) {
}
@@ -308,4 +310,10 @@ DeclareSetting(int, OtherOnline);
DeclareSetting(float64, SongVolume);
struct PeerData;
typedef QMap<PeerData*, QDateTime> SavedPeers;
typedef QMultiMap<QDateTime, PeerData*> SavedPeersByTime;
DeclareRefSetting(SavedPeers, SavedPeers);
DeclareRefSetting(SavedPeersByTime, SavedPeersByTime);
void settingsParseArgs(int argc, char *argv[]);

View File

@@ -122,6 +122,7 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent),
_desktopNotify(this, lang(lng_settings_desktop_notify), cDesktopNotify()),
_senderName(this, lang(lng_settings_show_name), cNotifyView() <= dbinvShowName),
_messagePreview(this, lang(lng_settings_show_preview), cNotifyView() <= dbinvShowPreview),
_windowsNotifications(this, lang(lng_settings_use_windows), cWindowsNotifications()),
_soundNotify(this, lang(lng_settings_sound_notify), cSoundNotify()),
// general
@@ -186,7 +187,10 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent),
_connectionTypeText(lang(lng_connection_type) + ' '),
_connectionTypeWidth(st::linkFont->m.width(_connectionTypeText)),
_showSessions(this, lang(lng_settings_show_sessions)),
_logOut(this, lang(lng_settings_logout), st::btnLogout)
_askQuestion(this, lang(lng_settings_ask_question)),
_telegramFAQ(this, lang(lng_settings_faq)),
_logOut(this, lang(lng_settings_logout), st::btnLogout),
_supportGetRequest(0)
{
if (self()) {
_nameText.setText(st::setNameFont, _nameCache, _textNameOptions);
@@ -217,6 +221,7 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent),
connect(&_desktopNotify, SIGNAL(changed()), this, SLOT(onDesktopNotify()));
connect(&_senderName, SIGNAL(changed()), this, SLOT(onSenderName()));
connect(&_messagePreview, SIGNAL(changed()), this, SLOT(onMessagePreview()));
connect(&_windowsNotifications, SIGNAL(changed()), this, SLOT(onWindowsNotifications()));
connect(&_soundNotify, SIGNAL(changed()), this, SLOT(onSoundNotify()));
// general
@@ -288,6 +293,8 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : QWidget(parent),
connect(&_passwordTurnOff, SIGNAL(clicked()), this, SLOT(onPasswordOff()));
connect(&_connectionType, SIGNAL(clicked()), this, SLOT(onConnectionType()));
connect(&_showSessions, SIGNAL(clicked()), this, SLOT(onShowSessions()));
connect(&_askQuestion, SIGNAL(clicked()), this, SLOT(onAskQuestion()));
connect(&_telegramFAQ, SIGNAL(clicked()), this, SLOT(onTelegramFAQ()));
connect(&_logOut, SIGNAL(clicked()), App::wnd(), SLOT(onLogout()));
if (App::main()) {
@@ -411,6 +418,9 @@ void SettingsInner::paintEvent(QPaintEvent *e) {
top += _desktopNotify.height() + st::setLittleSkip;
top += _senderName.height() + st::setLittleSkip;
top += _messagePreview.height() + st::setSectionSkip;
if (App::wnd()->psHasNativeNotifications() && cPlatform() == dbipWindows) {
top += _windowsNotifications.height() + st::setSectionSkip;
}
top += _soundNotify.height();
}
@@ -637,6 +647,9 @@ void SettingsInner::resizeEvent(QResizeEvent *e) {
_desktopNotify.move(_left, top); top += _desktopNotify.height() + st::setLittleSkip;
_senderName.move(_left, top); top += _senderName.height() + st::setLittleSkip;
_messagePreview.move(_left, top); top += _messagePreview.height() + st::setSectionSkip;
if (App::wnd()->psHasNativeNotifications() && cPlatform() == dbipWindows) {
_windowsNotifications.move(_left, top); top += _windowsNotifications.height() + st::setSectionSkip;
}
_soundNotify.move(_left, top); top += _soundNotify.height();
}
@@ -719,7 +732,12 @@ void SettingsInner::resizeEvent(QResizeEvent *e) {
_connectionType.move(_left + _connectionTypeWidth, top); top += _connectionType.height() + st::setLittleSkip;
if (self()) {
_showSessions.move(_left, top); top += _showSessions.height() + st::setSectionSkip;
_askQuestion.move(_left, top); top += _askQuestion.height() + st::setLittleSkip;
_telegramFAQ.move(_left, top); top += _telegramFAQ.height() + st::setSectionSkip;
_logOut.move(_left, top);
} else {
top += st::setSectionSkip - st::setLittleSkip;
_telegramFAQ.move(_left, top);
}
}
@@ -745,7 +763,9 @@ void SettingsInner::keyPressEvent(QKeyEvent *e) {
App::wnd()->showLayer(box);
from = size;
break;
} else if (qsl("debugmode").startsWith(str) || qsl("testmode").startsWith(str)) {
} else if (str == qstr("loadlang")) {
chooseCustomLang();
} else if (qsl("debugmode").startsWith(str) || qsl("testmode").startsWith(str) || qsl("loadlang").startsWith(str)) {
break;
}
++from;
@@ -810,7 +830,7 @@ bool SettingsInner::animStep(float64 ms) {
void SettingsInner::updateSize(int32 newWidth) {
if (_logOut.isHidden()) {
resize(newWidth, _connectionType.geometry().bottom() + st::setBottom);
resize(newWidth, _telegramFAQ.geometry().bottom() + st::setBottom);
} else {
resize(newWidth, _logOut.geometry().bottom() + st::setBottom);
}
@@ -936,11 +956,17 @@ void SettingsInner::showAll() {
_desktopNotify.show();
_senderName.show();
_messagePreview.show();
if (App::wnd()->psHasNativeNotifications() && cPlatform() == dbipWindows) {
_windowsNotifications.show();
} else {
_windowsNotifications.hide();
}
_soundNotify.show();
} else {
_desktopNotify.hide();
_senderName.hide();
_messagePreview.hide();
_windowsNotifications.hide();
_soundNotify.hide();
}
@@ -1049,6 +1075,7 @@ void SettingsInner::showAll() {
_passwordTurnOff.show();
}
_showSessions.show();
_askQuestion.show();
_logOut.show();
} else {
_passcodeEdit.hide();
@@ -1057,8 +1084,10 @@ void SettingsInner::showAll() {
_passwordEdit.hide();
_passwordTurnOff.hide();
_showSessions.hide();
_askQuestion.hide();
_logOut.hide();
}
_telegramFAQ.show();
}
void SettingsInner::saveError(const QString &str) {
@@ -1067,6 +1096,17 @@ void SettingsInner::saveError(const QString &str) {
update();
}
void SettingsInner::supportGot(const MTPhelp_Support &support) {
if (!App::main()) return;
if (support.type() == mtpc_help_support) {
const MTPDhelp_support &d(support.c_help_support());
UserData *u = App::feedUsers(MTP_vector<MTPUser>(1, d.vuser));
App::main()->showPeerHistory(u->id, ShowAtUnreadMsgId);
App::wnd()->hideSettings();
}
}
void SettingsInner::onUpdatePhotoCancel() {
if (self()) {
App::app()->cancelPhotoUpdate(self()->id);
@@ -1110,25 +1150,47 @@ void SettingsInner::onShowSessions() {
App::wnd()->showLayer(box);
}
void SettingsInner::onAskQuestion() {
if (!App::self()) return;
ConfirmBox *box = new ConfirmBox(lang(lng_settings_ask_sure), lang(lng_settings_ask_ok), lang(lng_settings_faq_button));
connect(box, SIGNAL(confirmed()), this, SLOT(onAskQuestionSure()));
connect(box, SIGNAL(cancelPressed()), this, SLOT(onTelegramFAQ()));
App::wnd()->showLayer(box);
}
void SettingsInner::onAskQuestionSure() {
if (_supportGetRequest) return;
_supportGetRequest = MTP::send(MTPhelp_GetSupport(), rpcDone(&SettingsInner::supportGot));
}
void SettingsInner::onTelegramFAQ() {
QDesktopServices::openUrl(qsl("https://telegram.org/faq#general"));
}
void SettingsInner::chooseCustomLang() {
QString file;
QByteArray arr;
if (filedialogGetOpenFile(file, arr, qsl("Choose language .strings file"), qsl("Language files (*.strings)"))) {
_testlang = QFileInfo(file).absoluteFilePath();
LangLoaderPlain loader(_testlang, LangLoaderRequest(lng_sure_save_language, lng_cancel, lng_continue));
if (loader.errors().isEmpty()) {
LangLoaderResult result = loader.found();
QString text = result.value(lng_sure_save_language, langOriginal(lng_sure_save_language)),
save = result.value(lng_continue, langOriginal(lng_continue)),
cancel = result.value(lng_cancel, langOriginal(lng_cancel));
ConfirmBox *box = new ConfirmBox(text, save, cancel);
connect(box, SIGNAL(confirmed()), this, SLOT(onSaveTestLang()));
App::wnd()->showLayer(box);
} else {
App::wnd()->showLayer(new ConfirmBox("Custom lang failed :(\n\nError: " + loader.errors(), true, lang(lng_close)));
}
}
}
void SettingsInner::onChangeLanguage() {
if ((_changeLanguage.clickModifiers() & Qt::ShiftModifier) && (_changeLanguage.clickModifiers() & Qt::AltModifier)) {
QString file;
QByteArray arr;
if (filedialogGetOpenFile(file, arr, qsl("Choose language .strings file"), qsl("Language files (*.strings)"))) {
_testlang = QFileInfo(file).absoluteFilePath();
LangLoaderPlain loader(_testlang, LangLoaderRequest(lng_sure_save_language, lng_cancel, lng_continue));
if (loader.errors().isEmpty()) {
LangLoaderResult result = loader.found();
QString text = result.value(lng_sure_save_language, langOriginal(lng_sure_save_language)),
save = result.value(lng_continue, langOriginal(lng_continue)),
cancel = result.value(lng_cancel, langOriginal(lng_cancel));
ConfirmBox *box = new ConfirmBox(text, save, cancel);
connect(box, SIGNAL(confirmed()), this, SLOT(onSaveTestLang()));
App::wnd()->showLayer(box);
} else {
App::wnd()->showLayer(new ConfirmBox("Custom lang failed :(\n\nError: " + loader.errors(), true, lang(lng_close)));
}
}
chooseCustomLang();
} else {
App::wnd()->showLayer(new LanguageBox());
}
@@ -1349,6 +1411,13 @@ void SettingsInner::onSoundNotify() {
Local::writeUserSettings();
}
void SettingsInner::onWindowsNotifications() {
cSetWindowsNotifications(!cWindowsNotifications());
App::wnd()->notifyClearFast();
cSetCustomNotifies(!cWindowsNotifications());
Local::writeUserSettings();
}
void SettingsInner::onDesktopNotify() {
cSetDesktopNotify(_desktopNotify.checked());
if (!_desktopNotify.checked()) {

View File

@@ -78,6 +78,8 @@ public:
void showAll();
void chooseCustomLang();
void updateChatBackground();
void needBackgroundUpdate(bool tile);
@@ -125,6 +127,8 @@ public slots:
void onSenderName();
void onMessagePreview();
void onWindowsNotifications();
void onReplaceEmojis();
void onViewEmojis();
@@ -162,10 +166,16 @@ public slots:
void onUpdateLocalStorage();
void onAskQuestion();
void onAskQuestionSure();
void onTelegramFAQ();
private:
void saveError(const QString &str = QString());
void supportGot(const MTPhelp_Support &support);
void setScale(DBIScale newScale);
QString _testlang, _secretText;
@@ -192,7 +202,7 @@ private:
LinkButton _chooseUsername;
// notifications
FlatCheckbox _desktopNotify, _senderName, _messagePreview, _soundNotify;
FlatCheckbox _desktopNotify, _senderName, _messagePreview, _windowsNotifications, _soundNotify;
// general
LinkButton _changeLanguage;
@@ -261,9 +271,11 @@ private:
LinkButton _connectionType;
QString _connectionTypeText;
int32 _connectionTypeWidth;
LinkButton _showSessions;
LinkButton _showSessions, _askQuestion, _telegramFAQ;
FlatButton _logOut;
mtpRequestId _supportGetRequest;
void gotPassword(const MTPaccount_Password &result);
void offPasswordDone(const MTPBool &result);
bool offPasswordFail(const RPCError &error);

View File

@@ -35,5 +35,7 @@ Q_IMPORT_PLUGIN(QWbmpPlugin)
Q_IMPORT_PLUGIN(QWebpPlugin)
#elif defined Q_OS_LINUX
Q_IMPORT_PLUGIN(QComposePlatformInputContextPlugin)
Q_IMPORT_PLUGIN(QIbusPlatformInputContextPlugin)
Q_IMPORT_PLUGIN(QFcitxPlatformInputContextPlugin)
Q_IMPORT_PLUGIN(QWebpPlugin)
#endif

View File

@@ -90,10 +90,10 @@ NotifySettingsPtr globalNotifyAllPtr = UnknownNotifySettings, globalNotifyUsersP
PeerData::PeerData(const PeerId &id) : id(id)
, loaded(false)
, chat(App::isChat(id))
, access(0)
, colorIndex(peerColorIndex(id))
, color(peerColor(colorIndex))
, photo(chat ? chatDefPhoto(colorIndex) : userDefPhoto(colorIndex))
, photoId(UnknownPeerPhotoId)
, nameVersion(0)
, notify(UnknownNotifySettings)
{
@@ -132,14 +132,16 @@ void PeerData::updateName(const QString &newName, const QString &newNameOrPhone,
}
}
void UserData::setPhoto(const MTPUserProfilePhoto &p) {
void UserData::setPhoto(const MTPUserProfilePhoto &p) { // see Local::readPeer as well
PhotoId newPhotoId = photoId;
ImagePtr newPhoto = photo;
StorageImageLocation newPhotoLoc = photoLoc;
switch (p.type()) {
case mtpc_userProfilePhoto: {
const MTPDuserProfilePhoto d(p.c_userProfilePhoto());
newPhotoId = d.vphoto_id.v;
newPhoto = ImagePtr(160, 160, d.vphoto_small, userDefPhoto(colorIndex));
newPhotoLoc = App::imageLocation(160, 160, d.vphoto_small);
newPhoto = newPhotoLoc.isNull() ? userDefPhoto(colorIndex) : ImagePtr(newPhotoLoc);
//App::feedPhoto(App::photoFromUserPhoto(MTP_int(id & 0xFFFFFFFF), MTP_int(unixtime()), p));
} break;
default: {
@@ -151,11 +153,13 @@ void UserData::setPhoto(const MTPUserProfilePhoto &p) {
} else {
newPhoto = userDefPhoto(colorIndex);
}
newPhotoLoc = StorageImageLocation();
} break;
}
if (newPhotoId != photoId || newPhoto.v() != photo.v()) {
if (newPhotoId != photoId || newPhoto.v() != photo.v() || newPhotoLoc != photoLoc) {
photoId = newPhotoId;
photo = newPhoto;
photoLoc = newPhotoLoc;
emit App::main()->peerPhotoChanged(this);
}
}
@@ -226,6 +230,7 @@ void UserData::setBotInfoVersion(int32 version) {
botInfo->inited = false;
}
}
void UserData::setBotInfo(const MTPBotInfo &info) {
switch (info.type()) {
case mtpc_botInfoEmpty:
@@ -305,23 +310,33 @@ void UserData::madeAction() {
}
}
void ChatData::setPhoto(const MTPChatPhoto &p, const PhotoId &phId) {
void ChatData::setPhoto(const MTPChatPhoto &p, const PhotoId &phId) { // see Local::readPeer as well
PhotoId newPhotoId = photoId;
ImagePtr newPhoto = photo;
StorageImageLocation newPhotoLoc = photoLoc;
switch (p.type()) {
case mtpc_chatPhoto: {
const MTPDchatPhoto d(p.c_chatPhoto());
photo = ImagePtr(160, 160, d.vphoto_small, chatDefPhoto(colorIndex));
photoFull = ImagePtr(640, 640, d.vphoto_big, chatDefPhoto(colorIndex));
if (phId != UnknownPeerPhotoId) {
photoId = phId;
newPhotoId = phId;
}
newPhotoLoc = App::imageLocation(160, 160, d.vphoto_small);
newPhoto = newPhotoLoc.isNull() ? chatDefPhoto(colorIndex) : ImagePtr(newPhotoLoc);
// photoFull = ImagePtr(640, 640, d.vphoto_big, chatDefPhoto(colorIndex));
} break;
default: {
photo = chatDefPhoto(colorIndex);
photoFull = ImagePtr();
photoId = 0;
newPhotoId = 0;
newPhotoLoc = StorageImageLocation();
newPhoto = chatDefPhoto(colorIndex);
// photoFull = ImagePtr();
} break;
}
emit App::main()->peerPhotoChanged(this);
if (newPhotoId != photoId || newPhoto.v() != photo.v() || newPhotoLoc != photoLoc) {
photoId = newPhotoId;
photo = newPhoto;
photoLoc = newPhotoLoc;
emit App::main()->peerPhotoChanged(this);
}
}
void PhotoLink::onClick(Qt::MouseButton button) const {
@@ -389,7 +404,7 @@ QString saveFileName(const QString &title, const QString &filter, const QString
void VideoOpenLink::onClick(Qt::MouseButton button) const {
VideoData *data = video();
if ((!data->user && !data->date) || button != Qt::LeftButton) return;
if (!data->date || button != Qt::LeftButton) return;
QString already = data->already(true);
if (!already.isEmpty()) {
@@ -409,7 +424,7 @@ void VideoOpenLink::onClick(Qt::MouseButton button) const {
}
void VideoSaveLink::doSave(VideoData *data, bool forceSavingAs) {
if (!data->user && !data->date) return;
if (!data->date) return;
QString already = data->already(true);
if (!already.isEmpty() && !forceSavingAs) {
@@ -441,13 +456,13 @@ void VideoSaveLink::onClick(Qt::MouseButton button) const {
void VideoCancelLink::onClick(Qt::MouseButton button) const {
VideoData *data = video();
if ((!data->user && !data->date) || button != Qt::LeftButton) return;
if (!data->date || button != Qt::LeftButton) return;
data->cancel();
}
VideoData::VideoData(const VideoId &id, const uint64 &access, int32 user, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size) :
id(id), access(access), user(user), date(date), duration(duration), w(w), h(h), thumb(thumb), dc(dc), size(size), status(FileReady), uploadOffset(0), fileType(0), openOnSave(0), openOnSaveMsgId(0), loader(0) {
VideoData::VideoData(const VideoId &id, const uint64 &access, int32 date, int32 duration, int32 w, int32 h, const ImagePtr &thumb, int32 dc, int32 size) :
id(id), access(access), date(date), duration(duration), w(w), h(h), thumb(thumb), dc(dc), size(size), status(FileReady), uploadOffset(0), fileType(0), openOnSave(0), openOnSaveMsgId(0), loader(0) {
location = Local::readFileLocation(mediaKey(VideoFileLocation, dc, id));
}
@@ -467,7 +482,7 @@ QString VideoData::already(bool check) {
void AudioOpenLink::onClick(Qt::MouseButton button) const {
AudioData *data = audio();
if ((!data->user && !data->date) || button != Qt::LeftButton) return;
if (!data->date || button != Qt::LeftButton) return;
QString already = data->already(true);
bool play = App::hoveredLinkItem() && audioPlayer();
@@ -501,7 +516,7 @@ void AudioOpenLink::onClick(Qt::MouseButton button) const {
}
void AudioSaveLink::doSave(AudioData *data, bool forceSavingAs) {
if (!data->user && !data->date) return;
if (!data->date) return;
QString already = data->already(true);
if (!already.isEmpty() && !forceSavingAs) {
@@ -534,7 +549,7 @@ void AudioSaveLink::onClick(Qt::MouseButton button) const {
void AudioCancelLink::onClick(Qt::MouseButton button) const {
AudioData *data = audio();
if ((!data->user && !data->date) || button != Qt::LeftButton) return;
if (!data->date || button != Qt::LeftButton) return;
data->cancel();
}
@@ -554,8 +569,8 @@ bool StickerData::setInstalled() const {
return false;
}
AudioData::AudioData(const AudioId &id, const uint64 &access, int32 user, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) :
id(id), access(access), user(user), date(date), mime(mime), duration(duration), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), openOnSaveMsgId(0), loader(0) {
AudioData::AudioData(const AudioId &id, const uint64 &access, int32 date, const QString &mime, int32 duration, int32 dc, int32 size) :
id(id), access(access), date(date), mime(mime), duration(duration), dc(dc), size(size), status(FileReady), uploadOffset(0), openOnSave(0), openOnSaveMsgId(0), loader(0) {
location = Local::readFileLocation(mediaKey(AudioFileLocation, dc, id));
}

View File

@@ -59,8 +59,10 @@ style::color peerColor(int32 index);
ImagePtr userDefPhoto(int32 index);
ImagePtr chatDefPhoto(int32 index);
struct ChatData;
static const PhotoId UnknownPeerPhotoId = 0xFFFFFFFFFFFFFFFFULL;
struct UserData;
struct ChatData;
struct PeerData {
PeerData(const PeerId &id);
virtual ~PeerData() {
@@ -94,13 +96,13 @@ struct PeerData {
bool loaded;
bool chat;
uint64 access;
MTPinputPeer input;
MTPinputUser inputUser;
int32 colorIndex;
style::color color;
ImagePtr photo;
PhotoId photoId;
StorageImageLocation photoLoc;
int32 nameVersion;
@@ -165,11 +167,15 @@ struct BotInfo {
QString startToken, startGroupToken;
};
static const PhotoId UnknownPeerPhotoId = 0xFFFFFFFFFFFFFFFFULL;
enum UserBlockedStatus {
UserBlockUnknown = 0,
UserIsBlocked,
UserIsNotBlocked,
};
struct PhotoData;
struct UserData : public PeerData {
UserData(const PeerId &id) : PeerData(id), photoId(UnknownPeerPhotoId), lnk(new PeerLink(this)), onlineTill(0), contact(-1), photosCount(-1), botInfo(0) {
UserData(const PeerId &id) : PeerData(id), access(0), lnk(new PeerLink(this)), onlineTill(0), contact(-1), blocked(UserBlockUnknown), photosCount(-1), botInfo(0) {
}
void setPhoto(const MTPUserProfilePhoto &photo);
void setName(const QString &first, const QString &last, const QString &phoneName, const QString &username);
@@ -180,15 +186,19 @@ struct UserData : public PeerData {
void madeAction(); // pseudo-online
uint64 access;
MTPinputUser inputUser;
QString firstName;
QString lastName;
QString username;
QString phone;
Text nameText;
PhotoId photoId;
TextLinkPtr lnk;
int32 onlineTill;
int32 contact; // -1 - not contact, cant add (self, empty, deleted, foreign), 0 - not contact, can add (request), 1 - contact
UserBlockedStatus blocked;
typedef QList<PhotoData*> Photos;
Photos photos;
@@ -198,7 +208,7 @@ struct UserData : public PeerData {
};
struct ChatData : public PeerData {
ChatData(const PeerId &id) : PeerData(id), count(0), date(0), version(0), left(false), forbidden(true), botStatus(0), photoId(UnknownPeerPhotoId) {
ChatData(const PeerId &id) : PeerData(id), count(0), date(0), version(0), left(false), forbidden(true), botStatus(0) {
}
void setPhoto(const MTPChatPhoto &photo, const PhotoId &phId = UnknownPeerPhotoId);
int32 count;
@@ -216,8 +226,7 @@ struct ChatData : public PeerData {
typedef QMap<UserData*, bool> MarkupSenders;
MarkupSenders markupSenders;
int32 botStatus; // -1 - no bots, 0 - unknown, 1 - one bot, that sees all history, 2 - other
ImagePtr photoFull;
PhotoId photoId;
// ImagePtr photoFull;
QString invitationUrl;
// geo
};
@@ -228,8 +237,8 @@ inline int32 newMessageFlags(PeerData *p) {
typedef QMap<char, QPixmap> PreparedPhotoThumbs;
struct PhotoData {
PhotoData(const PhotoId &id, const uint64 &access = 0, int32 user = 0, int32 date = 0, const ImagePtr &thumb = ImagePtr(), const ImagePtr &medium = ImagePtr(), const ImagePtr &full = ImagePtr()) :
id(id), access(access), user(user), date(date), thumb(thumb), medium(medium), full(full), chat(0) {
PhotoData(const PhotoId &id, const uint64 &access = 0, int32 date = 0, const ImagePtr &thumb = ImagePtr(), const ImagePtr &medium = ImagePtr(), const ImagePtr &full = ImagePtr()) :
id(id), access(access), date(date), thumb(thumb), medium(medium), full(full), chat(0) {
}
void forget() {
thumb->forget();
@@ -252,7 +261,6 @@ struct PhotoData {
}
PhotoId id;
uint64 access;
int32 user;
int32 date;
ImagePtr thumb, replyPreview;
ImagePtr medium;
@@ -292,7 +300,7 @@ enum FileStatus {
};
struct VideoData {
VideoData(const VideoId &id, const uint64 &access = 0, int32 user = 0, int32 date = 0, int32 duration = 0, int32 w = 0, int32 h = 0, const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0);
VideoData(const VideoId &id, const uint64 &access = 0, int32 date = 0, int32 duration = 0, int32 w = 0, int32 h = 0, const ImagePtr &thumb = ImagePtr(), int32 dc = 0, int32 size = 0);
void forget() {
thumb->forget();
@@ -328,7 +336,6 @@ struct VideoData {
VideoId id;
uint64 access;
int32 user;
int32 date;
int32 duration;
int32 w, h;
@@ -388,7 +395,7 @@ public:
};
struct AudioData {
AudioData(const AudioId &id, const uint64 &access = 0, int32 user = 0, int32 date = 0, const QString &mime = QString(), int32 duration = 0, int32 dc = 0, int32 size = 0);
AudioData(const AudioId &id, const uint64 &access = 0, int32 date = 0, const QString &mime = QString(), int32 duration = 0, int32 dc = 0, int32 size = 0);
void forget() {
}
@@ -423,7 +430,6 @@ struct AudioData {
AudioId id;
uint64 access;
int32 user;
int32 date;
QString mime;
int32 duration;

View File

@@ -1,42 +1,42 @@
<RCC>
<qresource prefix="/gui">
<file>art/fonts/OpenSans-Regular.ttf</file>
<file>art/fonts/OpenSans-Bold.ttf</file>
<file>art/fonts/OpenSans-Semibold.ttf</file>
<file>art/newmsg.wav</file>
<file>art/bg.jpg</file>
<file>art/bg0.png</file>
<file>art/sprite.png</file>
<file>art/sprite_125x.png</file>
<file>art/sprite_150x.png</file>
<file>art/sprite_200x.png</file>
<file>art/blank.gif</file>
<file>art/icon256.png</file>
<file>art/iconbig256.png</file>
</qresource>
<qresource prefix="/ava">
<file>art/chatcolor1.png</file>
<file>art/chatcolor2.png</file>
<file>art/chatcolor3.png</file>
<file>art/chatcolor4.png</file>
<file>art/usercolor1.png</file>
<file>art/usercolor2.png</file>
<file>art/usercolor3.png</file>
<file>art/usercolor4.png</file>
<file>art/usercolor5.png</file>
<file>art/usercolor6.png</file>
<file>art/usercolor7.png</file>
<file>art/usercolor8.png</file>
</qresource>
<qresource prefix="/qt-project.org">
<file>qmime/freedesktop.org.xml</file>
</qresource>
<qresource prefix="/langs">
<file alias="lang_it.strings">langs/lang_it.strings</file>
<file alias="lang_es.strings">langs/lang_es.strings</file>
<file alias="lang_de.strings">langs/lang_de.strings</file>
<file alias="lang_nl.strings">langs/lang_nl.strings</file>
<file alias="lang_pt_BR.strings">langs/lang_pt_BR.strings</file>
<file alias="lang_ko.strings">langs/lang_ko.strings</file>
</qresource>
<qresource prefix="/gui">
<file>art/fonts/OpenSans-Regular.ttf</file>
<file>art/fonts/OpenSans-Bold.ttf</file>
<file>art/fonts/OpenSans-Semibold.ttf</file>
<file>art/newmsg.wav</file>
<file>art/bg.jpg</file>
<file>art/bg0.png</file>
<file>art/sprite.png</file>
<file>art/sprite_125x.png</file>
<file>art/sprite_150x.png</file>
<file>art/sprite_200x.png</file>
<file>art/blank.gif</file>
<file>art/icon256.png</file>
<file>art/iconbig256.png</file>
</qresource>
<qresource prefix="/ava">
<file>art/chatcolor1.png</file>
<file>art/chatcolor2.png</file>
<file>art/chatcolor3.png</file>
<file>art/chatcolor4.png</file>
<file>art/usercolor1.png</file>
<file>art/usercolor2.png</file>
<file>art/usercolor3.png</file>
<file>art/usercolor4.png</file>
<file>art/usercolor5.png</file>
<file>art/usercolor6.png</file>
<file>art/usercolor7.png</file>
<file>art/usercolor8.png</file>
</qresource>
<qresource prefix="/qt-project.org">
<file>qmime/freedesktop.org.xml</file>
</qresource>
<qresource prefix="/langs">
<file alias="lang_it.strings">langs/lang_it.strings</file>
<file alias="lang_es.strings">langs/lang_es.strings</file>
<file alias="lang_de.strings">langs/lang_de.strings</file>
<file alias="lang_nl.strings">langs/lang_nl.strings</file>
<file alias="lang_pt_BR.strings">langs/lang_pt_BR.strings</file>
<file alias="lang_ko.strings">langs/lang_ko.strings</file>
</qresource>
</RCC>

View File

@@ -232,55 +232,56 @@ QString translitRusEng(const QString &rus);
QString rusKeyboardLayoutSwitch(const QString &from);
enum DataBlockId {
dbiKey = 0x00,
dbiUser = 0x01,
dbiDcOptionOld = 0x02,
dbiMaxGroupCount = 0x03,
dbiMutePeer = 0x04,
dbiSendKey = 0x05,
dbiAutoStart = 0x06,
dbiStartMinimized = 0x07,
dbiSoundNotify = 0x08,
dbiWorkMode = 0x09,
dbiSeenTrayTooltip = 0x0a,
dbiDesktopNotify = 0x0b,
dbiAutoUpdate = 0x0c,
dbiLastUpdateCheck = 0x0d,
dbiWindowPosition = 0x0e,
dbiConnectionType = 0x0f,
dbiKey = 0x00,
dbiUser = 0x01,
dbiDcOptionOld = 0x02,
dbiMaxGroupCount = 0x03,
dbiMutePeer = 0x04,
dbiSendKey = 0x05,
dbiAutoStart = 0x06,
dbiStartMinimized = 0x07,
dbiSoundNotify = 0x08,
dbiWorkMode = 0x09,
dbiSeenTrayTooltip = 0x0a,
dbiDesktopNotify = 0x0b,
dbiAutoUpdate = 0x0c,
dbiLastUpdateCheck = 0x0d,
dbiWindowPosition = 0x0e,
dbiConnectionType = 0x0f,
// 0x10 reserved
dbiDefaultAttach = 0x11,
dbiCatsAndDogs = 0x12,
dbiReplaceEmojis = 0x13,
dbiAskDownloadPath = 0x14,
dbiDownloadPath = 0x15,
dbiScale = 0x16,
dbiEmojiTab = 0x17,
dbiRecentEmojisOld = 0x18,
dbiLoggedPhoneNumber = 0x19,
dbiMutedPeers = 0x1a,
dbiDefaultAttach = 0x11,
dbiCatsAndDogs = 0x12,
dbiReplaceEmojis = 0x13,
dbiAskDownloadPath = 0x14,
dbiDownloadPath = 0x15,
dbiScale = 0x16,
dbiEmojiTab = 0x17,
dbiRecentEmojisOld = 0x18,
dbiLoggedPhoneNumber = 0x19,
dbiMutedPeers = 0x1a,
// 0x1b reserved
dbiNotifyView = 0x1c,
dbiSendToMenu = 0x1d,
dbiCompressPastedImage = 0x1e,
dbiLang = 0x1f,
dbiLangFile = 0x20,
dbiTileBackground = 0x21,
dbiAutoLock = 0x22,
dbiDialogLastPath = 0x23,
dbiRecentEmojis = 0x24,
dbiEmojiVariants = 0x25,
dbiRecentStickers = 0x26,
dbiDcOption = 0x27,
dbiTryIPv6 = 0x28,
dbiSongVolume = 0x29,
dbiNotifyView = 0x1c,
dbiSendToMenu = 0x1d,
dbiCompressPastedImage = 0x1e,
dbiLang = 0x1f,
dbiLangFile = 0x20,
dbiTileBackground = 0x21,
dbiAutoLock = 0x22,
dbiDialogLastPath = 0x23,
dbiRecentEmojis = 0x24,
dbiEmojiVariants = 0x25,
dbiRecentStickers = 0x26,
dbiDcOption = 0x27,
dbiTryIPv6 = 0x28,
dbiSongVolume = 0x29,
dbiWindowsNotifications = 0x30,
dbiEncryptedWithSalt = 333,
dbiEncrypted = 444,
dbiEncryptedWithSalt = 333,
dbiEncrypted = 444,
// 500-600 reserved
dbiVersion = 666,
dbiVersion = 666,
};
enum DBISendKey {

View File

@@ -11,7 +11,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.8.43</string>
<string>0.8.50</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>CFBundleSignature</key>

View File

@@ -312,7 +312,10 @@ INCLUDEPATH += "/usr/include/dee-1.0"
INCLUDEPATH += "/usr/include/libdbusmenu-glib-0.4"
LIBS += -lcrypto -lssl -lz -ldl -llzma -lexif -lopenal -lavformat -lavcodec -lswresample -lavutil -lopus
LIBS += ./../../../Libraries/QtStatic/qtbase/plugins/platforminputcontexts/libcomposeplatforminputcontextplugin.a
LIBS += ./../../../Libraries/QtStatic/qtbase/plugins/platforminputcontexts/libcomposeplatforminputcontextplugin.a \
./../../../Libraries/QtStatic/qtbase/plugins/platforminputcontexts/libibusplatforminputcontextplugin.a \
./../../../Libraries/QtStatic/qtbase/plugins/platforminputcontexts/libfcitxplatforminputcontextplugin.a
LIBS += /usr/local/lib/libxkbcommon.a
RESOURCES += \
./SourceFiles/telegram.qrc \

Binary file not shown.

View File

@@ -54,14 +54,17 @@
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)Intermediate\</IntDir>
<CustomBuildBeforeTargets>
</CustomBuildBeforeTargets>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)Intermediate\</IntDir>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)Intermediate\</IntDir>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -80,7 +83,7 @@
<SubSystem>Windows</SubSystem>
<OutputFile>$(OutDir)$(ProjectName).exe</OutputFile>
<AdditionalLibraryDirectories>.\..\..\Libraries\lzma\C\Util\LzmaLib\Debug;.\..\..\Libraries\libexif-0.6.20\win32\Debug;.\..\..\Libraries\ffmpeg-2.6.3;.\..\..\Libraries\opus\win32\VS2010\Win32\Debug;.\..\..\Libraries\openal-soft\build\Debug;.\..\..\Libraries\zlib-1.2.8\contrib\vstudio\vc11\x86\ZlibStatDebug;.\..\..\Libraries\OpenSSL-Win32\lib\VC\static;$(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;imm32.lib;winmm.lib;qtmaind.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Cored.lib;Qt5Guid.lib;qtharfbuzzngd.lib;qtpcred.lib;qtfreetyped.lib;Qt5Widgetsd.lib;Qt5Networkd.lib;Qt5PlatformSupportd.lib;platforms\qwindowsd.lib;imageformats\qwebpd.lib;libeay32MTd.lib;ssleay32MTd.lib;Crypt32.lib;zlibstat.lib;LzmaLib.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;Shlwapi.lib;Gdiplus.lib;imm32.lib;winmm.lib;qtmaind.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Cored.lib;Qt5Guid.lib;qtharfbuzzngd.lib;qtpcred.lib;qtfreetyped.lib;Qt5Widgetsd.lib;Qt5Networkd.lib;Qt5PlatformSupportd.lib;platforms\qwindowsd.lib;imageformats\qwebpd.lib;libeay32MTd.lib;ssleay32MTd.lib;Crypt32.lib;zlibstat.lib;LzmaLib.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ImageHasSafeExceptionHandlers />
<IgnoreSpecificDefaultLibraries>LIBCMT</IgnoreSpecificDefaultLibraries>
@@ -108,7 +111,7 @@
<SubSystem>Windows</SubSystem>
<OutputFile>$(OutDir)$(ProjectName).exe</OutputFile>
<AdditionalLibraryDirectories>.\..\..\Libraries\lzma\C\Util\LzmaLib\Release;.\..\..\Libraries\libexif-0.6.20\win32\Release;.\..\..\Libraries\ffmpeg-2.6.3;.\..\..\Libraries\opus\win32\VS2010\Win32\Release;.\..\..\Libraries\openal-soft\build\Release;.\..\..\Libraries\zlib-1.2.8\contrib\vstudio\vc11\x86\ZlibStatRelease;.\..\..\Libraries\OpenSSL-Win32\lib\VC\static;$(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;qtpcre.lib;qtfreetype.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32MT.lib;ssleay32MT.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;Shlwapi.lib;Gdiplus.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;qtpcre.lib;qtfreetype.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32MT.lib;ssleay32MT.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ImageHasSafeExceptionHandlers />
<ImportLibrary>$(SolutionDir)$(Platform)\$(Configuration)Intermediate\$(TargetName).lib</ImportLibrary>
<ProfileGuidedDatabase>$(IntDir)$(TargetName).pgd</ProfileGuidedDatabase>
@@ -130,12 +133,13 @@
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<AdditionalOptions>/Zm110 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<OutputFile>$(OutDir)$(ProjectName).exe</OutputFile>
<AdditionalLibraryDirectories>.\..\..\Libraries\lzma\C\Util\LzmaLib\Release;.\..\..\Libraries\libexif-0.6.20\win32\Release;.\..\..\Libraries\ffmpeg-2.6.3;.\..\..\Libraries\opus\win32\VS2010\Win32\Release;.\..\..\Libraries\openal-soft\build\Release;.\..\..\Libraries\zlib-1.2.8\contrib\vstudio\vc11\x86\ZlibStatRelease;.\..\..\Libraries\OpenSSL-Win32\lib\VC\static;$(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;qtpcre.lib;qtfreetype.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32MT.lib;ssleay32MT.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;Shlwapi.lib;Gdiplus.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;qtpcre.lib;qtfreetype.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32MT.lib;ssleay32MT.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ImageHasSafeExceptionHandlers>
</ImageHasSafeExceptionHandlers>
<ImportLibrary>$(SolutionDir)$(Platform)\$(Configuration)Intermediate\$(TargetName).lib</ImportLibrary>

View File

@@ -1707,7 +1707,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 0.8.43;
CURRENT_PROJECT_VERSION = 0.8.50;
DEBUG_INFORMATION_FORMAT = dwarf;
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
@@ -1725,7 +1725,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COPY_PHASE_STRIP = YES;
CURRENT_PROJECT_VERSION = 0.8.43;
CURRENT_PROJECT_VERSION = 0.8.50;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_OPTIMIZATION_LEVEL = fast;
GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h;
@@ -1751,10 +1751,10 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 0.8.43;
CURRENT_PROJECT_VERSION = 0.8.50;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_COMPATIBILITY_VERSION = 0.8;
DYLIB_CURRENT_VERSION = 0.8.43;
DYLIB_CURRENT_VERSION = 0.8.50;
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = "";
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
@@ -1885,10 +1885,10 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 0.8.43;
CURRENT_PROJECT_VERSION = 0.8.50;
DEBUG_INFORMATION_FORMAT = dwarf;
DYLIB_COMPATIBILITY_VERSION = 0.8;
DYLIB_CURRENT_VERSION = 0.8.43;
DYLIB_CURRENT_VERSION = 0.8.50;
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = "";
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;

View File

@@ -1,2 +1,2 @@
echo 0.8 8043 0.8.43 0
echo 0.8 8050 0.8.50 1
# AppVersionStrMajor AppVersion AppVersionStr DevChannel

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,29 @@
TARGET = composeplatforminputcontextplugin
PLUGIN_TYPE = platforminputcontexts
PLUGIN_EXTENDS = -
PLUGIN_CLASS_NAME = QComposePlatformInputContextPlugin
load(qt_plugin)
QT += gui-private
DEFINES += X11_PREFIX='\\"$$QMAKE_X11_PREFIX\\"'
SOURCES += $$PWD/qcomposeplatforminputcontextmain.cpp \
$$PWD/qcomposeplatforminputcontext.cpp \
$$PWD/generator/qtablegenerator.cpp \
HEADERS += $$PWD/qcomposeplatforminputcontext.h \
$$PWD/generator/qtablegenerator.h \
# libxkbcommon
contains(QT_CONFIG, xkbcommon-qt): {
# dont't need x11 dependency for compose key plugin
QT_CONFIG -= use-xkbcommon-x11support
# include(../../../3rdparty/xkbcommon.pri)
} else {
LIBS += $$QMAKE_LIBS_XKBCOMMON
QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XKBCOMMON
}
OTHER_FILES += $$PWD/compose.json

View File

@@ -0,0 +1,3 @@
{
"Keys": [ "fcitx" ]
}

View File

@@ -0,0 +1,38 @@
TARGET = fcitxplatforminputcontextplugin
PLUGIN_TYPE = platforminputcontexts
PLUGIN_EXTENDS = -
PLUGIN_CLASS_NAME = QFcitxPlatformInputContextPlugin
load(qt_plugin)
QT += dbus gui-private
SOURCES += $$PWD/fcitxqtconnection.cpp \
$$PWD/fcitxqtformattedpreedit.cpp \
$$PWD/fcitxqtinputcontextproxy.cpp \
$$PWD/fcitxqtinputmethoditem.cpp \
$$PWD/fcitxqtinputmethodproxy.cpp \
$$PWD/fcitxqtkeyboardlayout.cpp \
$$PWD/fcitxqtkeyboardproxy.cpp \
$$PWD/keyuni.cpp \
$$PWD/main.cpp \
$$PWD/qfcitxplatforminputcontext.cpp \
$$PWD/utils.cpp
HEADERS += $$PWD/fcitxqtconnection.h \
$$PWD/fcitxqtconnection_p.h \
$$PWD/fcitxqtdbusaddons_export.h \
$$PWD/fcitxqtdbusaddons_version.h \
$$PWD/fcitxqtformattedpreedit.h \
$$PWD/fcitxqtinputcontextproxy.h \
$$PWD/fcitxqtinputmethoditem.h \
$$PWD/fcitxqtinputmethodproxy.h \
$$PWD/fcitxqtkeyboardlayout.h \
$$PWD/fcitxqtkeyboardproxy.h \
$$PWD/keydata.h \
$$PWD/keyserver_x11.h \
$$PWD/keyuni.h \
$$PWD/main.h \
$$PWD/qfcitxplatforminputcontext.h \
$$PWD/utils.h
OTHER_FILES += $$PWD/fcitx.json

View File

@@ -0,0 +1,369 @@
/***************************************************************************
* Copyright (C) 2012~2012 by CSSlayer *
* *
* This program 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 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include "fcitxqtconnection_p.h"
#include <QDBusConnection>
#include <QDBusServiceWatcher>
#include <QDBusReply>
#include <QDBusConnectionInterface>
#include <QDebug>
#include <QFile>
#include <QTimer>
#include <QDir>
#include <signal.h>
#include <errno.h>
// utils function in fcitx-utils and fcitx-config
bool _pid_exists(pid_t pid) {
if (pid <= 0)
return 0;
return !(kill(pid, 0) && (errno == ESRCH));
}
FcitxQtConnection::FcitxQtConnection(QObject* parent): QObject(parent)
,d_ptr(new FcitxQtConnectionPrivate(this))
{
}
void FcitxQtConnection::startConnection()
{
Q_D(FcitxQtConnection);
if (!d->m_initialized) {
d->initialize();
d->createConnection();
}
}
void FcitxQtConnection::endConnection()
{
Q_D(FcitxQtConnection);
d->cleanUp();
d->finalize();
d->m_connectedOnce = false;
}
bool FcitxQtConnection::autoReconnect()
{
Q_D(FcitxQtConnection);
return d->m_autoReconnect;
}
void FcitxQtConnection::setAutoReconnect(bool a)
{
Q_D(FcitxQtConnection);
d->m_autoReconnect = a;
}
QDBusConnection* FcitxQtConnection::connection()
{
Q_D(FcitxQtConnection);
return d->m_connection;
}
const QString& FcitxQtConnection::serviceName()
{
Q_D(FcitxQtConnection);
return d->m_serviceName;
}
bool FcitxQtConnection::isConnected()
{
Q_D(FcitxQtConnection);
return d->isConnected();
}
FcitxQtConnection::~FcitxQtConnection()
{
}
FcitxQtConnectionPrivate::FcitxQtConnectionPrivate(FcitxQtConnection* conn) : QObject(conn)
,q_ptr(conn)
,m_displayNumber(-1)
,m_serviceName(QString("%1-%2").arg("org.fcitx.Fcitx").arg(displayNumber()))
,m_connection(0)
,m_serviceWatcher(new QDBusServiceWatcher(conn))
,m_watcher(new QFileSystemWatcher(this))
,m_autoReconnect(true)
,m_connectedOnce(false)
,m_initialized(false)
{
}
FcitxQtConnectionPrivate::~FcitxQtConnectionPrivate()
{
if (m_connection)
delete m_connection;
}
void FcitxQtConnectionPrivate::initialize() {
m_serviceWatcher->setConnection(QDBusConnection::sessionBus());
m_serviceWatcher->addWatchedService(m_serviceName);
QFileInfo info(socketFile());
QDir dir(info.path());
if (!dir.exists()) {
QDir rt(QDir::root());
rt.mkpath(info.path());
}
m_watcher->addPath(info.path());
if (info.exists()) {
m_watcher->addPath(info.filePath());
}
connect(m_watcher, SIGNAL(fileChanged(QString)), this, SLOT(socketFileChanged()));
connect(m_watcher, SIGNAL(directoryChanged(QString)), this, SLOT(socketFileChanged()));
m_initialized = true;
}
void FcitxQtConnectionPrivate::finalize() {
m_serviceWatcher->removeWatchedService(m_serviceName);
m_watcher->removePaths(m_watcher->files());
m_watcher->removePaths(m_watcher->directories());
m_watcher->disconnect(SIGNAL(fileChanged(QString)));
m_watcher->disconnect(SIGNAL(directoryChanged(QString)));
m_initialized = false;
}
void FcitxQtConnectionPrivate::socketFileChanged() {
QFileInfo info(socketFile());
if (info.exists()) {
if (m_watcher->files().indexOf(info.filePath()) == -1)
m_watcher->addPath(info.filePath());
}
QString addr = address();
if (addr.isNull())
return;
cleanUp();
createConnection();
}
QByteArray FcitxQtConnectionPrivate::localMachineId()
{
#if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0)
return QDBusConnection::localMachineId();
#else
QFile file1("/var/lib/dbus/machine-id");
QFile file2("/etc/machine-id");
QFile* fileToRead = NULL;
if (file1.open(QIODevice::ReadOnly)) {
fileToRead = &file1;
}
else if (file2.open(QIODevice::ReadOnly)) {
fileToRead = &file2;
}
if (fileToRead) {
QByteArray result = fileToRead->readLine(1024);
fileToRead->close();
result = result.trimmed();
if (!result.isEmpty())
return result;
}
return "machine-id";
#endif
}
int FcitxQtConnectionPrivate::displayNumber() {
if (m_displayNumber < 0) {
QByteArray displayNumber("0");
QByteArray display(qgetenv("DISPLAY"));
int pos = display.indexOf(':');
if (pos >= 0) {
++pos;
int pos2 = display.indexOf('.', pos);
if (pos2 > 0) {
displayNumber = display.mid(pos, pos2 - pos);
} else {
displayNumber = display.mid(pos);
}
}
bool ok;
int d = displayNumber.toInt(&ok);
if (ok) {
m_displayNumber = d;
} else {
m_displayNumber = 0;
}
}
return m_displayNumber;
}
const QString& FcitxQtConnectionPrivate::socketFile()
{
if (!m_socketFile.isEmpty())
return m_socketFile;
QString filename = QString("%1-%2").arg(QString::fromLatin1(QDBusConnection::localMachineId())).arg(displayNumber());
QString home = QString::fromLocal8Bit(qgetenv("XDG_CONFIG_HOME"));
if (home.isEmpty()) {
home = QDir::homePath().append(QLatin1Literal("/.config"));
}
m_socketFile = QString("%1/fcitx/dbus/%2").arg(home).arg(filename);
return m_socketFile;
}
QString FcitxQtConnectionPrivate::address()
{
QString addr;
QByteArray addrVar = qgetenv("FCITX_DBUS_ADDRESS");
if (!addrVar.isNull())
return QString::fromLocal8Bit(addrVar);
QFile file(socketFile());
if (!file.open(QIODevice::ReadOnly))
return QString();
const int BUFSIZE = 1024;
char buffer[BUFSIZE];
size_t sz = file.read(buffer, BUFSIZE);
file.close();
if (sz == 0)
return QString();
char* p = buffer;
while(*p)
p++;
size_t addrlen = p - buffer;
if (sz != addrlen + 2 * sizeof(pid_t) + 1)
return QString();
/* skip '\0' */
p++;
pid_t *ppid = (pid_t*) p;
pid_t daemonpid = ppid[0];
pid_t fcitxpid = ppid[1];
if (!_pid_exists(daemonpid)
|| !_pid_exists(fcitxpid))
return QString();
addr = QLatin1String(buffer);
return addr;
}
void FcitxQtConnectionPrivate::createConnection() {
if (m_connectedOnce && !m_autoReconnect) {
return;
}
m_serviceWatcher->disconnect(SIGNAL(serviceOwnerChanged(QString,QString,QString)));
QString addr = address();
if (!addr.isNull()) {
QDBusConnection connection(QDBusConnection::connectToBus(addr, "fcitx"));
if (connection.isConnected()) {
// qDebug() << "create private";
m_connection = new QDBusConnection(connection);
}
else
QDBusConnection::disconnectFromBus("fcitx");
}
if (!m_connection) {
QDBusConnection* connection = new QDBusConnection(QDBusConnection::sessionBus());
connect(m_serviceWatcher, SIGNAL(serviceOwnerChanged(QString,QString,QString)), this, SLOT(imChanged(QString,QString,QString)));
QDBusReply<bool> registered = connection->interface()->isServiceRegistered(m_serviceName);
if (!registered.isValid() || !registered.value()) {
delete connection;
}
else {
m_connection = connection;
}
}
Q_Q(FcitxQtConnection);
if (m_connection) {
m_connection->connect ("org.freedesktop.DBus.Local",
"/org/freedesktop/DBus/Local",
"org.freedesktop.DBus.Local",
"Disconnected",
this,
SLOT (dbusDisconnected ()));
m_connectedOnce = true;
emit q->connected();
}
}
void FcitxQtConnectionPrivate::dbusDisconnected()
{
cleanUp();
createConnection();
}
void FcitxQtConnectionPrivate::imChanged(const QString& service, const QString& oldowner, const QString& newowner)
{
if (service == m_serviceName) {
/* old die */
if (oldowner.length() > 0 || newowner.length() > 0)
cleanUp();
/* new rise */
if (newowner.length() > 0) {
QTimer::singleShot(100, this, SLOT(newServiceAppear()));
}
}
}
void FcitxQtConnectionPrivate::cleanUp()
{
Q_Q(FcitxQtConnection);
bool doemit = false;
QDBusConnection::disconnectFromBus("fcitx");
if (m_connection) {
delete m_connection;
m_connection = 0;
doemit = true;
}
if (!m_autoReconnect && m_connectedOnce)
finalize();
/* we want m_connection and finalize being called before the signal
* thus isConnected will return false in slot
* and startConnection can be called in slot
*/
if (doemit)
emit q->disconnected();
}
bool FcitxQtConnectionPrivate::isConnected()
{
return m_connection && m_connection->isConnected();
}
void FcitxQtConnectionPrivate::newServiceAppear() {
if (!isConnected()) {
cleanUp();
createConnection();
}
}

View File

@@ -0,0 +1,111 @@
/***************************************************************************
* Copyright (C) 2012~2012 by CSSlayer *
* *
* This program 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 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef FCITXQTCONNECTION_H
#define FCITXQTCONNECTION_H
#include "fcitxqtdbusaddons_export.h"
#include <QtCore/QObject>
class QDBusConnection;
class FcitxQtConnectionPrivate;
/**
* dbus connection to fcitx
**/
class FCITXQTDBUSADDONS_EXPORT FcitxQtConnection : public QObject {
Q_OBJECT
Q_PROPERTY(bool autoReconnect READ autoReconnect WRITE setAutoReconnect)
Q_PROPERTY(bool connected READ isConnected)
Q_PROPERTY(QDBusConnection* connection READ connection)
Q_PROPERTY(QString serviceName READ serviceName)
public:
/**
* create a new connection
*
* @param parent
**/
explicit FcitxQtConnection(QObject* parent = 0);
/**
* destroy the connection
**/
virtual ~FcitxQtConnection();
/**
* the connection will not start to work until you call this function
* you may want to connect to the signal before you call this function
**/
void startConnection();
void endConnection();
/**
* automatically reconnect if fcitx disappeared
*
* @param a ...
* @return void
**/
void setAutoReconnect(bool a);
/**
* check this connection is doing automatical reconnect or not
*
* default value is true
**/
bool autoReconnect();
/**
* return the current dbus connection to fcitx, notice, the object return
* by this function might be deteled if fcitx disappear, or might return 0
* if fcitx is not running
*
* @return QDBusConnection*
**/
QDBusConnection* connection();
/**
* current fcitx dbus service name, can be used for create DBus proxy
*
* @return service name
**/
const QString& serviceName();
/**
* check its connected or not
**/
bool isConnected();
Q_SIGNALS:
/**
* this signal will be emitted upon fcitx appears
**/
void connected();
/**
* this signal will be emitted upon fcitx disappears
*
* it will come with connected in pair
**/
void disconnected();
private:
FcitxQtConnectionPrivate * const d_ptr;
Q_DECLARE_PRIVATE(FcitxQtConnection);
};
#endif // FCITXCONNECTION_H

View File

@@ -0,0 +1,68 @@
/***************************************************************************
* Copyright (C) 2012~2012 by CSSlayer *
* *
* This program 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 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef FCITXQTCONNECTION_P_H
#define FCITXQTCONNECTION_P_H
#include "fcitxqtconnection.h"
#include <QtCore/QWeakPointer>
#include <QtCore/QFileSystemWatcher>
class QDBusConnection;
class QDBusServiceWatcher;
class FcitxQtConnectionPrivate : public QObject {
Q_OBJECT
public:
FcitxQtConnectionPrivate(FcitxQtConnection* conn);
virtual ~FcitxQtConnectionPrivate();
FcitxQtConnection * const q_ptr;
Q_DECLARE_PUBLIC(FcitxQtConnection);
private Q_SLOTS:
void imChanged(const QString& service, const QString& oldowner, const QString& newowner);
void dbusDisconnected();
void cleanUp();
void newServiceAppear();
void socketFileChanged();
private:
bool isConnected();
static QByteArray localMachineId();
const QString& socketFile();
void createConnection();
QString address();
int displayNumber();
void initialize();
void finalize();
int m_displayNumber;
QString m_serviceName;
QDBusConnection* m_connection;
QDBusServiceWatcher* m_serviceWatcher;
QFileSystemWatcher* m_watcher;
QString m_socketFile;
bool m_autoReconnect;
bool m_connectedOnce;
bool m_initialized;
};
#endif // FCITXCONNECTION_P_H

View File

@@ -0,0 +1,41 @@
#ifndef FCITXQTDBUSADDONS_EXPORT_H
#define FCITXQTDBUSADDONS_EXPORT_H
#ifdef FCITXQTDBUSADDONS_STATIC_DEFINE
# define FCITXQTDBUSADDONS_EXPORT
# define FCITXQTDBUSADDONS_NO_EXPORT
#else
# ifndef FCITXQTDBUSADDONS_EXPORT
# ifdef FcitxQt5DBusAddons_EXPORTS
/* We are building this library */
# define FCITXQTDBUSADDONS_EXPORT __attribute__((visibility("default")))
# else
/* We are using this library */
# define FCITXQTDBUSADDONS_EXPORT __attribute__((visibility("default")))
# endif
# endif
# ifndef FCITXQTDBUSADDONS_NO_EXPORT
# define FCITXQTDBUSADDONS_NO_EXPORT __attribute__((visibility("hidden")))
# endif
#endif
#ifndef FCITXQTDBUSADDONS_DEPRECATED
# define FCITXQTDBUSADDONS_DEPRECATED __attribute__ ((__deprecated__))
#endif
#ifndef FCITXQTDBUSADDONS_DEPRECATED_EXPORT
# define FCITXQTDBUSADDONS_DEPRECATED_EXPORT FCITXQTDBUSADDONS_EXPORT FCITXQTDBUSADDONS_DEPRECATED
#endif
#ifndef FCITXQTDBUSADDONS_DEPRECATED_NO_EXPORT
# define FCITXQTDBUSADDONS_DEPRECATED_NO_EXPORT FCITXQTDBUSADDONS_NO_EXPORT FCITXQTDBUSADDONS_DEPRECATED
#endif
#define DEFINE_NO_DEPRECATED 0
#if DEFINE_NO_DEPRECATED
# define FCITXQTDBUSADDONS_NO_DEPRECATED
#endif
#endif

View File

@@ -0,0 +1,11 @@
#ifndef FCITXQT5DBUSADDONS_VERSION_H
#define FCITXQT5DBUSADDONS_VERSION_H
#define FCITXQT5DBUSADDONS_VERSION_STRING "1.0.0"
#define FCITXQT5DBUSADDONS_VERSION_MAJOR 1
#define FCITXQT5DBUSADDONS_VERSION_MINOR 0
#define FCITXQT5DBUSADDONS_VERSION_PATCH 0
#define FCITXQT5DBUSADDONS_VERSION ((1<<16)|(0<<8)|(0))
#endif

View File

@@ -0,0 +1,78 @@
/***************************************************************************
* Copyright (C) 2012~2012 by CSSlayer *
* *
* This program 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 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include <QDBusMetaType>
#include "fcitxqtformattedpreedit.h"
void FcitxQtFormattedPreedit::registerMetaType()
{
qRegisterMetaType<FcitxQtFormattedPreedit>("FcitxQtFormattedPreedit");
qDBusRegisterMetaType<FcitxQtFormattedPreedit>();
qRegisterMetaType<FcitxQtFormattedPreeditList>("FcitxQtFormattedPreeditList");
qDBusRegisterMetaType<FcitxQtFormattedPreeditList>();
}
qint32 FcitxQtFormattedPreedit::format() const
{
return m_format;
}
const QString& FcitxQtFormattedPreedit::string() const
{
return m_string;
}
void FcitxQtFormattedPreedit::setFormat(qint32 format)
{
m_format = format;
}
void FcitxQtFormattedPreedit::setString(const QString& str)
{
m_string = str;
}
bool FcitxQtFormattedPreedit::operator==(const FcitxQtFormattedPreedit& preedit) const
{
return (preedit.m_format == m_format) && (preedit.m_string == m_string);
}
FCITXQTDBUSADDONS_EXPORT
QDBusArgument& operator<<(QDBusArgument& argument, const FcitxQtFormattedPreedit& preedit)
{
argument.beginStructure();
argument << preedit.string();
argument << preedit.format();
argument.endStructure();
return argument;
}
FCITXQTDBUSADDONS_EXPORT
const QDBusArgument& operator>>(const QDBusArgument& argument, FcitxQtFormattedPreedit& preedit)
{
QString str;
qint32 format;
argument.beginStructure();
argument >> str >> format;
argument.endStructure();
preedit.setString(str);
preedit.setFormat(format);
return argument;
}

View File

@@ -0,0 +1,51 @@
/***************************************************************************
* Copyright (C) 2012~2012 by CSSlayer *
* *
* This program 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 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef FCITX_QT_FORMATTED_PREEDIT_H
#define FCITX_QT_FORMATTED_PREEDIT_H
#include "fcitxqtdbusaddons_export.h"
#include <QtCore/QMetaType>
#include <QtDBus/QDBusArgument>
class FCITXQTDBUSADDONS_EXPORT FcitxQtFormattedPreedit {
public:
const QString& string() const;
qint32 format() const;
void setString(const QString& str);
void setFormat(qint32 format);
static void registerMetaType();
bool operator ==(const FcitxQtFormattedPreedit& preedit) const;
private:
QString m_string;
qint32 m_format;
};
typedef QList<FcitxQtFormattedPreedit> FcitxQtFormattedPreeditList;
QDBusArgument& operator<<(QDBusArgument& argument, const FcitxQtFormattedPreedit& im);
const QDBusArgument& operator>>(const QDBusArgument& argument, FcitxQtFormattedPreedit& im);
Q_DECLARE_METATYPE(FcitxQtFormattedPreedit)
Q_DECLARE_METATYPE(FcitxQtFormattedPreeditList)
#endif

View File

@@ -0,0 +1,26 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p fcitxqtinputcontextproxy -c FcitxQtInputContextProxy interfaces/org.fcitx.Fcitx.InputContext.xml -i fcitxqtformattedpreedit.h -i fcitxqt_export.h
*
* qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "fcitxqtinputcontextproxy.h"
/*
* Implementation of interface class FcitxQtInputContextProxy
*/
FcitxQtInputContextProxy::FcitxQtInputContextProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
{
}
FcitxQtInputContextProxy::~FcitxQtInputContextProxy()
{
}

View File

@@ -0,0 +1,136 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p fcitxqtinputcontextproxy -c FcitxQtInputContextProxy interfaces/org.fcitx.Fcitx.InputContext.xml -i fcitxqtformattedpreedit.h -i fcitxqt_export.h
*
* qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef FCITXQTINPUTCONTEXTPROXY_H_1409252990
#define FCITXQTINPUTCONTEXTPROXY_H_1409252990
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtDBus/QtDBus>
#include "fcitxqtformattedpreedit.h"
#include "fcitxqtdbusaddons_export.h"
/*
* Proxy class for interface org.fcitx.Fcitx.InputContext
*/
class FCITXQTDBUSADDONS_EXPORT FcitxQtInputContextProxy: public QDBusAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "org.fcitx.Fcitx.InputContext"; }
public:
FcitxQtInputContextProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
~FcitxQtInputContextProxy();
public Q_SLOTS: // METHODS
inline QDBusPendingReply<> CloseIC()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("CloseIC"), argumentList);
}
inline QDBusPendingReply<> DestroyIC()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("DestroyIC"), argumentList);
}
inline QDBusPendingReply<> EnableIC()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("EnableIC"), argumentList);
}
inline QDBusPendingReply<> FocusIn()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("FocusIn"), argumentList);
}
inline QDBusPendingReply<> FocusOut()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("FocusOut"), argumentList);
}
inline QDBusPendingReply<> MouseEvent(int x)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(x);
return asyncCallWithArgumentList(QLatin1String("MouseEvent"), argumentList);
}
inline QDBusPendingReply<int> ProcessKeyEvent(uint keyval, uint keycode, uint state, int type, uint time)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(keyval) << QVariant::fromValue(keycode) << QVariant::fromValue(state) << QVariant::fromValue(type) << QVariant::fromValue(time);
return asyncCallWithArgumentList(QLatin1String("ProcessKeyEvent"), argumentList);
}
inline QDBusPendingReply<> Reset()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("Reset"), argumentList);
}
inline QDBusPendingReply<> SetCapacity(uint caps)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(caps);
return asyncCallWithArgumentList(QLatin1String("SetCapacity"), argumentList);
}
inline QDBusPendingReply<> SetCursorLocation(int x, int y)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(x) << QVariant::fromValue(y);
return asyncCallWithArgumentList(QLatin1String("SetCursorLocation"), argumentList);
}
inline QDBusPendingReply<> SetCursorRect(int x, int y, int w, int h)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(x) << QVariant::fromValue(y) << QVariant::fromValue(w) << QVariant::fromValue(h);
return asyncCallWithArgumentList(QLatin1String("SetCursorRect"), argumentList);
}
inline QDBusPendingReply<> SetSurroundingText(const QString &text, uint cursor, uint anchor)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(text) << QVariant::fromValue(cursor) << QVariant::fromValue(anchor);
return asyncCallWithArgumentList(QLatin1String("SetSurroundingText"), argumentList);
}
inline QDBusPendingReply<> SetSurroundingTextPosition(uint cursor, uint anchor)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(cursor) << QVariant::fromValue(anchor);
return asyncCallWithArgumentList(QLatin1String("SetSurroundingTextPosition"), argumentList);
}
Q_SIGNALS: // SIGNALS
void CloseIM();
void CommitString(const QString &str);
void DeleteSurroundingText(int offset, uint nchar);
void EnableIM();
void ForwardKey(uint keyval, uint state, int type);
void UpdateClientSideUI(const QString &auxup, const QString &auxdown, const QString &preedit, const QString &candidateword, const QString &imname, int cursorpos);
void UpdateFormattedPreedit(FcitxQtFormattedPreeditList str, int cursorpos);
};
#endif

View File

@@ -0,0 +1,95 @@
/***************************************************************************
* Copyright (C) 2011~2012 by CSSlayer *
* *
* This program 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 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
// Qt
#include <QDBusArgument>
#include <QDBusMetaType>
// self
#include "fcitxqtinputmethoditem.h"
bool FcitxQtInputMethodItem::enabled() const
{
return m_enabled;
}
const QString& FcitxQtInputMethodItem::langCode() const
{
return m_langCode;
}
const QString& FcitxQtInputMethodItem::name() const
{
return m_name;
}
const QString& FcitxQtInputMethodItem::uniqueName() const
{
return m_uniqueName;
}
void FcitxQtInputMethodItem::setEnabled(bool enable)
{
m_enabled = enable;
}
void FcitxQtInputMethodItem::setLangCode(const QString& lang)
{
m_langCode = lang;
}
void FcitxQtInputMethodItem::setName(const QString& name)
{
m_name = name;
}
void FcitxQtInputMethodItem::setUniqueName(const QString& name)
{
m_uniqueName = name;
}
void FcitxQtInputMethodItem::registerMetaType()
{
qRegisterMetaType<FcitxQtInputMethodItem>("FcitxQtInputMethodItem");
qDBusRegisterMetaType<FcitxQtInputMethodItem>();
qRegisterMetaType<FcitxQtInputMethodItemList>("FcitxQtInputMethodItemList");
qDBusRegisterMetaType<FcitxQtInputMethodItemList>();
}
FCITXQTDBUSADDONS_EXPORT
QDBusArgument& operator<<(QDBusArgument& argument, const FcitxQtInputMethodItem& im)
{
argument.beginStructure();
argument << im.name();
argument << im.uniqueName();
argument << im.langCode();
argument << im.enabled();
argument.endStructure();
return argument;
}
FCITXQTDBUSADDONS_EXPORT
const QDBusArgument& operator>>(const QDBusArgument& argument, FcitxQtInputMethodItem& im)
{
QString name;
QString uniqueName;
QString langCode;
bool enabled;
argument.beginStructure();
argument >> name >> uniqueName >> langCode >> enabled;
argument.endStructure();
im.setName(name);
im.setUniqueName(uniqueName);
im.setLangCode(langCode);
im.setEnabled(enabled);
return argument;
}

View File

@@ -0,0 +1,64 @@
/***************************************************************************
* Copyright (C) 2011~2012 by CSSlayer *
* *
* This program 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 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef FCITX_QT_INPUT_METHOD_ITEM_H
#define FCITX_QT_INPUT_METHOD_ITEM_H
#include "fcitxqtdbusaddons_export.h"
// Qt
#include <QtCore/QString>
#include <QtCore/QMetaType>
#include <QtDBus/QDBusArgument>
class FCITXQTDBUSADDONS_EXPORT FcitxQtInputMethodItem
{
public:
const QString& name() const;
const QString& uniqueName() const;
const QString& langCode() const;
bool enabled() const;
void setName(const QString& name);
void setUniqueName(const QString& name);
void setLangCode(const QString& name);
void setEnabled(bool name);
static void registerMetaType();
inline bool operator < (const FcitxQtInputMethodItem& im) const {
if (m_enabled == true && im.m_enabled == false)
return true;
return false;
}
private:
QString m_name;
QString m_uniqueName;
QString m_langCode;
bool m_enabled;
};
typedef QList<FcitxQtInputMethodItem> FcitxQtInputMethodItemList;
QDBusArgument& operator<<(QDBusArgument& argument, const FcitxQtInputMethodItem& im);
const QDBusArgument& operator>>(const QDBusArgument& argument, FcitxQtInputMethodItem& im);
Q_DECLARE_METATYPE(FcitxQtInputMethodItem)
Q_DECLARE_METATYPE(FcitxQtInputMethodItemList)
#endif

View File

@@ -0,0 +1,26 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p fcitxqtinputmethodproxy -c FcitxQtInputMethodProxy interfaces/org.fcitx.Fcitx.InputMethod.xml -i fcitxqtinputmethoditem.h -i fcitxqt_export.h
*
* qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "fcitxqtinputmethodproxy.h"
/*
* Implementation of interface class FcitxQtInputMethodProxy
*/
FcitxQtInputMethodProxy::FcitxQtInputMethodProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
{
}
FcitxQtInputMethodProxy::~FcitxQtInputMethodProxy()
{
}

View File

@@ -0,0 +1,217 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p fcitxqtinputmethodproxy -c FcitxQtInputMethodProxy interfaces/org.fcitx.Fcitx.InputMethod.xml -i fcitxqtinputmethoditem.h -i fcitxqt_export.h
*
* qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef FCITXQTINPUTMETHODPROXY_H_1409252990
#define FCITXQTINPUTMETHODPROXY_H_1409252990
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtDBus/QtDBus>
#include "fcitxqtinputmethoditem.h"
#include "fcitxqtdbusaddons_export.h"
/*
* Proxy class for interface org.fcitx.Fcitx.InputMethod
*/
class FCITXQTDBUSADDONS_EXPORT FcitxQtInputMethodProxy: public QDBusAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "org.fcitx.Fcitx.InputMethod"; }
public:
FcitxQtInputMethodProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
~FcitxQtInputMethodProxy();
Q_PROPERTY(QString CurrentIM READ currentIM WRITE setCurrentIM)
inline QString currentIM() const
{ return qvariant_cast< QString >(property("CurrentIM")); }
inline void setCurrentIM(const QString &value)
{ setProperty("CurrentIM", QVariant::fromValue(value)); }
Q_PROPERTY(FcitxQtInputMethodItemList IMList READ iMList WRITE setIMList)
inline FcitxQtInputMethodItemList iMList() const
{ return qvariant_cast< FcitxQtInputMethodItemList >(property("IMList")); }
inline void setIMList(FcitxQtInputMethodItemList value)
{ setProperty("IMList", QVariant::fromValue(value)); }
public Q_SLOTS: // METHODS
inline QDBusPendingReply<> ActivateIM()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("ActivateIM"), argumentList);
}
inline QDBusPendingReply<> Configure()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("Configure"), argumentList);
}
inline QDBusPendingReply<> ConfigureAddon(const QString &addon)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(addon);
return asyncCallWithArgumentList(QLatin1String("ConfigureAddon"), argumentList);
}
inline QDBusPendingReply<> ConfigureIM(const QString &im)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(im);
return asyncCallWithArgumentList(QLatin1String("ConfigureIM"), argumentList);
}
inline QDBusPendingReply<int, uint, uint, uint, uint> CreateIC()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("CreateIC"), argumentList);
}
inline QDBusReply<int> CreateIC(uint &keyval1, uint &state1, uint &keyval2, uint &state2)
{
QList<QVariant> argumentList;
QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("CreateIC"), argumentList);
if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 5) {
keyval1 = qdbus_cast<uint>(reply.arguments().at(1));
state1 = qdbus_cast<uint>(reply.arguments().at(2));
keyval2 = qdbus_cast<uint>(reply.arguments().at(3));
state2 = qdbus_cast<uint>(reply.arguments().at(4));
}
return reply;
}
inline QDBusPendingReply<int, bool, uint, uint, uint, uint> CreateICv2(const QString &appname)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(appname);
return asyncCallWithArgumentList(QLatin1String("CreateICv2"), argumentList);
}
inline QDBusReply<int> CreateICv2(const QString &appname, bool &enable, uint &keyval1, uint &state1, uint &keyval2, uint &state2)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(appname);
QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("CreateICv2"), argumentList);
if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 6) {
enable = qdbus_cast<bool>(reply.arguments().at(1));
keyval1 = qdbus_cast<uint>(reply.arguments().at(2));
state1 = qdbus_cast<uint>(reply.arguments().at(3));
keyval2 = qdbus_cast<uint>(reply.arguments().at(4));
state2 = qdbus_cast<uint>(reply.arguments().at(5));
}
return reply;
}
inline QDBusPendingReply<int, bool, uint, uint, uint, uint> CreateICv3(const QString &appname, int pid)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(appname) << QVariant::fromValue(pid);
return asyncCallWithArgumentList(QLatin1String("CreateICv3"), argumentList);
}
inline QDBusReply<int> CreateICv3(const QString &appname, int pid, bool &enable, uint &keyval1, uint &state1, uint &keyval2, uint &state2)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(appname) << QVariant::fromValue(pid);
QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("CreateICv3"), argumentList);
if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 6) {
enable = qdbus_cast<bool>(reply.arguments().at(1));
keyval1 = qdbus_cast<uint>(reply.arguments().at(2));
state1 = qdbus_cast<uint>(reply.arguments().at(3));
keyval2 = qdbus_cast<uint>(reply.arguments().at(4));
state2 = qdbus_cast<uint>(reply.arguments().at(5));
}
return reply;
}
inline QDBusPendingReply<> Exit()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("Exit"), argumentList);
}
inline QDBusPendingReply<QString> GetCurrentIM()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("GetCurrentIM"), argumentList);
}
inline QDBusPendingReply<int> GetCurrentState()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("GetCurrentState"), argumentList);
}
inline QDBusPendingReply<QString> GetCurrentUI()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("GetCurrentUI"), argumentList);
}
inline QDBusPendingReply<QString> GetIMAddon(const QString &im)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(im);
return asyncCallWithArgumentList(QLatin1String("GetIMAddon"), argumentList);
}
inline QDBusPendingReply<> InactivateIM()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("InactivateIM"), argumentList);
}
inline QDBusPendingReply<> ReloadAddonConfig(const QString &addon)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(addon);
return asyncCallWithArgumentList(QLatin1String("ReloadAddonConfig"), argumentList);
}
inline QDBusPendingReply<> ReloadConfig()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("ReloadConfig"), argumentList);
}
inline QDBusPendingReply<> ResetIMList()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("ResetIMList"), argumentList);
}
inline QDBusPendingReply<> Restart()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("Restart"), argumentList);
}
inline QDBusPendingReply<> SetCurrentIM(const QString &im)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(im);
return asyncCallWithArgumentList(QLatin1String("SetCurrentIM"), argumentList);
}
inline QDBusPendingReply<> ToggleIM()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("ToggleIM"), argumentList);
}
Q_SIGNALS: // SIGNALS
};
#endif

View File

@@ -0,0 +1,100 @@
/***************************************************************************
* Copyright (C) 2011~2012 by CSSlayer *
* *
* This program 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 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
// Qt
#include <QDBusArgument>
#include <QDBusMetaType>
// self
#include "fcitxqtkeyboardlayout.h"
const QString& FcitxQtKeyboardLayout::layout() const
{
return m_layout;
}
const QString& FcitxQtKeyboardLayout::langCode() const
{
return m_langCode;
}
const QString& FcitxQtKeyboardLayout::name() const
{
return m_name;
}
const QString& FcitxQtKeyboardLayout::variant() const
{
return m_variant;
}
void FcitxQtKeyboardLayout::setLayout(const QString& layout)
{
m_layout = layout;
}
void FcitxQtKeyboardLayout::setLangCode(const QString& lang)
{
m_langCode = lang;
}
void FcitxQtKeyboardLayout::setName(const QString& name)
{
m_name = name;
}
void FcitxQtKeyboardLayout::setVariant(const QString& variant)
{
m_variant = variant;
}
void FcitxQtKeyboardLayout::registerMetaType()
{
qRegisterMetaType<FcitxQtKeyboardLayout>("FcitxQtKeyboardLayout");
qDBusRegisterMetaType<FcitxQtKeyboardLayout>();
qRegisterMetaType<FcitxQtKeyboardLayoutList>("FcitxQtKeyboardLayoutList");
qDBusRegisterMetaType<FcitxQtKeyboardLayoutList>();
}
FCITXQTDBUSADDONS_EXPORT
QDBusArgument& operator<<(QDBusArgument& argument, const FcitxQtKeyboardLayout& layout)
{
argument.beginStructure();
argument << layout.layout();
argument << layout.variant();
argument << layout.name();
argument << layout.langCode();
argument.endStructure();
return argument;
}
FCITXQTDBUSADDONS_EXPORT
const QDBusArgument& operator>>(const QDBusArgument& argument, FcitxQtKeyboardLayout& layout)
{
QString l;
QString variant;
QString name;
QString langCode;
argument.beginStructure();
argument >> l >> variant >> name >> langCode;
argument.endStructure();
layout.setLayout(l);
layout.setVariant(variant);
layout.setName(name);
layout.setLangCode(langCode);
return argument;
}

View File

@@ -0,0 +1,58 @@
/***************************************************************************
* Copyright (C) 2011~2012 by CSSlayer *
* *
* This program 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 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef FCITX_QT_KEYBOARD_LAYOUT_H
#define FCITX_QT_KEYBOARD_LAYOUT_H
#include "fcitxqtdbusaddons_export.h"
// Qt
#include <QtCore/QString>
#include <QtCore/QMetaType>
#include <QtDBus/QDBusArgument>
class FCITXQTDBUSADDONS_EXPORT FcitxQtKeyboardLayout
{
public:
const QString& layout() const;
const QString& variant() const;
const QString& name() const;
const QString& langCode() const;
void setLayout(const QString& layout);
void setLangCode(const QString& lang);
void setName(const QString& name);
void setVariant(const QString& variant);
static void registerMetaType();
private:
QString m_layout;
QString m_variant;
QString m_name;
QString m_langCode;
};
typedef QList<FcitxQtKeyboardLayout> FcitxQtKeyboardLayoutList;
QDBusArgument& operator<<(QDBusArgument& argument, const FcitxQtKeyboardLayout& l);
const QDBusArgument& operator>>(const QDBusArgument& argument, FcitxQtKeyboardLayout& l);
Q_DECLARE_METATYPE(FcitxQtKeyboardLayout)
Q_DECLARE_METATYPE(FcitxQtKeyboardLayoutList)
#endif

View File

@@ -0,0 +1,26 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p fcitxqtkeyboardproxy -c FcitxQtKeyboardProxy interfaces/org.fcitx.Fcitx.Keyboard.xml -i fcitxqtkeyboardlayout.h -i fcitxqt_export.h
*
* qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "fcitxqtkeyboardproxy.h"
/*
* Implementation of interface class FcitxQtKeyboardProxy
*/
FcitxQtKeyboardProxy::FcitxQtKeyboardProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
{
}
FcitxQtKeyboardProxy::~FcitxQtKeyboardProxy()
{
}

View File

@@ -0,0 +1,74 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp -N -p fcitxqtkeyboardproxy -c FcitxQtKeyboardProxy interfaces/org.fcitx.Fcitx.Keyboard.xml -i fcitxqtkeyboardlayout.h -i fcitxqt_export.h
*
* qdbusxml2cpp is Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef FCITXQTKEYBOARDPROXY_H_1409252990
#define FCITXQTKEYBOARDPROXY_H_1409252990
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtDBus/QtDBus>
#include "fcitxqtkeyboardlayout.h"
#include "fcitxqtdbusaddons_export.h"
/*
* Proxy class for interface org.fcitx.Fcitx.Keyboard
*/
class FCITXQTDBUSADDONS_EXPORT FcitxQtKeyboardProxy: public QDBusAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "org.fcitx.Fcitx.Keyboard"; }
public:
FcitxQtKeyboardProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
~FcitxQtKeyboardProxy();
public Q_SLOTS: // METHODS
inline QDBusPendingReply<QString, QString> GetLayoutForIM(const QString &im)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(im);
return asyncCallWithArgumentList(QLatin1String("GetLayoutForIM"), argumentList);
}
inline QDBusReply<QString> GetLayoutForIM(const QString &im, QString &variant)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(im);
QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("GetLayoutForIM"), argumentList);
if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 2) {
variant = qdbus_cast<QString>(reply.arguments().at(1));
}
return reply;
}
inline QDBusPendingReply<FcitxQtKeyboardLayoutList> GetLayouts()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("GetLayouts"), argumentList);
}
inline QDBusPendingReply<> SetLayoutForIM(const QString &im, const QString &layout, const QString &variant)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(im) << QVariant::fromValue(layout) << QVariant::fromValue(variant);
return asyncCallWithArgumentList(QLatin1String("SetLayoutForIM"), argumentList);
}
Q_SIGNALS: // SIGNALS
};
#endif

View File

@@ -0,0 +1,81 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.fcitx.Fcitx.InputContext">
<method name="EnableIC">
</method>
<method name="CloseIC">
</method>
<method name="FocusIn">
</method>
<method name="FocusOut">
</method>
<method name="Reset">
</method>
<method name="MouseEvent">
<arg name="x" direction="in" type="i" />
</method>
<method name="SetCursorLocation">
<arg name="x" direction="in" type="i"/>
<arg name="y" direction="in" type="i"/>
</method>
<method name="SetCursorRect">
<arg name="x" direction="in" type="i"/>
<arg name="y" direction="in" type="i"/>
<arg name="w" direction="in" type="i"/>
<arg name="h" direction="in" type="i"/>
</method>
<method name="SetCapacity">
<arg name="caps" direction="in" type="u"/>
</method>
<method name="SetSurroundingText">
<arg name="text" direction="in" type="s"/>
<arg name="cursor" direction="in" type="u"/>
<arg name="anchor" direction="in" type="u"/>
</method>
<method name="SetSurroundingTextPosition">
<arg name="cursor" direction="in" type="u"/>
<arg name="anchor" direction="in" type="u"/>
</method>
<method name="DestroyIC">
</method>
<method name="ProcessKeyEvent">
<arg name="keyval" direction="in" type="u"/>
<arg name="keycode" direction="in" type="u"/>
<arg name="state" direction="in" type="u"/>
<arg name="type" direction="in" type="i"/>
<arg name="time" direction="in" type="u"/>
<arg name="ret" direction="out" type="i"/>
</method>
<signal name="EnableIM">
</signal>
<signal name="CloseIM">
</signal>
<signal name="CommitString">
<arg name="str" type="s"/>
</signal>
<signal name="UpdateFormattedPreedit">
<arg name="str" type="a(si)" />
<arg name="cursorpos" type="i"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="FcitxQtFormattedPreeditList" />
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="FcitxQtFormattedPreeditList" />
</signal>
<signal name="UpdateClientSideUI">
<arg name="auxup" type="s"/>
<arg name="auxdown" type="s"/>
<arg name="preedit" type="s"/>
<arg name="candidateword" type="s"/>
<arg name="imname" type="s"/>
<arg name="cursorpos" type="i"/>
</signal>
<signal name="ForwardKey">
<arg name="keyval" type="u"/>
<arg name="state" type="u"/>
<arg name="type" type="i"/>
</signal>
<signal name="DeleteSurroundingText">
<arg name="offset" type="i"/>
<arg name="nchar" type="u"/>
</signal>
</interface>
</node>

View File

@@ -0,0 +1,81 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.fcitx.Fcitx.InputMethod">
<method name="CreateIC">
<arg name="icid" direction="out" type="i"/>
<arg name="keyval1" direction="out" type="u"/>
<arg name="state1" direction="out" type="u"/>
<arg name="keyval2" direction="out" type="u"/>
<arg name="state2" direction="out" type="u"/>
</method>
<method name="CreateICv2">
<arg name="appname" direction="in" type="s"/>
<arg name="icid" direction="out" type="i"/>
<arg name="enable" direction="out" type="b"/>
<arg name="keyval1" direction="out" type="u"/>
<arg name="state1" direction="out" type="u"/>
<arg name="keyval2" direction="out" type="u"/>
<arg name="state2" direction="out" type="u"/>
</method>
<method name="CreateICv3">
<arg name="appname" direction="in" type="s"/>
<arg name="pid" direction="in" type="i"/>
<arg name="icid" direction="out" type="i"/>
<arg name="enable" direction="out" type="b"/>
<arg name="keyval1" direction="out" type="u"/>
<arg name="state1" direction="out" type="u"/>
<arg name="keyval2" direction="out" type="u"/>
<arg name="state2" direction="out" type="u"/>
</method>
<method name="Exit">
</method>
<method name="GetCurrentIM">
<arg name="im" direction="out" type="s"/>
</method>
<method name="SetCurrentIM">
<arg name="im" direction="in" type="s"/>
</method>
<method name="ReloadConfig">
</method>
<method name="ReloadAddonConfig">
<arg name="addon" direction="in" type="s"/>
</method>
<method name="Restart">
</method>
<method name="Configure">
</method>
<method name="ConfigureAddon">
<arg name="addon" direction="in" type="s"/>
</method>
<method name="ConfigureIM">
<arg name="im" direction="in" type="s"/>
</method>
<method name="GetCurrentUI">
<arg name="addon" direction="out" type="s"/>
</method>
<method name="GetIMAddon">
<arg name="im" direction="in" type="s"/>
<arg name="addon" direction="out" type="s"/>
</method>
<method name="ActivateIM">
</method>
<method name="InactivateIM">
</method>
<method name="ToggleIM">
</method>
<method name="ResetIMList">
</method>
<method name="GetCurrentState">
<arg name="state" direction="out" type="i"/>
</method>
<property access="readwrite" type="a(sssb)" name="IMList">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
<annotation name="com.trolltech.QtDBus.QtTypeName" value="FcitxQtInputMethodItemList" />
<annotation name="org.qtproject.QtDBus.QtTypeName" value="FcitxQtInputMethodItemList" />
</property>
<property access="readwrite" type="s" name="CurrentIM">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
</property>
</interface>
</node>

View File

@@ -0,0 +1,20 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.fcitx.Fcitx.Keyboard">
<method name="GetLayouts">
<arg name="layouts" direction="out" type="a(ssss)"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="FcitxQtKeyboardLayoutList" />
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="FcitxQtKeyboardLayoutList" />
</method>
<method name="GetLayoutForIM">
<arg name="im" direction="in" type="s"/>
<arg name="layout" direction="out" type="s"/>
<arg name="variant" direction="out" type="s"/>
</method>
<method name="SetLayoutForIM">
<arg name="im" direction="in" type="s"/>
<arg name="layout" direction="in" type="s"/>
<arg name="variant" direction="in" type="s"/>
</method>
</interface>
</node>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,173 @@
/*
Copyright (C) 2001 Ellis Whitehead <ellis@kde.org>
Win32 port:
Copyright (C) 2004 Jaroslaw Staniek <js@iidea.pl>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KEYSERVER_X11_H
#define KEYSERVER_X11_H
#include <X11/keysym.h>
struct TransKey {
int keySymQt;
uint keySymX;
};
static const TransKey g_rgQtToSymX[] = {
{ Qt::Key_Escape, XK_Escape },
{ Qt::Key_Tab, XK_Tab },
{ Qt::Key_Backtab, XK_ISO_Left_Tab },
{ Qt::Key_Backspace, XK_BackSpace },
{ Qt::Key_Return, XK_Return },
{ Qt::Key_Enter, XK_KP_Enter },
{ Qt::Key_Insert, XK_Insert },
{ Qt::Key_Delete, XK_Delete },
{ Qt::Key_Pause, XK_Pause },
#ifdef sun
{ Qt::Key_Print, XK_F22 },
#else
{ Qt::Key_Print, XK_Print },
#endif
{ Qt::Key_SysReq, XK_Sys_Req },
{ Qt::Key_Home, XK_Home },
{ Qt::Key_End, XK_End },
{ Qt::Key_Left, XK_Left },
{ Qt::Key_Up, XK_Up },
{ Qt::Key_Right, XK_Right },
{ Qt::Key_Down, XK_Down },
//{ Qt::Key_Shift, 0 },
//{ Qt::Key_Control, 0 },
//{ Qt::Key_Meta, 0 },
//{ Qt::Key_Alt, 0 },
{ Qt::Key_CapsLock, XK_Caps_Lock },
{ Qt::Key_NumLock, XK_Num_Lock },
{ Qt::Key_ScrollLock, XK_Scroll_Lock },
{ Qt::Key_F1, XK_F1 },
{ Qt::Key_F2, XK_F2 },
{ Qt::Key_F3, XK_F3 },
{ Qt::Key_F4, XK_F4 },
{ Qt::Key_F5, XK_F5 },
{ Qt::Key_F6, XK_F6 },
{ Qt::Key_F7, XK_F7 },
{ Qt::Key_F8, XK_F8 },
{ Qt::Key_F9, XK_F9 },
{ Qt::Key_F10, XK_F10 },
{ Qt::Key_F11, XK_F11 },
{ Qt::Key_F12, XK_F12 },
{ Qt::Key_F13, XK_F13 },
{ Qt::Key_F14, XK_F14 },
{ Qt::Key_F15, XK_F15 },
{ Qt::Key_F16, XK_F16 },
{ Qt::Key_F17, XK_F17 },
{ Qt::Key_F18, XK_F18 },
{ Qt::Key_F19, XK_F19 },
{ Qt::Key_F20, XK_F20 },
{ Qt::Key_F21, XK_F21 },
{ Qt::Key_F22, XK_F22 },
{ Qt::Key_F23, XK_F23 },
{ Qt::Key_F24, XK_F24 },
{ Qt::Key_F25, XK_F25 },
{ Qt::Key_F26, XK_F26 },
{ Qt::Key_F27, XK_F27 },
{ Qt::Key_F28, XK_F28 },
{ Qt::Key_F29, XK_F29 },
{ Qt::Key_F30, XK_F30 },
{ Qt::Key_F31, XK_F31 },
{ Qt::Key_F32, XK_F32 },
{ Qt::Key_F33, XK_F33 },
{ Qt::Key_F34, XK_F34 },
{ Qt::Key_F35, XK_F35 },
{ Qt::Key_Super_L, XK_Super_L },
{ Qt::Key_Super_R, XK_Super_R },
{ Qt::Key_Menu, XK_Menu },
{ Qt::Key_Hyper_L, XK_Hyper_L },
{ Qt::Key_Hyper_R, XK_Hyper_R },
{ Qt::Key_Help, XK_Help },
{ '/', XK_KP_Divide },
{ '*', XK_KP_Multiply },
{ '-', XK_KP_Subtract },
{ '+', XK_KP_Add },
{ Qt::Key_Return, XK_KP_Enter },
{Qt::Key_Multi_key, XK_Multi_key},
{Qt::Key_Codeinput, XK_Codeinput},
{Qt::Key_SingleCandidate, XK_SingleCandidate},
{Qt::Key_MultipleCandidate, XK_MultipleCandidate},
{Qt::Key_PreviousCandidate, XK_PreviousCandidate},
{Qt::Key_Mode_switch, XK_Mode_switch},
{Qt::Key_Kanji, XK_Kanji},
{Qt::Key_Muhenkan, XK_Muhenkan},
{Qt::Key_Henkan, XK_Henkan},
{Qt::Key_Romaji, XK_Romaji},
{Qt::Key_Hiragana, XK_Hiragana},
{Qt::Key_Katakana, XK_Katakana},
{Qt::Key_Hiragana_Katakana, XK_Hiragana_Katakana},
{Qt::Key_Zenkaku, XK_Zenkaku},
{Qt::Key_Hankaku, XK_Hankaku},
{Qt::Key_Zenkaku_Hankaku, XK_Zenkaku_Hankaku},
{Qt::Key_Touroku, XK_Touroku},
{Qt::Key_Massyo, XK_Massyo},
{Qt::Key_Kana_Lock, XK_Kana_Lock},
{Qt::Key_Kana_Shift, XK_Kana_Shift},
{Qt::Key_Eisu_Shift, XK_Eisu_Shift},
{Qt::Key_Eisu_toggle, XK_Eisu_toggle},
{Qt::Key_Hangul, XK_Hangul},
{Qt::Key_Hangul_Start, XK_Hangul_Start},
{Qt::Key_Hangul_End, XK_Hangul_End},
{Qt::Key_Hangul_Hanja, XK_Hangul_Hanja},
{Qt::Key_Hangul_Jamo, XK_Hangul_Jamo},
{Qt::Key_Hangul_Romaja, XK_Hangul_Romaja},
{Qt::Key_Hangul_Jeonja, XK_Hangul_Jeonja},
{Qt::Key_Hangul_Banja, XK_Hangul_Banja},
{Qt::Key_Hangul_PreHanja, XK_Hangul_PreHanja},
{Qt::Key_Hangul_PostHanja, XK_Hangul_PostHanja},
{Qt::Key_Hangul_Special, XK_Hangul_Special},
};
#include <qstring.h>
inline int map_sym_to_qt(uint keySym)
{
if (keySym < 0x1000) {
if (keySym >= 'a' && keySym <= 'z')
return QChar(keySym).toUpper().unicode();
return keySym;
}
#ifdef Q_WS_WIN
if (keySym < 0x3000)
return keySym;
#else
if (keySym < 0x3000)
return keySym | Qt::UNICODE_ACCEL;
for (uint i = 0; i < sizeof(g_rgQtToSymX) / sizeof(TransKey); i++)
if (g_rgQtToSymX[i].keySymX == keySym)
return g_rgQtToSymX[i].keySymQt;
#endif
return Qt::Key_unknown;
}
static bool symToKeyQt(uint keySym, int& keyQt)
{
keyQt = map_sym_to_qt(keySym);
return (keyQt != Qt::Key_unknown);
}
#endif

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