Merge branch 'dev' into player
Conflicts: Telegram/SourceFiles/application.cpp Telegram/SourceFiles/core/utils.h Telegram/SourceFiles/localstorage.cpp Telegram/SourceFiles/pspecific_mac_p.mm
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 89 KiB |
|
@ -68,7 +68,7 @@ semiboldButtonBlueText: #2b99d5;
|
||||||
wndMinHeight: 480px;
|
wndMinHeight: 480px;
|
||||||
wndDefWidth: 800px;
|
wndDefWidth: 800px;
|
||||||
wndDefHeight: 600px;
|
wndDefHeight: 600px;
|
||||||
wndShadow: sprite(209px, 46px, 19px, 19px);
|
wndShadow: icon {{ "window_shadow", windowShadowFg }};
|
||||||
wndShadowShift: 1px;
|
wndShadowShift: 1px;
|
||||||
|
|
||||||
layerAlpha: 0.5;
|
layerAlpha: 0.5;
|
||||||
|
@ -298,10 +298,11 @@ solidScroll: flatScroll {
|
||||||
duration: 150;
|
duration: 150;
|
||||||
hiding: 0;
|
hiding: 0;
|
||||||
}
|
}
|
||||||
|
defaultDropdownShadow: icon {{ "dropdown_shadow", windowShadowFg }};
|
||||||
defaultPopupMenu: PopupMenu {
|
defaultPopupMenu: PopupMenu {
|
||||||
skip: 5px;
|
skip: 5px;
|
||||||
|
|
||||||
shadow: sprite(241px, 46px, 6px, 6px);
|
shadow: defaultDropdownShadow;
|
||||||
shadowShift: 1px;
|
shadowShift: 1px;
|
||||||
|
|
||||||
itemBg: white;
|
itemBg: white;
|
||||||
|
@ -320,7 +321,7 @@ defaultPopupMenu: PopupMenu {
|
||||||
separatorWidth: 1px;
|
separatorWidth: 1px;
|
||||||
separatorFg: #f1f1f1;
|
separatorFg: #f1f1f1;
|
||||||
|
|
||||||
arrow: sprite(0px, 126px, 4px, 7px);
|
arrow: icon {{ "dropdown_submenu_arrow", #373737 }};
|
||||||
|
|
||||||
duration: 120;
|
duration: 120;
|
||||||
|
|
||||||
|
@ -689,7 +690,7 @@ btnIntroNext: flatButton(btnDefNext, btnDefBig) {
|
||||||
radius: buttonRadius;
|
radius: buttonRadius;
|
||||||
}
|
}
|
||||||
|
|
||||||
boxShadow: sprite(363px, 50px, 15px, 15px);
|
boxShadow: icon {{ "box_shadow", windowShadowFg }};
|
||||||
boxShadowShift: 2px;
|
boxShadowShift: 2px;
|
||||||
|
|
||||||
introCountry: countryInput {
|
introCountry: countryInput {
|
||||||
|
@ -1213,12 +1214,12 @@ btnBotKbHide: iconedButton(btnAttachEmoji) {
|
||||||
downIcon: sprite(373px, 95px, 23px, 14px);
|
downIcon: sprite(373px, 95px, 23px, 14px);
|
||||||
downIconPos: point(5px, 17px);
|
downIconPos: point(5px, 17px);
|
||||||
}
|
}
|
||||||
broadcastToggle: flatCheckbox {
|
silentToggle: flatCheckbox {
|
||||||
textColor: black;
|
textColor: black;
|
||||||
bgColor: white;
|
bgColor: white;
|
||||||
disColor: black;
|
disColor: black;
|
||||||
|
|
||||||
width: 34px;
|
width: 33px;
|
||||||
height: 46px;
|
height: 46px;
|
||||||
duration: 200;
|
duration: 200;
|
||||||
bgFunc: transition(easeOutCirc);
|
bgFunc: transition(easeOutCirc);
|
||||||
|
@ -1226,24 +1227,14 @@ broadcastToggle: flatCheckbox {
|
||||||
|
|
||||||
font: normalFont;
|
font: normalFont;
|
||||||
|
|
||||||
imageRect: sprite(18px, 125px, 22px, 21px);
|
|
||||||
chkImageRect: sprite(40px, 125px, 22px, 21px);
|
|
||||||
overImageRect: sprite(40px, 104px, 22px, 21px);
|
|
||||||
chkOverImageRect: sprite(40px, 125px, 22px, 21px);
|
|
||||||
disImageRect: sprite(18px, 125px, 22px, 21px);
|
|
||||||
chkDisImageRect: sprite(18px, 125px, 22px, 21px);
|
|
||||||
|
|
||||||
imagePos: point(6px, 12px);
|
|
||||||
}
|
|
||||||
silentToggle: flatCheckbox(broadcastToggle) {
|
|
||||||
width: 33px;
|
|
||||||
|
|
||||||
imageRect: sprite(354px, 242px, 21px, 21px);
|
imageRect: sprite(354px, 242px, 21px, 21px);
|
||||||
chkImageRect: sprite(354px, 221px, 21px, 21px);
|
chkImageRect: sprite(354px, 221px, 21px, 21px);
|
||||||
overImageRect: sprite(375px, 242px, 21px, 21px);
|
overImageRect: sprite(375px, 242px, 21px, 21px);
|
||||||
chkOverImageRect: sprite(375px, 221px, 21px, 21px);
|
chkOverImageRect: sprite(375px, 221px, 21px, 21px);
|
||||||
disImageRect: sprite(354px, 242px, 21px, 21px);
|
disImageRect: sprite(354px, 242px, 21px, 21px);
|
||||||
chkDisImageRect: sprite(354px, 221px, 21px, 21px);
|
chkDisImageRect: sprite(354px, 221px, 21px, 21px);
|
||||||
|
|
||||||
|
imagePos: point(6px, 12px);
|
||||||
}
|
}
|
||||||
btnRecordAudio: sprite(379px, 390px, 16px, 24px);
|
btnRecordAudio: sprite(379px, 390px, 16px, 24px);
|
||||||
btnRecordAudioActive: sprite(379px, 366px, 16px, 24px);
|
btnRecordAudioActive: sprite(379px, 366px, 16px, 24px);
|
||||||
|
@ -1411,15 +1402,7 @@ btnCancelSearch: iconedButton(btnAddContact) {
|
||||||
downIcon: sprite(188px, 43px, 18px, 18px);
|
downIcon: sprite(188px, 43px, 18px, 18px);
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyBG: white;
|
simpleClose: iconedButton(btnDefIconed) {
|
||||||
notifyBorder: #f1f1f1;
|
|
||||||
notifyBorderWidth: 1px;
|
|
||||||
notifySlowHide: 4000;
|
|
||||||
notifyPhotoSize: 62px;
|
|
||||||
notifyMacPhotoSize: 64px;
|
|
||||||
notifyPhotoPos: point(9px, 9px);
|
|
||||||
notifyClosePos: point(1px, 2px);
|
|
||||||
notifyClose: iconedButton(btnDefIconed) {
|
|
||||||
icon: sprite(167px, 130px, 10px, 10px);
|
icon: sprite(167px, 130px, 10px, 10px);
|
||||||
iconPos: point(10px, 10px);
|
iconPos: point(10px, 10px);
|
||||||
downIcon: sprite(167px, 130px, 10px, 10px);
|
downIcon: sprite(167px, 130px, 10px, 10px);
|
||||||
|
@ -1428,17 +1411,6 @@ notifyClose: iconedButton(btnDefIconed) {
|
||||||
width: 30px;
|
width: 30px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
}
|
}
|
||||||
notifyItemTop: 12px;
|
|
||||||
notifyTextLeft: 12px;
|
|
||||||
notifyTextTop: 7px;
|
|
||||||
notifySlowHideFunc: transition(easeInCirc);
|
|
||||||
notifyWaitShortHide: 0;
|
|
||||||
notifyWaitLongHide: 20000;
|
|
||||||
notifyFastAnim: 150;
|
|
||||||
notifyWidth: 316px;
|
|
||||||
notifyHeight: 80px;
|
|
||||||
notifyDeltaX: 6px;
|
|
||||||
notifyDeltaY: 7px;
|
|
||||||
|
|
||||||
boxPhotoPadding: margins(28px, 28px, 28px, 18px);
|
boxPhotoPadding: margins(28px, 28px, 28px, 18px);
|
||||||
boxPhotoCompressedPadding: margins(0px, 2px, 0px, 22px);
|
boxPhotoCompressedPadding: margins(0px, 2px, 0px, 22px);
|
||||||
|
@ -1540,17 +1512,15 @@ dropdownDef: dropdown {
|
||||||
borderColor: #ebebeb;
|
borderColor: #ebebeb;
|
||||||
|
|
||||||
padding: margins(10px, 10px, 10px, 10px);
|
padding: margins(10px, 10px, 10px, 10px);
|
||||||
shadow: sprite(241px, 46px, 6px, 6px);
|
shadow: defaultDropdownShadow;
|
||||||
shadowShift: 1px;
|
shadowShift: 1px;
|
||||||
|
|
||||||
duration: 150;
|
duration: 150;
|
||||||
width: 0px;
|
width: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultInnerDropdownShadow: icon {{ "dropdown_shadow", windowShadowFg }};
|
|
||||||
defaultInnerDropdown: InnerDropdown {
|
defaultInnerDropdown: InnerDropdown {
|
||||||
padding: margins(10px, 10px, 10px, 10px);
|
padding: margins(10px, 10px, 10px, 10px);
|
||||||
shadow: defaultInnerDropdownShadow;
|
shadow: defaultDropdownShadow;
|
||||||
shadowShift: 1px;
|
shadowShift: 1px;
|
||||||
|
|
||||||
duration: 150;
|
duration: 150;
|
||||||
|
@ -1840,7 +1810,7 @@ mvControlSize: 90px;
|
||||||
mvIconSize: size(60px, 56px);
|
mvIconSize: size(60px, 56px);
|
||||||
|
|
||||||
mvDropdown: dropdown(dropdownDef) {
|
mvDropdown: dropdown(dropdownDef) {
|
||||||
shadow: sprite(0px, 0px, 0px, 0px);
|
shadow: icon {};
|
||||||
padding: margins(11px, 12px, 11px, 12px);
|
padding: margins(11px, 12px, 11px, 12px);
|
||||||
|
|
||||||
border: 0px;
|
border: 0px;
|
||||||
|
@ -1865,7 +1835,7 @@ mvButton: iconedButton(btnDefIconed) {
|
||||||
duration: 0;
|
duration: 0;
|
||||||
}
|
}
|
||||||
mvPopupMenu: PopupMenu(defaultPopupMenu) {
|
mvPopupMenu: PopupMenu(defaultPopupMenu) {
|
||||||
shadow: sprite(0px, 0px, 0px, 0px);
|
shadow: icon {};
|
||||||
|
|
||||||
itemBg: #383838;
|
itemBg: #383838;
|
||||||
itemBgOver: #505050;
|
itemBgOver: #505050;
|
||||||
|
@ -2044,7 +2014,7 @@ sessionInfoFont: msgFont;
|
||||||
sessionInfoColor: #888888;
|
sessionInfoColor: #888888;
|
||||||
sessionTerminateTop: 30px;
|
sessionTerminateTop: 30px;
|
||||||
sessionTerminateSkip: 18px;
|
sessionTerminateSkip: 18px;
|
||||||
sessionTerminate: iconedButton(notifyClose) {
|
sessionTerminate: iconedButton(simpleClose) {
|
||||||
iconPos: point(3px, 3px);
|
iconPos: point(3px, 3px);
|
||||||
downIconPos: point(3px, 4px);
|
downIconPos: point(3px, 4px);
|
||||||
width: 16px;
|
width: 16px;
|
||||||
|
@ -2058,6 +2028,8 @@ webPageDescriptionFont: normalFont;
|
||||||
webPagePhotoSize: 100px;
|
webPagePhotoSize: 100px;
|
||||||
webPagePhotoDelta: 8px;
|
webPagePhotoDelta: 8px;
|
||||||
|
|
||||||
|
mediaPlayerSuppressDuration: 150;
|
||||||
|
|
||||||
botDescSkip: 8px;
|
botDescSkip: 8px;
|
||||||
|
|
||||||
suppressAll: 0.2;
|
suppressAll: 0.2;
|
||||||
|
|
|
@ -233,7 +233,7 @@ dropdown {
|
||||||
borderColor: color;
|
borderColor: color;
|
||||||
|
|
||||||
padding: margins;
|
padding: margins;
|
||||||
shadow: sprite;
|
shadow: icon;
|
||||||
shadowShift: pixels;
|
shadowShift: pixels;
|
||||||
|
|
||||||
duration: int;
|
duration: int;
|
||||||
|
@ -255,7 +255,7 @@ InnerDropdown {
|
||||||
PopupMenu {
|
PopupMenu {
|
||||||
skip: pixels;
|
skip: pixels;
|
||||||
|
|
||||||
shadow: sprite;
|
shadow: icon;
|
||||||
shadowShift: pixels;
|
shadowShift: pixels;
|
||||||
|
|
||||||
itemBg: color;
|
itemBg: color;
|
||||||
|
@ -273,7 +273,7 @@ PopupMenu {
|
||||||
separatorWidth: pixels;
|
separatorWidth: pixels;
|
||||||
separatorFg: color;
|
separatorFg: color;
|
||||||
|
|
||||||
arrow: sprite;
|
arrow: icon;
|
||||||
|
|
||||||
duration: int;
|
duration: int;
|
||||||
|
|
||||||
|
|
BIN
Telegram/Resources/icons/box_shadow.png
Normal file
After Width: | Height: | Size: 190 B |
BIN
Telegram/Resources/icons/box_shadow@2x.png
Normal file
After Width: | Height: | Size: 294 B |
BIN
Telegram/Resources/icons/dropdown_submenu_arrow.png
Normal file
After Width: | Height: | Size: 119 B |
BIN
Telegram/Resources/icons/dropdown_submenu_arrow@2x.png
Normal file
After Width: | Height: | Size: 166 B |
BIN
Telegram/Resources/icons/fade_horizontal_left.png
Normal file
After Width: | Height: | Size: 139 B |
BIN
Telegram/Resources/icons/fade_horizontal_left@2x.png
Normal file
After Width: | Height: | Size: 192 B |
BIN
Telegram/Resources/icons/fade_horizontal_right.png
Normal file
After Width: | Height: | Size: 142 B |
BIN
Telegram/Resources/icons/fade_horizontal_right@2x.png
Normal file
After Width: | Height: | Size: 190 B |
BIN
Telegram/Resources/icons/monitor.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
Telegram/Resources/icons/monitor@2x.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
Telegram/Resources/icons/notification_send.png
Normal file
After Width: | Height: | Size: 292 B |
BIN
Telegram/Resources/icons/notification_send@2x.png
Normal file
After Width: | Height: | Size: 506 B |
BIN
Telegram/Resources/icons/window_shadow.png
Normal file
After Width: | Height: | Size: 225 B |
BIN
Telegram/Resources/icons/window_shadow@2x.png
Normal file
After Width: | Height: | Size: 372 B |
|
@ -244,10 +244,17 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
"lng_settings_show_name" = "Show sender's name";
|
"lng_settings_show_name" = "Show sender's name";
|
||||||
"lng_settings_show_preview" = "Show message preview";
|
"lng_settings_show_preview" = "Show message preview";
|
||||||
"lng_settings_use_windows" = "Use Windows notifications";
|
"lng_settings_use_windows" = "Use Windows notifications";
|
||||||
|
"lng_settings_use_native_notifications" = "Use native notifications";
|
||||||
|
"lng_settings_advanced_notifications" = "Notifications position and count";
|
||||||
|
"lng_settings_notifications_position" = "Location on the screen";
|
||||||
|
"lng_settings_notifications_count" = "Notifications count";
|
||||||
"lng_settings_sound_notify" = "Play sound";
|
"lng_settings_sound_notify" = "Play sound";
|
||||||
"lng_settings_include_muted" = "Include muted chats in unread count";
|
"lng_settings_include_muted" = "Include muted chats in unread count";
|
||||||
|
|
||||||
"lng_notification_preview" = "You have a new message";
|
"lng_notification_preview" = "You have a new message";
|
||||||
|
"lng_notification_reply" = "Reply";
|
||||||
|
"lng_notification_hide_all" = "Hide all";
|
||||||
|
"lng_notification_sample" = "This is a sample notification";
|
||||||
|
|
||||||
"lng_settings_section_general" = "General";
|
"lng_settings_section_general" = "General";
|
||||||
"lng_settings_change_lang" = "Change language";
|
"lng_settings_change_lang" = "Change language";
|
||||||
|
@ -567,7 +574,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
"lng_action_changed_title" = "{from} changed group name to «{title}»";
|
"lng_action_changed_title" = "{from} changed group name to «{title}»";
|
||||||
"lng_action_changed_title_channel" = "Channel name was changed to «{title}»";
|
"lng_action_changed_title_channel" = "Channel name was changed to «{title}»";
|
||||||
"lng_action_created_chat" = "{from} created group «{title}»";
|
"lng_action_created_chat" = "{from} created group «{title}»";
|
||||||
"lng_action_created_channel" = "Channel «{title}» created";
|
"lng_action_created_channel" = "Channel created";
|
||||||
"lng_action_group_migrate" = "The group was upgraded to a supergroup";
|
"lng_action_group_migrate" = "The group was upgraded to a supergroup";
|
||||||
"lng_action_pinned_message" = "{from} pinned «{text}»";
|
"lng_action_pinned_message" = "{from} pinned «{text}»";
|
||||||
"lng_action_pinned_media" = "{from} pinned {media}";
|
"lng_action_pinned_media" = "{from} pinned {media}";
|
||||||
|
@ -584,6 +591,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
"lng_action_pinned_media_game" = "the game «{game}»";
|
"lng_action_pinned_media_game" = "the game «{game}»";
|
||||||
"lng_action_game_score" = "{from} scored {count:#|#|#} in {game}";
|
"lng_action_game_score" = "{from} scored {count:#|#|#} in {game}";
|
||||||
"lng_action_game_you_scored" = "You scored {count:#|#|#} in {game}";
|
"lng_action_game_you_scored" = "You scored {count:#|#|#} in {game}";
|
||||||
|
"lng_action_game_score_no_game" = "{from} scored {count:#|#|#}";
|
||||||
|
"lng_action_game_you_scored_no_game" = "You scored {count:#|#|#}";
|
||||||
|
|
||||||
"lng_profile_migrate_reached" = "{count:_not_used_|# member|# members} limit reached";
|
"lng_profile_migrate_reached" = "{count:_not_used_|# member|# members} limit reached";
|
||||||
"lng_profile_migrate_body" = "To get over this limit, you can upgrade your group to a supergroup.";
|
"lng_profile_migrate_body" = "To get over this limit, you can upgrade your group to a supergroup.";
|
||||||
|
|
|
@ -772,12 +772,12 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
"lng_allow_bot" = "허용";
|
"lng_allow_bot" = "허용";
|
||||||
|
|
||||||
"lng_bot_start" = "시작";
|
"lng_bot_start" = "시작";
|
||||||
"lng_bot_choose_group" = "Select a Group";
|
"lng_bot_choose_group" = "그룹방 선택";
|
||||||
"lng_bot_no_groups" = "그룹이 존재하지 않습니다.";
|
"lng_bot_no_groups" = "그룹이 존재하지 않습니다.";
|
||||||
"lng_bot_groups_not_found" = "그룹을 찾을 수 없습니다.";
|
"lng_bot_groups_not_found" = "그룹을 찾을 수 없습니다.";
|
||||||
"lng_bot_sure_invite" = "<<{group}>>에 봇을 추가 하시겠습니까?";
|
"lng_bot_sure_invite" = "<<{group}>>에 봇을 추가 하시겠습니까?";
|
||||||
"lng_bot_already_in_group" = "봇이 이미 그룹의 멤버입니다.";
|
"lng_bot_already_in_group" = "봇이 이미 그룹의 멤버입니다.";
|
||||||
"lng_bot_choose_chat" = "Select a Chat";
|
"lng_bot_choose_chat" = "채팅방 선택";
|
||||||
"lng_bot_no_chats" = "채팅방이 없습니다.";
|
"lng_bot_no_chats" = "채팅방이 없습니다.";
|
||||||
"lng_bot_chats_not_found" = "채팅방을 찾 을 수 없음";
|
"lng_bot_chats_not_found" = "채팅방을 찾 을 수 없음";
|
||||||
"lng_bot_sure_share_game" = "{user}에게 게임을 공유하겠습니까?";
|
"lng_bot_sure_share_game" = "{user}에게 게임을 공유하겠습니까?";
|
||||||
|
@ -787,10 +787,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
"lng_user_typing" = "{user}님이 입력중입니다.";
|
"lng_user_typing" = "{user}님이 입력중입니다.";
|
||||||
"lng_users_typing" = "{user}님과 {second_user}님이 입력중입니다.";
|
"lng_users_typing" = "{user}님과 {second_user}님이 입력중입니다.";
|
||||||
"lng_many_typing" = "{count:_not_used_|#명이|#명이} 입력중입니다";
|
"lng_many_typing" = "{count:_not_used_|#명이|#명이} 입력중입니다";
|
||||||
"lng_playing_game" = "playing a game";
|
"lng_playing_game" = "게임 중";
|
||||||
"lng_user_playing_game" = "{user} is playing a game";
|
"lng_user_playing_game" = "{user}님이 게임 중입니다.";
|
||||||
"lng_users_playing_game" = "{user} and {second_user} are playing a game";
|
"lng_users_playing_game" = "{user}님과 {second_user}님이 게임 중입니다.";
|
||||||
"lng_many_playing_game" = "{count:_not_used_|# is|# are} playing a game";
|
"lng_many_playing_game" = "{count:_not_used_|#명이|#명이} 게임 중입니다";
|
||||||
"lng_send_action_record_video" = "비디오 녹화 중";
|
"lng_send_action_record_video" = "비디오 녹화 중";
|
||||||
"lng_user_action_record_video" = "{user}님이 녹화중입니다";
|
"lng_user_action_record_video" = "{user}님이 녹화중입니다";
|
||||||
"lng_send_action_upload_video" = "비디오 전송 중";
|
"lng_send_action_upload_video" = "비디오 전송 중";
|
||||||
|
|
|
@ -34,8 +34,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 0,10,8,5
|
FILEVERSION 0,10,13,0
|
||||||
PRODUCTVERSION 0,10,8,5
|
PRODUCTVERSION 0,10,13,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -51,10 +51,10 @@ BEGIN
|
||||||
BLOCK "040904b0"
|
BLOCK "040904b0"
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "Telegram Messenger LLP"
|
VALUE "CompanyName", "Telegram Messenger LLP"
|
||||||
VALUE "FileVersion", "0.10.8.5"
|
VALUE "FileVersion", "0.10.13.0"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
|
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
|
||||||
VALUE "ProductName", "Telegram Desktop"
|
VALUE "ProductName", "Telegram Desktop"
|
||||||
VALUE "ProductVersion", "0.10.8.5"
|
VALUE "ProductVersion", "0.10.13.0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 0,10,8,5
|
FILEVERSION 0,10,13,0
|
||||||
PRODUCTVERSION 0,10,8,5
|
PRODUCTVERSION 0,10,13,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -43,10 +43,10 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "Telegram Messenger LLP"
|
VALUE "CompanyName", "Telegram Messenger LLP"
|
||||||
VALUE "FileDescription", "Telegram Updater"
|
VALUE "FileDescription", "Telegram Updater"
|
||||||
VALUE "FileVersion", "0.10.8.5"
|
VALUE "FileVersion", "0.10.13.0"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
|
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
|
||||||
VALUE "ProductName", "Telegram Desktop"
|
VALUE "ProductName", "Telegram Desktop"
|
||||||
VALUE "ProductVersion", "0.10.8.5"
|
VALUE "ProductVersion", "0.10.13.0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
@ -20,6 +20,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/single_timer.h"
|
||||||
|
|
||||||
class ApiWrap : public QObject, public RPCSender {
|
class ApiWrap : public QObject, public RPCSender {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#include "numbers.h"
|
#include "numbers.h"
|
||||||
#include "observer_peer.h"
|
#include "observer_peer.h"
|
||||||
#include "window/chat_background.h"
|
#include "window/chat_background.h"
|
||||||
|
#include "window/notifications_manager.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
App::LaunchState _launchState = App::Launched;
|
App::LaunchState _launchState = App::Launched;
|
||||||
|
@ -1991,13 +1992,10 @@ namespace {
|
||||||
if (::mousedItem == item) {
|
if (::mousedItem == item) {
|
||||||
mousedItem(nullptr);
|
mousedItem(nullptr);
|
||||||
}
|
}
|
||||||
if (App::wnd()) {
|
|
||||||
App::wnd()->notifyItemRemoved(item);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void historyUnregItem(HistoryItem *item) {
|
void historyUnregItem(HistoryItem *item) {
|
||||||
MsgsData *data = fetchMsgsData(item->channelId(), false);
|
auto data = fetchMsgsData(item->channelId(), false);
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
|
|
||||||
auto i = data->find(item->id);
|
auto i = data->find(item->id);
|
||||||
|
@ -2013,10 +2011,13 @@ namespace {
|
||||||
std::swap(items, j.value());
|
std::swap(items, j.value());
|
||||||
::dependentItems.erase(j);
|
::dependentItems.erase(j);
|
||||||
|
|
||||||
for_const (HistoryItem *dependent, items) {
|
for_const (auto dependent, items) {
|
||||||
dependent->dependencyItemRemoved(item);
|
dependent->dependencyItemRemoved(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (auto manager = Window::Notifications::manager()) {
|
||||||
|
manager->clearFromItem(item);
|
||||||
|
}
|
||||||
if (App::main() && !App::quitting()) {
|
if (App::main() && !App::quitting()) {
|
||||||
App::main()->itemRemoved(item);
|
App::main()->itemRemoved(item);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#include "lang.h"
|
#include "lang.h"
|
||||||
#include "boxes/confirmbox.h"
|
#include "boxes/confirmbox.h"
|
||||||
#include "ui/filedialog.h"
|
#include "ui/filedialog.h"
|
||||||
|
#include "ui/popupmenu.h"
|
||||||
#include "langloaderplain.h"
|
#include "langloaderplain.h"
|
||||||
#include "localstorage.h"
|
#include "localstorage.h"
|
||||||
#include "autoupdater.h"
|
#include "autoupdater.h"
|
||||||
|
@ -35,6 +36,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#include "observer_peer.h"
|
#include "observer_peer.h"
|
||||||
#include "window/chat_background.h"
|
#include "window/chat_background.h"
|
||||||
#include "media/player/media_player_instance.h"
|
#include "media/player/media_player_instance.h"
|
||||||
|
#include "window/notifications_manager.h"
|
||||||
#include "history/history_location_manager.h"
|
#include "history/history_location_manager.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -303,9 +305,8 @@ void Application::readClients() {
|
||||||
if (!startUrl.isEmpty()) {
|
if (!startUrl.isEmpty()) {
|
||||||
cSetStartUrl(startUrl);
|
cSetStartUrl(startUrl);
|
||||||
}
|
}
|
||||||
if (!cStartUrl().isEmpty() && App::main() && App::self()) {
|
if (auto main = App::main()) {
|
||||||
App::main()->openLocalUrl(cStartUrl());
|
main->checkStartUrl();
|
||||||
cSetStartUrl(QString());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,8 +333,11 @@ void Application::closeApplication() {
|
||||||
if (App::launchState() == App::QuitProcessed) return;
|
if (App::launchState() == App::QuitProcessed) return;
|
||||||
App::setLaunchState(App::QuitProcessed);
|
App::setLaunchState(App::QuitProcessed);
|
||||||
|
|
||||||
delete AppObject;
|
if (auto manager = Window::Notifications::manager()) {
|
||||||
AppObject = 0;
|
manager->clearAllFast();
|
||||||
|
}
|
||||||
|
|
||||||
|
delete base::take(AppObject);
|
||||||
|
|
||||||
Sandbox::finish();
|
Sandbox::finish();
|
||||||
|
|
||||||
|
@ -729,6 +733,7 @@ AppClass::AppClass() : QObject()
|
||||||
anim::startManager();
|
anim::startManager();
|
||||||
historyInit();
|
historyInit();
|
||||||
Media::Player::start();
|
Media::Player::start();
|
||||||
|
Window::Notifications::start();
|
||||||
|
|
||||||
DEBUG_LOG(("Application Info: inited..."));
|
DEBUG_LOG(("Application Info: inited..."));
|
||||||
|
|
||||||
|
@ -742,7 +747,8 @@ AppClass::AppClass() : QObject()
|
||||||
|
|
||||||
DEBUG_LOG(("Application Info: starting app..."));
|
DEBUG_LOG(("Application Info: starting app..."));
|
||||||
|
|
||||||
QMimeDatabase().mimeTypeForName(qsl("text/plain")); // create mime database
|
// Create mime database, so it won't be slow later.
|
||||||
|
QMimeDatabase().mimeTypeForName(qsl("text/plain"));
|
||||||
|
|
||||||
_window = new MainWindow();
|
_window = new MainWindow();
|
||||||
_window->createWinId();
|
_window->createWinId();
|
||||||
|
@ -1080,8 +1086,8 @@ void AppClass::checkMapVersion() {
|
||||||
if (Local::oldMapVersion() < AppVersion) {
|
if (Local::oldMapVersion() < AppVersion) {
|
||||||
if (Local::oldMapVersion()) {
|
if (Local::oldMapVersion()) {
|
||||||
QString versionFeatures;
|
QString versionFeatures;
|
||||||
if ((cAlphaVersion() || cBetaVersion()) && Local::oldMapVersion() < 10003) {
|
if ((cAlphaVersion() || cBetaVersion()) && Local::oldMapVersion() < 10012) {
|
||||||
versionFeatures = QString::fromUtf8("\xe2\x80\x94 New cute design for the Settings page");
|
versionFeatures = QString::fromUtf8("Windows and Linux:\n\xe2\x80\x94 Quick reply from notifications\n\xe2\x80\x94 Hide all notifications button added\n\xe2\x80\x94 Change notifications location and maximum count\n\nLinux:\n\xe2\x80\x94 You can enable native notifications in Settings");
|
||||||
} else if (!(cAlphaVersion() || cBetaVersion()) && Local::oldMapVersion() < 10005) {
|
} else if (!(cAlphaVersion() || cBetaVersion()) && Local::oldMapVersion() < 10005) {
|
||||||
versionFeatures = langNewVersionText();
|
versionFeatures = langNewVersionText();
|
||||||
} else {
|
} else {
|
||||||
|
@ -1098,8 +1104,9 @@ void AppClass::checkMapVersion() {
|
||||||
AppClass::~AppClass() {
|
AppClass::~AppClass() {
|
||||||
Shortcuts::finish();
|
Shortcuts::finish();
|
||||||
|
|
||||||
auto window = createAndSwap(_window);
|
delete base::take(_window);
|
||||||
delete window;
|
|
||||||
|
Window::Notifications::finish();
|
||||||
|
|
||||||
anim::stopManager();
|
anim::stopManager();
|
||||||
|
|
||||||
|
@ -1110,8 +1117,8 @@ AppClass::~AppClass() {
|
||||||
MTP::finish();
|
MTP::finish();
|
||||||
|
|
||||||
AppObject = nullptr;
|
AppObject = nullptr;
|
||||||
deleteAndMark(_uploader);
|
delete base::take(_uploader);
|
||||||
deleteAndMark(_translator);
|
delete base::take(_translator);
|
||||||
|
|
||||||
Window::chatBackground()->reset();
|
Window::chatBackground()->reset();
|
||||||
|
|
||||||
|
@ -1128,9 +1135,9 @@ AppClass *AppClass::app() {
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow *AppClass::wnd() {
|
MainWindow *AppClass::wnd() {
|
||||||
return AppObject ? AppObject->_window : 0;
|
return AppObject ? AppObject->_window : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWidget *AppClass::main() {
|
MainWidget *AppClass::main() {
|
||||||
return (AppObject && AppObject->_window) ? AppObject->_window->mainWidget() : 0;
|
return (AppObject && AppObject->_window) ? AppObject->_window->mainWidget() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "pspecific.h"
|
#include "pspecific.h"
|
||||||
|
#include "core/single_timer.h"
|
||||||
|
|
||||||
class UpdateChecker;
|
class UpdateChecker;
|
||||||
class Application : public QApplication {
|
class Application : public QApplication {
|
||||||
|
|
|
@ -160,7 +160,7 @@ void AbstractBox::resizeMaxHeight(int32 newWidth, int32 maxHeight) {
|
||||||
move(r.left(), newTop);
|
move(r.left(), newTop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parentWidget()->update(geometry().united(g).marginsAdded(QMargins(st::boxShadow.pxWidth(), st::boxShadow.pxHeight(), st::boxShadow.pxWidth(), st::boxShadow.pxHeight())));
|
parentWidget()->update(geometry().united(g).marginsAdded(QMargins(st::boxShadow.width(), st::boxShadow.height(), st::boxShadow.width(), st::boxShadow.height())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1405,7 +1405,7 @@ void RevokePublicLinkBox::mousePressEvent(QMouseEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RevokePublicLinkBox::mouseReleaseEvent(QMouseEvent *e) {
|
void RevokePublicLinkBox::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
auto pressed = createAndSwap(_pressed);
|
auto pressed = base::take(_pressed);
|
||||||
setCursor((_selected || _pressed) ? style::cur_pointer : style::cur_default);
|
setCursor((_selected || _pressed) ? style::cur_pointer : style::cur_default);
|
||||||
if (pressed && pressed == _selected) {
|
if (pressed && pressed == _selected) {
|
||||||
auto text_method = pressed->isMegagroup() ? lng_channels_too_much_public_revoke_confirm_group : lng_channels_too_much_public_revoke_confirm_channel;
|
auto text_method = pressed->isMegagroup() ? lng_channels_too_much_public_revoke_confirm_group : lng_channels_too_much_public_revoke_confirm_channel;
|
||||||
|
|
|
@ -89,3 +89,24 @@ shareColumnSkip: 6px;
|
||||||
shareSelectDuration: 150;
|
shareSelectDuration: 150;
|
||||||
shareActivateDuration: 150;
|
shareActivateDuration: 150;
|
||||||
shareScrollDuration: 300;
|
shareScrollDuration: 300;
|
||||||
|
|
||||||
|
notificationsBoxHeight: 450px;
|
||||||
|
notificationsBoxMonitorTop: 63px;
|
||||||
|
notificationsBoxMonitor: icon {{ "monitor", #000000 }};
|
||||||
|
notificationsBoxScreenTop: 10px;
|
||||||
|
notificationsBoxScreenSize: size(280px, 160px);
|
||||||
|
notificationsBoxScreenBg: titleBg;
|
||||||
|
notificationsBoxCountLabelTop: 80px;
|
||||||
|
notificationsBoxCountTop: 30px;
|
||||||
|
|
||||||
|
notificationsSampleSkip: 5px;
|
||||||
|
notificationsSampleTopSkip: 5px;
|
||||||
|
notificationsSampleBottomSkip: 5px;
|
||||||
|
notificationsSampleMargin: 2px;
|
||||||
|
|
||||||
|
notificationSampleOpacity: 0.5;
|
||||||
|
notificationSampleSize: size(64px, 16px);
|
||||||
|
notificationSampleUserpicFg: #40ace3;
|
||||||
|
notificationSampleCloseFg: #d7d7d7;
|
||||||
|
notificationSampleTextFg: #d7d7d7;
|
||||||
|
notificationSampleNameFg: #939393;
|
||||||
|
|
|
@ -21,6 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "abstractbox.h"
|
#include "abstractbox.h"
|
||||||
|
#include "core/single_timer.h"
|
||||||
|
|
||||||
namespace Dialogs {
|
namespace Dialogs {
|
||||||
class Row;
|
class Row;
|
||||||
|
|
421
Telegram/SourceFiles/boxes/notifications_box.cpp
Normal file
|
@ -0,0 +1,421 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||||
|
|
||||||
|
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
It is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
In addition, as a special exception, the copyright holders give permission
|
||||||
|
to link the code of portions of this program with the OpenSSL library.
|
||||||
|
|
||||||
|
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||||
|
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
*/
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "boxes/notifications_box.h"
|
||||||
|
|
||||||
|
#include "lang.h"
|
||||||
|
#include "ui/buttons/round_button.h"
|
||||||
|
#include "ui/widgets/discrete_slider.h"
|
||||||
|
#include "styles/style_boxes.h"
|
||||||
|
#include "styles/style_dialogs.h"
|
||||||
|
#include "styles/style_window.h"
|
||||||
|
#include "application.h"
|
||||||
|
#include "localstorage.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr int kMaxNotificationsCount = 5;
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
class NotificationsBox::SampleWidget : public QWidget {
|
||||||
|
public:
|
||||||
|
SampleWidget(NotificationsBox *owner, const QPixmap &cache) : QWidget(nullptr)
|
||||||
|
, _owner(owner)
|
||||||
|
, _cache(cache) {
|
||||||
|
resize(cache.width() / cache.devicePixelRatio(), cache.height() / cache.devicePixelRatio());
|
||||||
|
|
||||||
|
setAttribute(Qt::WA_MacAlwaysShowToolWindow);
|
||||||
|
setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||||
|
setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::BypassWindowManagerHint | Qt::NoDropShadowWindowHint);
|
||||||
|
|
||||||
|
setWindowOpacity(0.);
|
||||||
|
show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void detach() {
|
||||||
|
_owner = nullptr;
|
||||||
|
hideFast();
|
||||||
|
}
|
||||||
|
|
||||||
|
void showFast() {
|
||||||
|
_hiding = false;
|
||||||
|
startAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
void hideFast() {
|
||||||
|
_hiding = true;
|
||||||
|
startAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void paintEvent(QPaintEvent *e) {
|
||||||
|
Painter p(this);
|
||||||
|
p.drawPixmap(0, 0, _cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void startAnimation() {
|
||||||
|
_opacity.start([this] { animationCallback(); }, _hiding ? 1. : 0., _hiding ? 0. : 1., st::notifyFastAnim);
|
||||||
|
}
|
||||||
|
void animationCallback() {
|
||||||
|
setWindowOpacity(_opacity.current(_hiding ? 0. : 1.));
|
||||||
|
if (!_opacity.animating() && _hiding) {
|
||||||
|
if (_owner) {
|
||||||
|
_owner->removeSample(this);
|
||||||
|
}
|
||||||
|
hide();
|
||||||
|
destroyDelayed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroyDelayed() {
|
||||||
|
if (_deleted) return;
|
||||||
|
_deleted = true;
|
||||||
|
|
||||||
|
// Ubuntu has a lag if deleteLater() called immediately.
|
||||||
|
#if defined Q_OS_LINUX32 || defined Q_OS_LINUX64
|
||||||
|
QTimer::singleShot(1000, [this] { delete this; });
|
||||||
|
#else // Q_OS_LINUX32 || Q_OS_LINUX64
|
||||||
|
deleteLater();
|
||||||
|
#endif // Q_OS_LINUX32 || Q_OS_LINUX64
|
||||||
|
}
|
||||||
|
|
||||||
|
NotificationsBox *_owner;
|
||||||
|
QPixmap _cache;
|
||||||
|
FloatAnimation _opacity;
|
||||||
|
bool _hiding = false;
|
||||||
|
bool _deleted = false;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
NotificationsBox::NotificationsBox() : AbstractBox()
|
||||||
|
, _chosenCorner(Global::NotificationsCorner())
|
||||||
|
, _oldCount(snap(Global::NotificationsCount(), 1, kMaxNotificationsCount))
|
||||||
|
, _countSlider(this)
|
||||||
|
, _done(this, lang(lng_about_done), st::defaultBoxButton) {
|
||||||
|
_sampleOpacities.reserve(kMaxNotificationsCount);
|
||||||
|
for (int i = 0; i != kMaxNotificationsCount; ++i) {
|
||||||
|
_countSlider->addSection(QString::number(i + 1));
|
||||||
|
_sampleOpacities.push_back(FloatAnimation());
|
||||||
|
}
|
||||||
|
_countSlider->setActiveSectionFast(_oldCount - 1);
|
||||||
|
_countSlider->setSectionActivatedCallback([this] { countChanged(); });
|
||||||
|
|
||||||
|
setMouseTracking(true);
|
||||||
|
_done->setClickedCallback([this] { onClose(); });
|
||||||
|
|
||||||
|
prepareNotificationSampleSmall();
|
||||||
|
prepareNotificationSampleLarge();
|
||||||
|
setMaxHeight(st::notificationsBoxHeight);
|
||||||
|
|
||||||
|
prepare();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotificationsBox::paintEvent(QPaintEvent *e) {
|
||||||
|
Painter p(this);
|
||||||
|
if (paint(p)) return;
|
||||||
|
|
||||||
|
auto contentLeft = getContentLeft();
|
||||||
|
|
||||||
|
p.setFont(st::boxTitleFont);
|
||||||
|
p.setPen(st::boxTitleFg);
|
||||||
|
p.drawTextLeft(contentLeft, st::boxTitlePosition.y(), width(), lang(lng_settings_notifications_position));
|
||||||
|
|
||||||
|
auto screenRect = getScreenRect();
|
||||||
|
p.fillRect(screenRect.x(), screenRect.y(), st::notificationsBoxScreenSize.width(), st::notificationsBoxScreenSize.height(), st::notificationsBoxScreenBg);
|
||||||
|
|
||||||
|
auto monitorTop = st::notificationsBoxMonitorTop;
|
||||||
|
st::notificationsBoxMonitor.paint(p, contentLeft, monitorTop, width());
|
||||||
|
|
||||||
|
for (int corner = 0; corner != 4; ++corner) {
|
||||||
|
auto screenCorner = static_cast<Notify::ScreenCorner>(corner);
|
||||||
|
auto isLeft = Notify::IsLeftCorner(screenCorner);
|
||||||
|
auto isTop = Notify::IsTopCorner(screenCorner);
|
||||||
|
auto sampleLeft = isLeft ? (screenRect.x() + st::notificationsSampleSkip) : (screenRect.x() + screenRect.width() - st::notificationsSampleSkip - st::notificationSampleSize.width());
|
||||||
|
auto sampleTop = isTop ? (screenRect.y() + st::notificationsSampleTopSkip) : (screenRect.y() + screenRect.height() - st::notificationsSampleBottomSkip - st::notificationSampleSize.height());
|
||||||
|
if (corner == static_cast<int>(_chosenCorner)) {
|
||||||
|
auto count = currentCount();
|
||||||
|
for (int i = 0; i != kMaxNotificationsCount; ++i) {
|
||||||
|
auto opacity = _sampleOpacities[i].current(getms(), (i < count) ? 1. : 0.);
|
||||||
|
p.setOpacity(opacity);
|
||||||
|
p.drawPixmapLeft(sampleLeft, sampleTop, width(), _notificationSampleSmall);
|
||||||
|
sampleTop += (isTop ? 1 : -1) * (st::notificationSampleSize.height() + st::notificationsSampleMargin);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p.setOpacity(st::notificationSampleOpacity);
|
||||||
|
p.drawPixmapLeft(sampleLeft, sampleTop, width(), _notificationSampleSmall);
|
||||||
|
p.setOpacity(1.);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto labelTop = screenRect.y() + screenRect.height() + st::notificationsBoxCountLabelTop;
|
||||||
|
p.drawTextLeft(contentLeft, labelTop, width(), lang(lng_settings_notifications_count));
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotificationsBox::countChanged() {
|
||||||
|
auto count = currentCount();
|
||||||
|
auto moreSamples = (count > _oldCount);
|
||||||
|
auto from = moreSamples ? 0. : 1.;
|
||||||
|
auto to = moreSamples ? 1. : 0.;
|
||||||
|
auto indexDelta = moreSamples ? 1 : -1;
|
||||||
|
auto animatedDelta = moreSamples ? 0 : -1;
|
||||||
|
for (; _oldCount != count; _oldCount += indexDelta) {
|
||||||
|
_sampleOpacities[_oldCount + animatedDelta].start([this] { update(); }, from, to, st::notifyFastAnim);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentCount() != Global::NotificationsCount()) {
|
||||||
|
Global::SetNotificationsCount(currentCount());
|
||||||
|
Global::RefNotifySettingsChanged().notify(Notify::ChangeType::MaxCount);
|
||||||
|
Local::writeUserSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int NotificationsBox::getContentLeft() const {
|
||||||
|
return (width() - st::notificationsBoxMonitor.width()) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect NotificationsBox::getScreenRect() const {
|
||||||
|
auto screenLeft = (width() - st::notificationsBoxScreenSize.width()) / 2;
|
||||||
|
auto screenTop = st::notificationsBoxMonitorTop + st::notificationsBoxScreenTop;
|
||||||
|
return QRect(screenLeft, screenTop, st::notificationsBoxScreenSize.width(), st::notificationsBoxScreenSize.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotificationsBox::resizeEvent(QResizeEvent *e) {
|
||||||
|
_done->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _done->height());
|
||||||
|
|
||||||
|
auto screenRect = getScreenRect();
|
||||||
|
auto sliderTop = screenRect.y() + screenRect.height() + st::notificationsBoxCountLabelTop + st::notificationsBoxCountTop;
|
||||||
|
auto contentLeft = getContentLeft();
|
||||||
|
_countSlider->resizeToWidth(width() - 2 * contentLeft);
|
||||||
|
_countSlider->move(contentLeft, sliderTop);
|
||||||
|
AbstractBox::resizeEvent(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotificationsBox::prepareNotificationSampleSmall() {
|
||||||
|
auto width = st::notificationSampleSize.width();
|
||||||
|
auto height = st::notificationSampleSize.height();
|
||||||
|
auto sampleImage = QImage(width * cIntRetinaFactor(), height * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
||||||
|
sampleImage.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
sampleImage.fill(st::notifyBg->c);
|
||||||
|
{
|
||||||
|
Painter p(&sampleImage);
|
||||||
|
p.setPen(Qt::NoPen);
|
||||||
|
p.setRenderHint(QPainter::HighQualityAntialiasing);
|
||||||
|
|
||||||
|
auto padding = height / 8;
|
||||||
|
auto userpicSize = height - 2 * padding;
|
||||||
|
p.setBrush(st::notificationSampleUserpicFg);
|
||||||
|
p.drawEllipse(rtlrect(padding, padding, userpicSize, userpicSize, width));
|
||||||
|
|
||||||
|
auto rowLeft = height;
|
||||||
|
auto rowHeight = padding;
|
||||||
|
auto nameTop = (height - 5 * padding) / 2;
|
||||||
|
auto nameWidth = height;
|
||||||
|
p.setBrush(st::notificationSampleNameFg);
|
||||||
|
p.drawRoundedRect(rtlrect(rowLeft, nameTop, nameWidth, rowHeight, width), rowHeight / 2, rowHeight / 2);
|
||||||
|
|
||||||
|
auto rowWidth = (width - rowLeft - 3 * padding);
|
||||||
|
auto rowTop = nameTop + rowHeight + padding;
|
||||||
|
p.setBrush(st::notificationSampleTextFg);
|
||||||
|
p.drawRoundedRect(rtlrect(rowLeft, rowTop, rowWidth, rowHeight, width), rowHeight / 2, rowHeight / 2);
|
||||||
|
rowTop += rowHeight + padding;
|
||||||
|
p.drawRoundedRect(rtlrect(rowLeft, rowTop, rowWidth, rowHeight, width), rowHeight / 2, rowHeight / 2);
|
||||||
|
|
||||||
|
auto closeLeft = width - 2 * padding;
|
||||||
|
p.fillRect(rtlrect(closeLeft, padding, padding, padding, width), st::notificationSampleCloseFg);
|
||||||
|
}
|
||||||
|
_notificationSampleSmall = App::pixmapFromImageInPlace(std_::move(sampleImage));
|
||||||
|
_notificationSampleSmall.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotificationsBox::prepareNotificationSampleUserpic() {
|
||||||
|
if (_notificationSampleUserpic.isNull()) {
|
||||||
|
_notificationSampleUserpic = App::pixmapFromImageInPlace(App::wnd()->iconLarge().scaled(st::notifyPhotoSize * cIntRetinaFactor(), st::notifyPhotoSize * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||||
|
_notificationSampleUserpic.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotificationsBox::prepareNotificationSampleLarge() {
|
||||||
|
int w = st::notifyWidth, h = st::notifyMinHeight;
|
||||||
|
auto sampleImage = QImage(w * cIntRetinaFactor(), h * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
||||||
|
sampleImage.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
sampleImage.fill(st::notifyBg->c);
|
||||||
|
{
|
||||||
|
Painter p(&sampleImage);
|
||||||
|
p.fillRect(0, 0, w - st::notifyBorderWidth, st::notifyBorderWidth, st::notifyBorder->b);
|
||||||
|
p.fillRect(w - st::notifyBorderWidth, 0, st::notifyBorderWidth, h - st::notifyBorderWidth, st::notifyBorder->b);
|
||||||
|
p.fillRect(st::notifyBorderWidth, h - st::notifyBorderWidth, w - st::notifyBorderWidth, st::notifyBorderWidth, st::notifyBorder->b);
|
||||||
|
p.fillRect(0, st::notifyBorderWidth, st::notifyBorderWidth, h - st::notifyBorderWidth, st::notifyBorder->b);
|
||||||
|
|
||||||
|
prepareNotificationSampleUserpic();
|
||||||
|
p.drawPixmap(st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), _notificationSampleUserpic);
|
||||||
|
|
||||||
|
int itemWidth = w - st::notifyPhotoPos.x() - st::notifyPhotoSize - st::notifyTextLeft - st::notifyClosePos.x() - st::notifyClose.width;
|
||||||
|
|
||||||
|
auto rectForName = rtlrect(st::notifyPhotoPos.x() + st::notifyPhotoSize + st::notifyTextLeft, st::notifyTextTop, itemWidth, st::msgNameFont->height, w);
|
||||||
|
|
||||||
|
auto notifyText = st::dialogsTextFont->elided(lang(lng_notification_sample), itemWidth);
|
||||||
|
p.setFont(st::dialogsTextFont);
|
||||||
|
p.setPen(st::dialogsTextFgService);
|
||||||
|
p.drawText(st::notifyPhotoPos.x() + st::notifyPhotoSize + st::notifyTextLeft, st::notifyItemTop + st::msgNameFont->height + st::dialogsTextFont->ascent, notifyText);
|
||||||
|
|
||||||
|
p.setPen(st::dialogsNameFg);
|
||||||
|
p.setFont(st::msgNameFont);
|
||||||
|
|
||||||
|
auto notifyTitle = st::msgNameFont->elided(qsl("Telegram Desktop"), rectForName.width());
|
||||||
|
p.drawText(rectForName.left(), rectForName.top() + st::msgNameFont->ascent, notifyTitle);
|
||||||
|
|
||||||
|
p.setOpacity(st::notifyClose.opacity);
|
||||||
|
p.drawSpriteLeft(w - st::notifyClosePos.x() - st::notifyClose.width + st::notifyClose.iconPos.x(), st::notifyClosePos.y() + st::notifyClose.iconPos.y(), w, st::notifyClose.icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
_notificationSampleLarge = App::pixmapFromImageInPlace(std_::move(sampleImage));
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotificationsBox::removeSample(SampleWidget *widget) {
|
||||||
|
for (auto &samples : _cornerSamples) {
|
||||||
|
for (int i = 0, size = samples.size(); i != size; ++i) {
|
||||||
|
if (samples[i] == widget) {
|
||||||
|
for (int j = i + 1; j != size; ++j) {
|
||||||
|
samples[j]->detach();
|
||||||
|
}
|
||||||
|
samples.resize(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotificationsBox::mouseMoveEvent(QMouseEvent *e) {
|
||||||
|
auto screenRect = getScreenRect();
|
||||||
|
auto cornerWidth = screenRect.width() / 3;
|
||||||
|
auto cornerHeight = screenRect.height() / 3;
|
||||||
|
auto topLeft = rtlrect(screenRect.x(), screenRect.y(), cornerWidth, cornerHeight, width());
|
||||||
|
auto topRight = rtlrect(screenRect.x() + screenRect.width() - cornerWidth, screenRect.y(), cornerWidth, cornerHeight, width());
|
||||||
|
auto bottomRight = rtlrect(screenRect.x() + screenRect.width() - cornerWidth, screenRect.y() + screenRect.height() - cornerHeight, cornerWidth, cornerHeight, width());
|
||||||
|
auto bottomLeft = rtlrect(screenRect.x(), screenRect.y() + screenRect.height() - cornerHeight, cornerWidth, cornerHeight, width());
|
||||||
|
if (topLeft.contains(e->pos())) {
|
||||||
|
setOverCorner(Notify::ScreenCorner::TopLeft);
|
||||||
|
} else if (topRight.contains(e->pos())) {
|
||||||
|
setOverCorner(Notify::ScreenCorner::TopRight);
|
||||||
|
} else if (bottomRight.contains(e->pos())) {
|
||||||
|
setOverCorner(Notify::ScreenCorner::BottomRight);
|
||||||
|
} else if (bottomLeft.contains(e->pos())) {
|
||||||
|
setOverCorner(Notify::ScreenCorner::BottomLeft);
|
||||||
|
} else {
|
||||||
|
clearOverCorner();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotificationsBox::leaveEvent(QEvent *e) {
|
||||||
|
clearOverCorner();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotificationsBox::setOverCorner(Notify::ScreenCorner corner) {
|
||||||
|
if (_isOverCorner) {
|
||||||
|
if (corner == _overCorner) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for_const (auto widget, _cornerSamples[static_cast<int>(_overCorner)]) {
|
||||||
|
widget->hideFast();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_isOverCorner = true;
|
||||||
|
setCursor(style::cur_pointer);
|
||||||
|
Global::SetNotificationsDemoIsShown(true);
|
||||||
|
Global::RefNotifySettingsChanged().notify(Notify::ChangeType::DemoIsShown);
|
||||||
|
}
|
||||||
|
_overCorner = corner;
|
||||||
|
|
||||||
|
auto &samples = _cornerSamples[static_cast<int>(_overCorner)];
|
||||||
|
auto samplesAlready = samples.size();
|
||||||
|
auto samplesNeeded = currentCount();
|
||||||
|
auto samplesLeave = qMin(samplesAlready, samplesNeeded);
|
||||||
|
for (int i = 0; i != samplesLeave; ++i) {
|
||||||
|
samples[i]->showFast();
|
||||||
|
}
|
||||||
|
if (samplesNeeded > samplesLeave) {
|
||||||
|
auto r = psDesktopRect();
|
||||||
|
auto isLeft = Notify::IsLeftCorner(_overCorner);
|
||||||
|
auto isTop = Notify::IsTopCorner(_overCorner);
|
||||||
|
auto sampleLeft = (isLeft == rtl()) ? (r.x() + r.width() - st::notifyWidth - st::notifyDeltaX) : (r.x() + st::notifyDeltaX);
|
||||||
|
auto sampleTop = isTop ? (r.y() + st::notifyDeltaY) : (r.y() + r.height() - st::notifyDeltaY - st::notifyMinHeight);
|
||||||
|
for (int i = samplesLeave; i != samplesNeeded; ++i) {
|
||||||
|
auto widget = std_::make_unique<SampleWidget>(this, _notificationSampleLarge);
|
||||||
|
widget->move(sampleLeft, sampleTop + (isTop ? 1 : -1) * i * (st::notifyMinHeight + st::notifyDeltaY));
|
||||||
|
widget->showFast();
|
||||||
|
samples.push_back(widget.release());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = samplesLeave; i != samplesAlready; ++i) {
|
||||||
|
samples[i]->hideFast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotificationsBox::clearOverCorner() {
|
||||||
|
if (_isOverCorner) {
|
||||||
|
_isOverCorner = false;
|
||||||
|
setCursor(style::cur_default);
|
||||||
|
Global::SetNotificationsDemoIsShown(false);
|
||||||
|
Global::RefNotifySettingsChanged().notify(Notify::ChangeType::DemoIsShown);
|
||||||
|
|
||||||
|
for_const (auto &samples, _cornerSamples) {
|
||||||
|
for_const (auto widget, samples) {
|
||||||
|
widget->hideFast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int NotificationsBox::currentCount() const {
|
||||||
|
return _countSlider->activeSection() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotificationsBox::mousePressEvent(QMouseEvent *e) {
|
||||||
|
_isDownCorner = _isOverCorner;
|
||||||
|
_downCorner = _overCorner;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotificationsBox::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
|
auto isDownCorner = base::take(_isDownCorner);
|
||||||
|
if (isDownCorner && _isOverCorner && _downCorner == _overCorner && _downCorner != _chosenCorner) {
|
||||||
|
_chosenCorner = _downCorner;
|
||||||
|
update();
|
||||||
|
|
||||||
|
if (_chosenCorner != Global::NotificationsCorner()) {
|
||||||
|
Global::SetNotificationsCorner(_chosenCorner);
|
||||||
|
Global::RefNotifySettingsChanged().notify(Notify::ChangeType::Corner);
|
||||||
|
Local::writeUserSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NotificationsBox::~NotificationsBox() {
|
||||||
|
for_const (auto &samples, _cornerSamples) {
|
||||||
|
for_const (auto widget, samples) {
|
||||||
|
widget->detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clearOverCorner();
|
||||||
|
}
|
79
Telegram/SourceFiles/boxes/notifications_box.h
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||||
|
|
||||||
|
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
It is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
In addition, as a special exception, the copyright holders give permission
|
||||||
|
to link the code of portions of this program with the OpenSSL library.
|
||||||
|
|
||||||
|
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||||
|
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "abstractbox.h"
|
||||||
|
|
||||||
|
class BoxButton;
|
||||||
|
class LinkButton;
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class DiscreteSlider;
|
||||||
|
} // namespace Ui
|
||||||
|
|
||||||
|
class NotificationsBox : public AbstractBox {
|
||||||
|
public:
|
||||||
|
NotificationsBox();
|
||||||
|
~NotificationsBox();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
void resizeEvent(QResizeEvent *e) override;
|
||||||
|
void mousePressEvent(QMouseEvent *e) override;
|
||||||
|
void mouseMoveEvent(QMouseEvent *e) override;
|
||||||
|
void leaveEvent(QEvent *e) override;
|
||||||
|
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
using ScreenCorner = Notify::ScreenCorner;
|
||||||
|
void countChanged();
|
||||||
|
void setOverCorner(ScreenCorner corner);
|
||||||
|
void clearOverCorner();
|
||||||
|
|
||||||
|
class SampleWidget;
|
||||||
|
void removeSample(SampleWidget *widget);
|
||||||
|
|
||||||
|
int currentCount() const;
|
||||||
|
|
||||||
|
QRect getScreenRect() const;
|
||||||
|
int getContentLeft() const;
|
||||||
|
void prepareNotificationSampleSmall();
|
||||||
|
void prepareNotificationSampleLarge();
|
||||||
|
void prepareNotificationSampleUserpic();
|
||||||
|
|
||||||
|
QPixmap _notificationSampleUserpic;
|
||||||
|
QPixmap _notificationSampleSmall;
|
||||||
|
QPixmap _notificationSampleLarge;
|
||||||
|
ScreenCorner _chosenCorner;
|
||||||
|
std_::vector_of_moveable<FloatAnimation> _sampleOpacities;
|
||||||
|
|
||||||
|
bool _isOverCorner = false;
|
||||||
|
ScreenCorner _overCorner = ScreenCorner::TopLeft;
|
||||||
|
bool _isDownCorner = false;
|
||||||
|
ScreenCorner _downCorner = ScreenCorner::TopLeft;
|
||||||
|
|
||||||
|
int _oldCount;
|
||||||
|
ChildWidget<Ui::DiscreteSlider> _countSlider;
|
||||||
|
ChildWidget<BoxButton> _done;
|
||||||
|
|
||||||
|
QVector<SampleWidget*> _cornerSamples[4];
|
||||||
|
|
||||||
|
};
|
|
@ -83,11 +83,11 @@ void ReportBox::onChange() {
|
||||||
connect(_reasonOtherText, SIGNAL(submitted(bool)), this, SLOT(onReport()));
|
connect(_reasonOtherText, SIGNAL(submitted(bool)), this, SLOT(onReport()));
|
||||||
connect(_reasonOtherText, SIGNAL(cancelled()), this, SLOT(onClose()));
|
connect(_reasonOtherText, SIGNAL(cancelled()), this, SLOT(onClose()));
|
||||||
}
|
}
|
||||||
|
_reasonOtherText->setFocus();
|
||||||
} else if (_reasonOtherText) {
|
} else if (_reasonOtherText) {
|
||||||
_reasonOtherText.destroy();
|
_reasonOtherText.destroy();
|
||||||
updateMaxHeight();
|
updateMaxHeight();
|
||||||
}
|
}
|
||||||
_reasonOtherText->setFocus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReportBox::doSetInnerFocus() {
|
void ReportBox::doSetInnerFocus() {
|
||||||
|
|
|
@ -21,6 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "abstractbox.h"
|
#include "abstractbox.h"
|
||||||
|
#include "core/single_timer.h"
|
||||||
|
|
||||||
class ConfirmBox;
|
class ConfirmBox;
|
||||||
|
|
||||||
|
|
|
@ -337,7 +337,7 @@ private:
|
||||||
int _dragging = -1;
|
int _dragging = -1;
|
||||||
int _above = -1;
|
int _above = -1;
|
||||||
|
|
||||||
BoxShadow _aboveShadow;
|
Ui::RectShadow _aboveShadow;
|
||||||
|
|
||||||
int32 _scrollbar = 0;
|
int32 _scrollbar = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -769,10 +769,6 @@ structure::Value ParsedFile::readIconValue() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parts.empty()) {
|
|
||||||
logErrorUnexpectedToken() << "at least one icon part";
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return { structure::data::icon { parts } };
|
return { structure::data::icon { parts } };
|
||||||
}
|
}
|
||||||
file_.putBack();
|
file_.putBack();
|
||||||
|
|
|
@ -97,9 +97,6 @@ enum {
|
||||||
MediaOverviewStartPerPage = 5,
|
MediaOverviewStartPerPage = 5,
|
||||||
MediaOverviewPreloadCount = 4,
|
MediaOverviewPreloadCount = 4,
|
||||||
|
|
||||||
// a new message from the same sender is attached to previous within 15 minutes
|
|
||||||
AttachMessageToPreviousSecondsDelta = 900,
|
|
||||||
|
|
||||||
AudioSimultaneousLimit = 4,
|
AudioSimultaneousLimit = 4,
|
||||||
AudioCheckPositionTimeout = 100, // 100ms per check audio pos
|
AudioCheckPositionTimeout = 100, // 100ms per check audio pos
|
||||||
AudioCheckPositionDelta = 2400, // update position called each 2400 samples
|
AudioCheckPositionDelta = 2400, // update position called each 2400 samples
|
||||||
|
@ -215,7 +212,7 @@ Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+\n\
|
||||||
8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n\n\
|
8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n\n\
|
||||||
Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB\n\
|
Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB\n\
|
||||||
-----END RSA PUBLIC KEY-----"};
|
-----END RSA PUBLIC KEY-----"};
|
||||||
keysCount = arraysize(keys);
|
keysCount = base::array_size(keys);
|
||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,6 +289,10 @@ static const int32 ApiId = 17349;
|
||||||
static const char *ApiHash = "344583e45741c457fe1862106095a5eb";
|
static const char *ApiHash = "344583e45741c457fe1862106095a5eb";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
|
||||||
|
#error "Only little endian is supported!"
|
||||||
|
#endif // Q_BYTE_ORDER == Q_BIG_ENDIAN
|
||||||
|
|
||||||
#ifndef BETA_VERSION_MACRO
|
#ifndef BETA_VERSION_MACRO
|
||||||
#error "Beta version macro is not defined."
|
#error "Beta version macro is not defined."
|
||||||
#endif
|
#endif
|
||||||
|
@ -375,9 +376,7 @@ enum {
|
||||||
WaitForChannelGetDifference = 1000, // 1s wait after show channel history before sending getChannelDifference
|
WaitForChannelGetDifference = 1000, // 1s wait after show channel history before sending getChannelDifference
|
||||||
|
|
||||||
MemoryForImageCache = 64 * 1024 * 1024, // after 64mb of unpacked images we try to clear some memory
|
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
|
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
|
UpdateChunk = 100 * 1024, // 100kb parts when downloading the update
|
||||||
IdleMsecs = 60 * 1000, // after 60secs without user input we think we are idle
|
IdleMsecs = 60 * 1000, // after 60secs without user input we think we are idle
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#include "core/qthelp_regex.h"
|
#include "core/qthelp_regex.h"
|
||||||
#include "core/qthelp_url.h"
|
#include "core/qthelp_url.h"
|
||||||
#include "localstorage.h"
|
#include "localstorage.h"
|
||||||
|
#include "ui/popupmenu.h"
|
||||||
|
|
||||||
QString UrlClickHandler::copyToClipboardContextItemText() const {
|
QString UrlClickHandler::copyToClipboardContextItemText() const {
|
||||||
return lang(isEmail() ? lng_context_copy_email : lng_context_copy_link);
|
return lang(isEmail() ? lng_context_copy_email : lng_context_copy_link);
|
||||||
|
|
|
@ -20,9 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef OS_MAC_OLD
|
#include "core/stl_subset.h"
|
||||||
#include <memory>
|
|
||||||
#endif // OS_MAC_OLD
|
|
||||||
|
|
||||||
namespace base {
|
namespace base {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
@ -392,191 +390,3 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace base
|
} // namespace base
|
||||||
|
|
||||||
// While we still use rpcDone() and rpcFail()
|
|
||||||
|
|
||||||
#include "mtproto/rpc_sender.h"
|
|
||||||
|
|
||||||
template <typename FunctionType>
|
|
||||||
struct LambdaUniqueHelper;
|
|
||||||
|
|
||||||
template <typename Lambda, typename R, typename ...Args>
|
|
||||||
struct LambdaUniqueHelper<R(Lambda::*)(Args...) const> {
|
|
||||||
using UniqueType = base::lambda_unique<R(Args...)>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename FunctionType>
|
|
||||||
using LambdaGetUnique = typename LambdaUniqueHelper<FunctionType>::UniqueType;
|
|
||||||
|
|
||||||
template <typename Base, typename FunctionType>
|
|
||||||
class RPCHandlerImplementation : public Base {
|
|
||||||
protected:
|
|
||||||
using Lambda = base::lambda_unique<FunctionType>;
|
|
||||||
using Parent = RPCHandlerImplementation<Base, FunctionType>;
|
|
||||||
|
|
||||||
public:
|
|
||||||
RPCHandlerImplementation(Lambda &&handler) : _handler(std_::move(handler)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Lambda _handler;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename FunctionType>
|
|
||||||
using RPCDoneHandlerImplementation = RPCHandlerImplementation<RPCAbstractDoneHandler, FunctionType>;
|
|
||||||
|
|
||||||
template <typename R>
|
|
||||||
class RPCDoneHandlerImplementationBare : public RPCDoneHandlerImplementation<R(const mtpPrime*, const mtpPrime*)> { // done(from, end)
|
|
||||||
public:
|
|
||||||
using RPCDoneHandlerImplementation<R(const mtpPrime*, const mtpPrime*)>::Parent::Parent;
|
|
||||||
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) const override {
|
|
||||||
return this->_handler ? this->_handler(from, end) : void(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename R>
|
|
||||||
class RPCDoneHandlerImplementationBareReq : public RPCDoneHandlerImplementation<R(const mtpPrime*, const mtpPrime*, mtpRequestId)> { // done(from, end, req_id)
|
|
||||||
public:
|
|
||||||
using RPCDoneHandlerImplementation<R(const mtpPrime*, const mtpPrime*, mtpRequestId)>::Parent::Parent;
|
|
||||||
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) const override {
|
|
||||||
return this->_handler ? this->_handler(from, end, requestId) : void(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename R, typename T>
|
|
||||||
class RPCDoneHandlerImplementationPlain : public RPCDoneHandlerImplementation<R(const T&)> { // done(result)
|
|
||||||
public:
|
|
||||||
using RPCDoneHandlerImplementation<R(const T&)>::Parent::Parent;
|
|
||||||
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) const override {
|
|
||||||
return this->_handler ? this->_handler(T(from, end)) : void(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename R, typename T>
|
|
||||||
class RPCDoneHandlerImplementationReq : public RPCDoneHandlerImplementation<R(const T&, mtpRequestId)> { // done(result, req_id)
|
|
||||||
public:
|
|
||||||
using RPCDoneHandlerImplementation<R(const T&, mtpRequestId)>::Parent::Parent;
|
|
||||||
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) const override {
|
|
||||||
return this->_handler ? this->_handler(T(from, end), requestId) : void(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename R>
|
|
||||||
class RPCDoneHandlerImplementationNo : public RPCDoneHandlerImplementation<R()> { // done()
|
|
||||||
public:
|
|
||||||
using RPCDoneHandlerImplementation<R()>::Parent::Parent;
|
|
||||||
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) const override {
|
|
||||||
return this->_handler ? this->_handler() : void(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename R>
|
|
||||||
class RPCDoneHandlerImplementationNoReq : public RPCDoneHandlerImplementation<R(mtpRequestId)> { // done(req_id)
|
|
||||||
public:
|
|
||||||
using RPCDoneHandlerImplementation<R(mtpRequestId)>::Parent::Parent;
|
|
||||||
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) const override {
|
|
||||||
return this->_handler ? this->_handler(requestId) : void(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename R>
|
|
||||||
inline RPCDoneHandlerPtr rpcDone_lambda_wrap_helper(base::lambda_unique<R(const mtpPrime*, const mtpPrime*)> &&lambda) {
|
|
||||||
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationBare<R>(std_::move(lambda)));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename R>
|
|
||||||
inline RPCDoneHandlerPtr rpcDone_lambda_wrap_helper(base::lambda_unique<R(const mtpPrime*, const mtpPrime*, mtpRequestId)> &&lambda) {
|
|
||||||
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationBareReq<R>(std_::move(lambda)));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename R, typename T>
|
|
||||||
inline RPCDoneHandlerPtr rpcDone_lambda_wrap_helper(base::lambda_unique<R(const T&)> &&lambda) {
|
|
||||||
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationPlain<R, T>(std_::move(lambda)));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename R, typename T>
|
|
||||||
inline RPCDoneHandlerPtr rpcDone_lambda_wrap_helper(base::lambda_unique<R(const T&, mtpRequestId)> &&lambda) {
|
|
||||||
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationReq<R, T>(std_::move(lambda)));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename R>
|
|
||||||
inline RPCDoneHandlerPtr rpcDone_lambda_wrap_helper(base::lambda_unique<R()> &&lambda) {
|
|
||||||
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationNo<R>(std_::move(lambda)));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename R>
|
|
||||||
inline RPCDoneHandlerPtr rpcDone_lambda_wrap_helper(base::lambda_unique<R(mtpRequestId)> &&lambda) {
|
|
||||||
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationNoReq<R>(std_::move(lambda)));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Lambda, typename = std_::enable_if_t<std_::is_rvalue_reference<Lambda&&>::value>>
|
|
||||||
RPCDoneHandlerPtr rpcDone(Lambda &&lambda) {
|
|
||||||
return rpcDone_lambda_wrap_helper(LambdaGetUnique<decltype(&Lambda::operator())>(std_::move(lambda)));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename FunctionType>
|
|
||||||
using RPCFailHandlerImplementation = RPCHandlerImplementation<RPCAbstractFailHandler, FunctionType>;
|
|
||||||
|
|
||||||
class RPCFailHandlerImplementationPlain : public RPCFailHandlerImplementation<bool(const RPCError&)> { // fail(error)
|
|
||||||
public:
|
|
||||||
using Parent::Parent;
|
|
||||||
bool operator()(mtpRequestId requestId, const RPCError &error) const override {
|
|
||||||
return _handler ? _handler(error) : true;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class RPCFailHandlerImplementationReq : public RPCFailHandlerImplementation<bool(const RPCError&, mtpRequestId)> { // fail(error, req_id)
|
|
||||||
public:
|
|
||||||
using Parent::Parent;
|
|
||||||
bool operator()(mtpRequestId requestId, const RPCError &error) const override {
|
|
||||||
return this->_handler ? this->_handler(error, requestId) : true;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class RPCFailHandlerImplementationNo : public RPCFailHandlerImplementation<bool()> { // fail()
|
|
||||||
public:
|
|
||||||
using Parent::Parent;
|
|
||||||
bool operator()(mtpRequestId requestId, const RPCError &error) const override {
|
|
||||||
return this->_handler ? this->_handler() : true;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class RPCFailHandlerImplementationNoReq : public RPCFailHandlerImplementation<bool(mtpRequestId)> { // fail(req_id)
|
|
||||||
public:
|
|
||||||
using Parent::Parent;
|
|
||||||
bool operator()(mtpRequestId requestId, const RPCError &error) const override {
|
|
||||||
return this->_handler ? this->_handler(requestId) : true;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
inline RPCFailHandlerPtr rpcFail_lambda_wrap_helper(base::lambda_unique<bool(const RPCError&)> &&lambda) {
|
|
||||||
return RPCFailHandlerPtr(new RPCFailHandlerImplementationPlain(std_::move(lambda)));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline RPCFailHandlerPtr rpcFail_lambda_wrap_helper(base::lambda_unique<bool(const RPCError&, mtpRequestId)> &&lambda) {
|
|
||||||
return RPCFailHandlerPtr(new RPCFailHandlerImplementationReq(std_::move(lambda)));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline RPCFailHandlerPtr rpcFail_lambda_wrap_helper(base::lambda_unique<bool()> &&lambda) {
|
|
||||||
return RPCFailHandlerPtr(new RPCFailHandlerImplementationNo(std_::move(lambda)));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline RPCFailHandlerPtr rpcFail_lambda_wrap_helper(base::lambda_unique<bool(mtpRequestId)> &&lambda) {
|
|
||||||
return RPCFailHandlerPtr(new RPCFailHandlerImplementationNoReq(std_::move(lambda)));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Lambda, typename = std_::enable_if_t<std_::is_rvalue_reference<Lambda&&>::value>>
|
|
||||||
RPCFailHandlerPtr rpcFail(Lambda &&lambda) {
|
|
||||||
return rpcFail_lambda_wrap_helper(LambdaGetUnique<decltype(&Lambda::operator())>(std_::move(lambda)));
|
|
||||||
}
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ public:
|
||||||
Subscription() = default;
|
Subscription() = default;
|
||||||
Subscription(const Subscription &) = delete;
|
Subscription(const Subscription &) = delete;
|
||||||
Subscription &operator=(const Subscription &) = delete;
|
Subscription &operator=(const Subscription &) = delete;
|
||||||
Subscription(Subscription &&other) : _node(createAndSwap(other._node)), _removeMethod(other._removeMethod) {
|
Subscription(Subscription &&other) : _node(base::take(other._node)), _removeMethod(other._removeMethod) {
|
||||||
}
|
}
|
||||||
Subscription &operator=(Subscription &&other) {
|
Subscription &operator=(Subscription &&other) {
|
||||||
qSwap(_node, other._node);
|
qSwap(_node, other._node);
|
||||||
|
@ -258,7 +258,7 @@ public:
|
||||||
private:
|
private:
|
||||||
void callHandlers() {
|
void callHandlers() {
|
||||||
_handling = true;
|
_handling = true;
|
||||||
auto events = createAndSwap(_events);
|
auto events = base::take(_events);
|
||||||
for (auto &event : events) {
|
for (auto &event : events) {
|
||||||
this->notifyEnumerate([this, &event]() {
|
this->notifyEnumerate([this, &event]() {
|
||||||
this->_current->handler(event);
|
this->_current->handler(event);
|
||||||
|
@ -305,7 +305,7 @@ public:
|
||||||
private:
|
private:
|
||||||
void callHandlers() {
|
void callHandlers() {
|
||||||
_handling = true;
|
_handling = true;
|
||||||
auto eventsCount = createAndSwap(_eventsCount);
|
auto eventsCount = base::take(_eventsCount);
|
||||||
for (int i = 0; i != eventsCount; ++i) {
|
for (int i = 0; i != eventsCount; ++i) {
|
||||||
this->notifyEnumerate([this]() {
|
this->notifyEnumerate([this]() {
|
||||||
this->_current->handler();
|
this->_current->handler();
|
||||||
|
@ -352,7 +352,7 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
~Subscriber() {
|
~Subscriber() {
|
||||||
auto subscriptions = createAndSwap(_subscriptions);
|
auto subscriptions = base::take(_subscriptions);
|
||||||
for (auto &subscription : subscriptions) {
|
for (auto &subscription : subscriptions) {
|
||||||
subscription.destroy();
|
subscription.destroy();
|
||||||
}
|
}
|
||||||
|
|
80
Telegram/SourceFiles/core/single_timer.cpp
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||||
|
|
||||||
|
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
It is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
In addition, as a special exception, the copyright holders give permission
|
||||||
|
to link the code of portions of this program with the OpenSSL library.
|
||||||
|
|
||||||
|
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||||
|
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
*/
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "core/single_timer.h"
|
||||||
|
|
||||||
|
#include "application.h"
|
||||||
|
|
||||||
|
SingleTimer::SingleTimer() {
|
||||||
|
QTimer::setSingleShot(true);
|
||||||
|
if (App::app()) {
|
||||||
|
connect(App::app(), SIGNAL(adjustSingleTimers()), this, SLOT(adjust()));
|
||||||
|
_inited = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleTimer::setTimeoutHandler(base::lambda_unique<void()> &&handler) {
|
||||||
|
if (_handler && !handler) {
|
||||||
|
disconnect(this, SIGNAL(timeout()), this, SLOT(onTimeout()));
|
||||||
|
} else if (handler && !_handler) {
|
||||||
|
connect(this, SIGNAL(timeout()), this, SLOT(onTimeout()));
|
||||||
|
}
|
||||||
|
_handler = std_::move(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleTimer::adjust() {
|
||||||
|
uint64 n = getms(true);
|
||||||
|
if (isActive()) {
|
||||||
|
if (n >= _finishing) {
|
||||||
|
start(0);
|
||||||
|
} else {
|
||||||
|
start(_finishing - n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleTimer::onTimeout() {
|
||||||
|
if (_handler) {
|
||||||
|
_handler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleTimer::start(int msec) {
|
||||||
|
_finishing = getms(true) + (msec < 0 ? 0 : uint64(msec));
|
||||||
|
if (!_inited && App::app()) {
|
||||||
|
connect(App::app(), SIGNAL(adjustSingleTimers()), this, SLOT(adjust()));
|
||||||
|
_inited = true;
|
||||||
|
}
|
||||||
|
QTimer::start(msec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleTimer::startIfNotActive(int msec) {
|
||||||
|
if (isActive()) {
|
||||||
|
int remains = remainingTime();
|
||||||
|
if (remains > msec) {
|
||||||
|
start(msec);
|
||||||
|
} else if (!remains) {
|
||||||
|
start(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
start(msec);
|
||||||
|
}
|
||||||
|
}
|
50
Telegram/SourceFiles/core/single_timer.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||||
|
|
||||||
|
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
It is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
In addition, as a special exception, the copyright holders give permission
|
||||||
|
to link the code of portions of this program with the OpenSSL library.
|
||||||
|
|
||||||
|
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||||
|
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/basic_types.h"
|
||||||
|
#include "core/lambda_wrap.h"
|
||||||
|
|
||||||
|
class SingleTimer : public QTimer { // single shot timer with check
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
SingleTimer();
|
||||||
|
|
||||||
|
void setSingleShot(bool); // is not available
|
||||||
|
void start(); // is not available
|
||||||
|
|
||||||
|
void setTimeoutHandler(base::lambda_unique<void()> &&handler);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void start(int msec);
|
||||||
|
void startIfNotActive(int msec);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void adjust();
|
||||||
|
void onTimeout();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64 _finishing = 0;
|
||||||
|
bool _inited = false;
|
||||||
|
base::lambda_unique<void()> _handler;
|
||||||
|
|
||||||
|
};
|
|
@ -345,36 +345,6 @@ uint64 getms(bool checked) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SingleTimer::SingleTimer() : _finishing(0), _inited(false) {
|
|
||||||
QTimer::setSingleShot(true);
|
|
||||||
if (App::app()) {
|
|
||||||
connect(App::app(), SIGNAL(adjustSingleTimers()), this, SLOT(adjust()));
|
|
||||||
_inited = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SingleTimer::start(int msec) {
|
|
||||||
_finishing = getms(true) + (msec < 0 ? 0 : uint64(msec));
|
|
||||||
if (!_inited && App::app()) {
|
|
||||||
connect(App::app(), SIGNAL(adjustSingleTimers()), this, SLOT(adjust()));
|
|
||||||
_inited = true;
|
|
||||||
}
|
|
||||||
QTimer::start(msec);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SingleTimer::startIfNotActive(int msec) {
|
|
||||||
if (isActive()) {
|
|
||||||
int remains = remainingTime();
|
|
||||||
if (remains > msec) {
|
|
||||||
start(msec);
|
|
||||||
} else if (!remains) {
|
|
||||||
start(1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
start(msec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64 msgid() {
|
uint64 msgid() {
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
LARGE_INTEGER li;
|
LARGE_INTEGER li;
|
||||||
|
|
|
@ -22,23 +22,21 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
#include "core/basic_types.h"
|
#include "core/basic_types.h"
|
||||||
|
|
||||||
|
namespace base {
|
||||||
|
|
||||||
template <typename T, size_t N>
|
template <typename T, size_t N>
|
||||||
inline constexpr size_t arraysize(T(&ArrahSizeHelper)[N]) {
|
inline constexpr size_t array_size(T(&)[N]) {
|
||||||
return N;
|
return N;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void deleteAndMark(T *&link) {
|
inline T take(T &source) {
|
||||||
delete link;
|
T result = T();
|
||||||
link = reinterpret_cast<T*>(0x00000BAD);
|
std_::swap_moveable(result, source);
|
||||||
|
return std_::move(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
} // namespace base
|
||||||
T *getPointerAndReset(T *&ptr) {
|
|
||||||
T *result = nullptr;
|
|
||||||
qSwap(result, ptr);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Enum>
|
template <typename Enum>
|
||||||
inline QFlags<Enum> qFlags(Enum v) {
|
inline QFlags<Enum> qFlags(Enum v) {
|
||||||
|
@ -87,13 +85,6 @@ inline void accumulate_max(T &a, const T &b) { if (a < b) a = b; }
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline void accumulate_min(T &a, const T &b) { if (a > b) a = b; }
|
inline void accumulate_min(T &a, const T &b) { if (a > b) a = b; }
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T createAndSwap(T &value) {
|
|
||||||
T result = T();
|
|
||||||
std_::swap_moveable(result, value);
|
|
||||||
return std_::move(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static volatile int *t_assert_nullptr = nullptr;
|
static volatile int *t_assert_nullptr = nullptr;
|
||||||
inline void t_noop() {}
|
inline void t_noop() {}
|
||||||
inline void t_assert_fail(const char *message, const char *file, int32 line) {
|
inline void t_assert_fail(const char *message, const char *file, int32 line) {
|
||||||
|
@ -172,37 +163,6 @@ void finish();
|
||||||
bool checkms(); // returns true if time has changed
|
bool checkms(); // returns true if time has changed
|
||||||
uint64 getms(bool checked = false);
|
uint64 getms(bool checked = false);
|
||||||
|
|
||||||
class SingleTimer : public QTimer { // single shot timer with check
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
SingleTimer();
|
|
||||||
|
|
||||||
void setSingleShot(bool); // is not available
|
|
||||||
void start(); // is not available
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
|
|
||||||
void start(int msec);
|
|
||||||
void startIfNotActive(int msec);
|
|
||||||
void adjust() {
|
|
||||||
uint64 n = getms(true);
|
|
||||||
if (isActive()) {
|
|
||||||
if (n >= _finishing) {
|
|
||||||
start(0);
|
|
||||||
} else {
|
|
||||||
start(_finishing - n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint64 _finishing;
|
|
||||||
bool _inited;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const static uint32 _md5_block_size = 64;
|
const static uint32 _md5_block_size = 64;
|
||||||
class HashMd5 {
|
class HashMd5 {
|
||||||
public:
|
public:
|
||||||
|
@ -508,7 +468,7 @@ public:
|
||||||
return _p;
|
return _p;
|
||||||
}
|
}
|
||||||
T *release() {
|
T *release() {
|
||||||
return getPointerAndReset(_p);
|
return base::take(_p);
|
||||||
}
|
}
|
||||||
void reset(T *p = nullptr) {
|
void reset(T *p = nullptr) {
|
||||||
delete _p;
|
delete _p;
|
||||||
|
@ -551,7 +511,7 @@ public:
|
||||||
return _p;
|
return _p;
|
||||||
}
|
}
|
||||||
T *release() {
|
T *release() {
|
||||||
return getPointerAndReset(_p);
|
return base::take(_p);
|
||||||
}
|
}
|
||||||
void reset(T *p = nullptr) {
|
void reset(T *p = nullptr) {
|
||||||
delete _p;
|
delete _p;
|
||||||
|
|
|
@ -36,9 +36,9 @@ public:
|
||||||
vector_of_moveable(const vector_of_moveable &other) = delete;
|
vector_of_moveable(const vector_of_moveable &other) = delete;
|
||||||
vector_of_moveable &operator=(const vector_of_moveable &other) = delete;
|
vector_of_moveable &operator=(const vector_of_moveable &other) = delete;
|
||||||
vector_of_moveable(vector_of_moveable &&other)
|
vector_of_moveable(vector_of_moveable &&other)
|
||||||
: _size(createAndSwap(other._size))
|
: _size(base::take(other._size))
|
||||||
, _capacity(createAndSwap(other._capacity))
|
, _capacity(base::take(other._capacity))
|
||||||
, _plaindata(createAndSwap(other._plaindata)) {
|
, _plaindata(base::take(other._plaindata)) {
|
||||||
}
|
}
|
||||||
vector_of_moveable &operator=(vector_of_moveable &&other) {
|
vector_of_moveable &operator=(vector_of_moveable &&other) {
|
||||||
std_::swap_moveable(_size, other._size);
|
std_::swap_moveable(_size, other._size);
|
||||||
|
|
|
@ -22,9 +22,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
#include "core/utils.h"
|
#include "core/utils.h"
|
||||||
|
|
||||||
#define BETA_VERSION_MACRO (10008005ULL)
|
#define BETA_VERSION_MACRO (0ULL)
|
||||||
|
|
||||||
constexpr int AppVersion = 10008;
|
constexpr int AppVersion = 10013;
|
||||||
constexpr str_const AppVersionStr = "0.10.8";
|
constexpr str_const AppVersionStr = "0.10.13";
|
||||||
constexpr bool AppAlphaVersion = false;
|
constexpr bool AppAlphaVersion = true;
|
||||||
constexpr uint64 AppBetaVersion = BETA_VERSION_MACRO;
|
constexpr uint64 AppBetaVersion = BETA_VERSION_MACRO;
|
||||||
|
|
|
@ -25,6 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#include "dialogs/dialogs_layout.h"
|
#include "dialogs/dialogs_layout.h"
|
||||||
#include "styles/style_dialogs.h"
|
#include "styles/style_dialogs.h"
|
||||||
#include "ui/buttons/round_button.h"
|
#include "ui/buttons/round_button.h"
|
||||||
|
#include "ui/popupmenu.h"
|
||||||
#include "data/data_drafts.h"
|
#include "data/data_drafts.h"
|
||||||
#include "lang.h"
|
#include "lang.h"
|
||||||
#include "application.h"
|
#include "application.h"
|
||||||
|
@ -122,8 +123,8 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO
|
||||||
p.fillRect(0, 0, w, st::mentionHeight, (selected ? st::mentionBgOver : st::white)->b);
|
p.fillRect(0, 0, w, st::mentionHeight, (selected ? st::mentionBgOver : st::white)->b);
|
||||||
if (!paintingOther) {
|
if (!paintingOther) {
|
||||||
if (selected) {
|
if (selected) {
|
||||||
int skip = (st::mentionHeight - st::notifyClose.icon.pxHeight()) / 2;
|
int skip = (st::mentionHeight - st::simpleClose.icon.pxHeight()) / 2;
|
||||||
p.drawSprite(QPoint(w - st::notifyClose.icon.pxWidth() - skip, skip), st::notifyClose.icon);
|
p.drawSprite(QPoint(w - st::simpleClose.icon.pxWidth() - skip, skip), st::simpleClose.icon);
|
||||||
}
|
}
|
||||||
QString first = (_hashtagFilter.size() < 2) ? QString() : ('#' + _hashtagResults.at(from).mid(0, _hashtagFilter.size() - 1)), second = (_hashtagFilter.size() < 2) ? ('#' + _hashtagResults.at(from)) : _hashtagResults.at(from).mid(_hashtagFilter.size() - 1);
|
QString first = (_hashtagFilter.size() < 2) ? QString() : ('#' + _hashtagResults.at(from).mid(0, _hashtagFilter.size() - 1)), second = (_hashtagFilter.size() < 2) ? ('#' + _hashtagResults.at(from)) : _hashtagResults.at(from).mid(_hashtagFilter.size() - 1);
|
||||||
int32 firstwidth = st::mentionFont->width(first), secondwidth = st::mentionFont->width(second);
|
int32 firstwidth = st::mentionFont->width(first), secondwidth = st::mentionFont->width(second);
|
||||||
|
@ -478,7 +479,6 @@ void DialogsInner::removeDialog(History *history) {
|
||||||
if (importantDialogs) {
|
if (importantDialogs) {
|
||||||
history->removeFromChatList(Dialogs::Mode::Important, importantDialogs.get());
|
history->removeFromChatList(Dialogs::Mode::Important, importantDialogs.get());
|
||||||
}
|
}
|
||||||
history->clearNotifications();
|
|
||||||
if (App::wnd()) App::wnd()->notifyClear(history);
|
if (App::wnd()) App::wnd()->notifyClear(history);
|
||||||
if (contacts->contains(history->peer->id)) {
|
if (contacts->contains(history->peer->id)) {
|
||||||
if (!contactsNoDialogs->contains(history->peer->id)) {
|
if (!contactsNoDialogs->contains(history->peer->id)) {
|
||||||
|
|
|
@ -22,7 +22,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
#include "window/section_widget.h"
|
#include "window/section_widget.h"
|
||||||
|
|
||||||
class MainWidget;
|
|
||||||
namespace Dialogs {
|
namespace Dialogs {
|
||||||
class Row;
|
class Row;
|
||||||
class FakeRow;
|
class FakeRow;
|
||||||
|
@ -33,6 +32,9 @@ namespace Ui {
|
||||||
class RoundButton;
|
class RoundButton;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
|
class MainWidget;
|
||||||
|
class PopupMenu;
|
||||||
|
|
||||||
enum DialogsSearchRequestType {
|
enum DialogsSearchRequestType {
|
||||||
DialogsSearchFromStart,
|
DialogsSearchFromStart,
|
||||||
DialogsSearchFromOffset,
|
DialogsSearchFromOffset,
|
||||||
|
|
|
@ -122,7 +122,7 @@ void Dropdown::resizeEvent(QResizeEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dropdown::paintEvent(QPaintEvent *e) {
|
void Dropdown::paintEvent(QPaintEvent *e) {
|
||||||
QPainter p(this);
|
Painter p(this);
|
||||||
|
|
||||||
if (_a_appearance.animating()) {
|
if (_a_appearance.animating()) {
|
||||||
p.setOpacity(a_opacity.current());
|
p.setOpacity(a_opacity.current());
|
||||||
|
@ -358,7 +358,7 @@ void DragArea::setText(const QString &text, const QString &subtext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DragArea::paintEvent(QPaintEvent *e) {
|
void DragArea::paintEvent(QPaintEvent *e) {
|
||||||
QPainter p(this);
|
Painter p(this);
|
||||||
|
|
||||||
if (_a_appearance.animating()) {
|
if (_a_appearance.animating()) {
|
||||||
p.setOpacity(a_opacity.current());
|
p.setOpacity(a_opacity.current());
|
||||||
|
|
|
@ -21,7 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ui/twidget.h"
|
#include "ui/twidget.h"
|
||||||
#include "ui/boxshadow.h"
|
#include "ui/effects/rect_shadow.h"
|
||||||
|
|
||||||
class Dropdown : public TWidget {
|
class Dropdown : public TWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -91,7 +91,7 @@ private:
|
||||||
|
|
||||||
QTimer _hideTimer;
|
QTimer _hideTimer;
|
||||||
|
|
||||||
BoxShadow _shadow;
|
Ui::RectShadow _shadow;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -101,13 +101,6 @@ class DragArea : public TWidget {
|
||||||
public:
|
public:
|
||||||
DragArea(QWidget *parent);
|
DragArea(QWidget *parent);
|
||||||
|
|
||||||
void paintEvent(QPaintEvent *e);
|
|
||||||
void mouseMoveEvent(QMouseEvent *e);
|
|
||||||
void dragEnterEvent(QDragEnterEvent *e);
|
|
||||||
void dragLeaveEvent(QDragLeaveEvent *e);
|
|
||||||
void dropEvent(QDropEvent *e);
|
|
||||||
void dragMoveEvent(QDragMoveEvent *e);
|
|
||||||
|
|
||||||
void setText(const QString &text, const QString &subtext);
|
void setText(const QString &text, const QString &subtext);
|
||||||
|
|
||||||
void otherEnter();
|
void otherEnter();
|
||||||
|
@ -127,6 +120,14 @@ public:
|
||||||
).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()));
|
).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
void mouseMoveEvent(QMouseEvent *e) override;
|
||||||
|
void dragEnterEvent(QDragEnterEvent *e) override;
|
||||||
|
void dragLeaveEvent(QDragLeaveEvent *e) override;
|
||||||
|
void dropEvent(QDropEvent *e) override;
|
||||||
|
void dragMoveEvent(QDragMoveEvent *e) override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void dropped(const QMimeData *data);
|
void dropped(const QMimeData *data);
|
||||||
|
|
||||||
|
@ -143,7 +144,7 @@ private:
|
||||||
anim::cvalue a_color;
|
anim::cvalue a_color;
|
||||||
Animation _a_appearance;
|
Animation _a_appearance;
|
||||||
|
|
||||||
BoxShadow _shadow;
|
Ui::RectShadow _shadow;
|
||||||
|
|
||||||
QString _text, _subtext;
|
QString _text, _subtext;
|
||||||
|
|
||||||
|
|
|
@ -634,8 +634,10 @@ struct Data {
|
||||||
bool RestoreSoundNotifyFromTray = false;
|
bool RestoreSoundNotifyFromTray = false;
|
||||||
bool IncludeMuted = true;
|
bool IncludeMuted = true;
|
||||||
DBINotifyView NotifyView = dbinvShowPreview;
|
DBINotifyView NotifyView = dbinvShowPreview;
|
||||||
bool WindowsNotifications = true;
|
bool NativeNotifications = false;
|
||||||
bool CustomNotifies = (cPlatform() == dbipMac) ? false : true;
|
int NotificationsCount = 3;
|
||||||
|
Notify::ScreenCorner NotificationsCorner = Notify::ScreenCorner::BottomRight;
|
||||||
|
bool NotificationsDemoIsShown = false;
|
||||||
base::Observable<Notify::ChangeType> NotifySettingsChanged;
|
base::Observable<Notify::ChangeType> NotifySettingsChanged;
|
||||||
|
|
||||||
DBIConnectionType ConnectionType = dbictAuto;
|
DBIConnectionType ConnectionType = dbictAuto;
|
||||||
|
@ -742,8 +744,10 @@ DefineVar(Global, bool, DesktopNotify);
|
||||||
DefineVar(Global, bool, RestoreSoundNotifyFromTray);
|
DefineVar(Global, bool, RestoreSoundNotifyFromTray);
|
||||||
DefineVar(Global, bool, IncludeMuted);
|
DefineVar(Global, bool, IncludeMuted);
|
||||||
DefineVar(Global, DBINotifyView, NotifyView);
|
DefineVar(Global, DBINotifyView, NotifyView);
|
||||||
DefineVar(Global, bool, WindowsNotifications);
|
DefineVar(Global, bool, NativeNotifications);
|
||||||
DefineVar(Global, bool, CustomNotifies);
|
DefineVar(Global, int, NotificationsCount);
|
||||||
|
DefineVar(Global, Notify::ScreenCorner, NotificationsCorner);
|
||||||
|
DefineVar(Global, bool, NotificationsDemoIsShown);
|
||||||
DefineRefVar(Global, base::Observable<Notify::ChangeType>, NotifySettingsChanged);
|
DefineRefVar(Global, base::Observable<Notify::ChangeType>, NotifySettingsChanged);
|
||||||
|
|
||||||
DefineVar(Global, DBIConnectionType, ConnectionType);
|
DefineVar(Global, DBIConnectionType, ConnectionType);
|
||||||
|
|
|
@ -148,9 +148,26 @@ enum class ChangeType {
|
||||||
IncludeMuted,
|
IncludeMuted,
|
||||||
DesktopEnabled,
|
DesktopEnabled,
|
||||||
ViewParams,
|
ViewParams,
|
||||||
UseNative,
|
MaxCount,
|
||||||
|
Corner,
|
||||||
|
DemoIsShown,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ScreenCorner {
|
||||||
|
TopLeft = 0,
|
||||||
|
TopRight = 1,
|
||||||
|
BottomRight = 2,
|
||||||
|
BottomLeft = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool IsLeftCorner(ScreenCorner corner) {
|
||||||
|
return (corner == ScreenCorner::TopLeft) || (corner == ScreenCorner::BottomLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsTopCorner(ScreenCorner corner) {
|
||||||
|
return (corner == ScreenCorner::TopLeft) || (corner == ScreenCorner::TopRight);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Notify
|
} // namespace Notify
|
||||||
|
|
||||||
#define DeclareReadOnlyVar(Type, Name) const Type &Name();
|
#define DeclareReadOnlyVar(Type, Name) const Type &Name();
|
||||||
|
@ -309,8 +326,10 @@ DeclareVar(bool, DesktopNotify);
|
||||||
DeclareVar(bool, RestoreSoundNotifyFromTray);
|
DeclareVar(bool, RestoreSoundNotifyFromTray);
|
||||||
DeclareVar(bool, IncludeMuted);
|
DeclareVar(bool, IncludeMuted);
|
||||||
DeclareVar(DBINotifyView, NotifyView);
|
DeclareVar(DBINotifyView, NotifyView);
|
||||||
DeclareVar(bool, WindowsNotifications);
|
DeclareVar(bool, NativeNotifications);
|
||||||
DeclareVar(bool, CustomNotifies);
|
DeclareVar(int, NotificationsCount);
|
||||||
|
DeclareVar(Notify::ScreenCorner, NotificationsCorner);
|
||||||
|
DeclareVar(bool, NotificationsDemoIsShown);
|
||||||
DeclareRefVar(base::Observable<Notify::ChangeType>, NotifySettingsChanged);
|
DeclareRefVar(base::Observable<Notify::ChangeType>, NotifySettingsChanged);
|
||||||
|
|
||||||
DeclareVar(DBIConnectionType, ConnectionType);
|
DeclareVar(DBIConnectionType, ConnectionType);
|
||||||
|
|
|
@ -1427,7 +1427,6 @@ MsgId History::inboxRead(MsgId upTo) {
|
||||||
|
|
||||||
showFrom = nullptr;
|
showFrom = nullptr;
|
||||||
App::wnd()->notifyClear(this);
|
App::wnd()->notifyClear(this);
|
||||||
clearNotifications();
|
|
||||||
|
|
||||||
return upTo;
|
return upTo;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,13 +28,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
FieldAutocomplete::FieldAutocomplete(QWidget *parent) : TWidget(parent)
|
FieldAutocomplete::FieldAutocomplete(QWidget *parent) : TWidget(parent)
|
||||||
, _scroll(this, st::mentionScroll)
|
, _scroll(this, st::mentionScroll)
|
||||||
, _inner(this, &_mrows, &_hrows, &_brows, &_srows)
|
, _inner(this, &_mrows, &_hrows, &_brows, &_srows)
|
||||||
, _chat(0)
|
|
||||||
, _user(0)
|
|
||||||
, _channel(0)
|
|
||||||
, _hiding(false)
|
|
||||||
, a_opacity(0)
|
, a_opacity(0)
|
||||||
, _a_appearance(animation(this, &FieldAutocomplete::step_appearance))
|
, _a_appearance(animation(this, &FieldAutocomplete::step_appearance)) {
|
||||||
, _shadow(st::dropdownDef.shadow) {
|
|
||||||
_hideTimer.setSingleShot(true);
|
_hideTimer.setSingleShot(true);
|
||||||
connect(&_hideTimer, SIGNAL(timeout()), this, SLOT(hideStart()));
|
connect(&_hideTimer, SIGNAL(timeout()), this, SLOT(hideStart()));
|
||||||
|
|
||||||
|
@ -605,9 +600,9 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
|
||||||
bool selected = (i == _sel);
|
bool selected = (i == _sel);
|
||||||
if (selected) {
|
if (selected) {
|
||||||
p.fillRect(0, i * st::mentionHeight, width(), st::mentionHeight, st::mentionBgOver->b);
|
p.fillRect(0, i * st::mentionHeight, width(), st::mentionHeight, st::mentionBgOver->b);
|
||||||
int skip = (st::mentionHeight - st::notifyClose.icon.pxHeight()) / 2;
|
int skip = (st::mentionHeight - st::simpleClose.icon.pxHeight()) / 2;
|
||||||
if (!_hrows->isEmpty() || (!_mrows->isEmpty() && i < _recentInlineBotsInRows)) {
|
if (!_hrows->isEmpty() || (!_mrows->isEmpty() && i < _recentInlineBotsInRows)) {
|
||||||
p.drawSprite(QPoint(width() - st::notifyClose.icon.pxWidth() - skip, i * st::mentionHeight + skip), st::notifyClose.icon);
|
p.drawSprite(QPoint(width() - st::simpleClose.icon.pxWidth() - skip, i * st::mentionHeight + skip), st::simpleClose.icon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.setPen(st::black->p);
|
p.setPen(st::black->p);
|
||||||
|
|
|
@ -21,7 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ui/twidget.h"
|
#include "ui/twidget.h"
|
||||||
#include "ui/boxshadow.h"
|
#include "ui/effects/rect_shadow.h"
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
@ -91,9 +91,10 @@ public slots:
|
||||||
|
|
||||||
void showStart();
|
void showStart();
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
|
||||||
|
private:
|
||||||
void updateFiltered(bool resetScroll = false);
|
void updateFiltered(bool resetScroll = false);
|
||||||
void recount(bool resetScroll = false);
|
void recount(bool resetScroll = false);
|
||||||
|
|
||||||
|
@ -108,9 +109,9 @@ private:
|
||||||
ChildWidget<ScrollArea> _scroll;
|
ChildWidget<ScrollArea> _scroll;
|
||||||
ChildWidget<internal::FieldAutocompleteInner> _inner;
|
ChildWidget<internal::FieldAutocompleteInner> _inner;
|
||||||
|
|
||||||
ChatData *_chat;
|
ChatData *_chat = nullptr;
|
||||||
UserData *_user;
|
UserData *_user = nullptr;
|
||||||
ChannelData *_channel;
|
ChannelData *_channel = nullptr;
|
||||||
EmojiPtr _emoji;
|
EmojiPtr _emoji;
|
||||||
enum class Type {
|
enum class Type {
|
||||||
Mentions,
|
Mentions,
|
||||||
|
@ -124,14 +125,13 @@ private:
|
||||||
bool _addInlineBots;
|
bool _addInlineBots;
|
||||||
|
|
||||||
int32 _width, _height;
|
int32 _width, _height;
|
||||||
bool _hiding;
|
bool _hiding = false;
|
||||||
|
|
||||||
anim::fvalue a_opacity;
|
anim::fvalue a_opacity;
|
||||||
Animation _a_appearance;
|
Animation _a_appearance;
|
||||||
|
|
||||||
QTimer _hideTimer;
|
QTimer _hideTimer;
|
||||||
|
|
||||||
BoxShadow _shadow;
|
|
||||||
friend class internal::FieldAutocompleteInner;
|
friend class internal::FieldAutocompleteInner;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,6 +28,13 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#include "styles/style_dialogs.h"
|
#include "styles/style_dialogs.h"
|
||||||
#include "fileuploader.h"
|
#include "fileuploader.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// a new message from the same sender is attached to previous within 15 minutes
|
||||||
|
constexpr int kAttachMessageToPreviousSecondsDelta = 900;
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
ReplyMarkupClickHandler::ReplyMarkupClickHandler(const HistoryItem *item, int row, int col)
|
ReplyMarkupClickHandler::ReplyMarkupClickHandler(const HistoryItem *item, int row, int col)
|
||||||
: _itemId(item->fullId())
|
: _itemId(item->fullId())
|
||||||
, _row(row)
|
, _row(row)
|
||||||
|
@ -352,7 +359,7 @@ void HistoryMessageReplyMarkup::createFromButtonRows(const QVector<MTPKeyboardBu
|
||||||
if (!b.isEmpty()) {
|
if (!b.isEmpty()) {
|
||||||
ButtonRow buttonRow;
|
ButtonRow buttonRow;
|
||||||
buttonRow.reserve(b.size());
|
buttonRow.reserve(b.size());
|
||||||
for_const (const auto &button, b) {
|
for_const (auto &button, b) {
|
||||||
switch (button.type()) {
|
switch (button.type()) {
|
||||||
case mtpc_keyboardButton: {
|
case mtpc_keyboardButton: {
|
||||||
buttonRow.push_back({ Button::Type::Default, qs(button.c_keyboardButton().vtext), QByteArray(), 0 });
|
buttonRow.push_back({ Button::Type::Default, qs(button.c_keyboardButton().vtext), QByteArray(), 0 });
|
||||||
|
@ -401,31 +408,46 @@ void HistoryMessageReplyMarkup::create(const MTPReplyMarkup &markup) {
|
||||||
|
|
||||||
switch (markup.type()) {
|
switch (markup.type()) {
|
||||||
case mtpc_replyKeyboardMarkup: {
|
case mtpc_replyKeyboardMarkup: {
|
||||||
const auto &d(markup.c_replyKeyboardMarkup());
|
auto &d = markup.c_replyKeyboardMarkup();
|
||||||
flags = d.vflags.v;
|
flags = d.vflags.v;
|
||||||
|
|
||||||
createFromButtonRows(d.vrows.c_vector().v);
|
createFromButtonRows(d.vrows.c_vector().v);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case mtpc_replyInlineMarkup: {
|
case mtpc_replyInlineMarkup: {
|
||||||
const auto &d(markup.c_replyInlineMarkup());
|
auto &d = markup.c_replyInlineMarkup();
|
||||||
flags = MTPDreplyKeyboardMarkup::Flags(0) | MTPDreplyKeyboardMarkup_ClientFlag::f_inline;
|
flags = MTPDreplyKeyboardMarkup::Flags(0) | MTPDreplyKeyboardMarkup_ClientFlag::f_inline;
|
||||||
|
|
||||||
createFromButtonRows(d.vrows.c_vector().v);
|
createFromButtonRows(d.vrows.c_vector().v);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case mtpc_replyKeyboardHide: {
|
case mtpc_replyKeyboardHide: {
|
||||||
const auto &d(markup.c_replyKeyboardHide());
|
auto &d = markup.c_replyKeyboardHide();
|
||||||
flags = mtpCastFlags(d.vflags) | MTPDreplyKeyboardMarkup_ClientFlag::f_zero;
|
flags = mtpCastFlags(d.vflags) | MTPDreplyKeyboardMarkup_ClientFlag::f_zero;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case mtpc_replyKeyboardForceReply: {
|
case mtpc_replyKeyboardForceReply: {
|
||||||
const auto &d(markup.c_replyKeyboardForceReply());
|
auto &d = markup.c_replyKeyboardForceReply();
|
||||||
flags = mtpCastFlags(d.vflags) | MTPDreplyKeyboardMarkup_ClientFlag::f_force_reply;
|
flags = mtpCastFlags(d.vflags) | MTPDreplyKeyboardMarkup_ClientFlag::f_force_reply;
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HistoryMessageReplyMarkup::create(const HistoryMessageReplyMarkup &markup) {
|
||||||
|
flags = markup.flags;
|
||||||
|
inlineKeyboard = nullptr;
|
||||||
|
|
||||||
|
rows.clear();
|
||||||
|
for_const (auto &row, markup.rows) {
|
||||||
|
ButtonRow buttonRow;
|
||||||
|
buttonRow.reserve(row.size());
|
||||||
|
for_const (auto &button, row) {
|
||||||
|
buttonRow.push_back({ button.type, button.text, button.data, 0 });
|
||||||
|
}
|
||||||
|
if (!buttonRow.isEmpty()) rows.push_back(buttonRow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void HistoryMessageUnreadBar::init(int count) {
|
void HistoryMessageUnreadBar::init(int count) {
|
||||||
if (_freezed) return;
|
if (_freezed) return;
|
||||||
_text = lng_unread_bar(lt_count, count);
|
_text = lng_unread_bar(lt_count, count);
|
||||||
|
@ -482,19 +504,19 @@ void HistoryMediaPtr::reset(HistoryMedia *p) {
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
TextSelection unshiftSelection(TextSelection selection, const Text &byText) {
|
TextSelection unshiftSelection(TextSelection selection, const Text &byText) {
|
||||||
if (selection == FullSelection) {
|
if (selection == FullSelection) {
|
||||||
return selection;
|
return selection;
|
||||||
}
|
|
||||||
return ::unshiftSelection(selection, byText);
|
|
||||||
}
|
}
|
||||||
|
return ::unshiftSelection(selection, byText);
|
||||||
|
}
|
||||||
|
|
||||||
TextSelection shiftSelection(TextSelection selection, const Text &byText) {
|
TextSelection shiftSelection(TextSelection selection, const Text &byText) {
|
||||||
if (selection == FullSelection) {
|
if (selection == FullSelection) {
|
||||||
return selection;
|
return selection;
|
||||||
}
|
|
||||||
return ::shiftSelection(selection, byText);
|
|
||||||
}
|
}
|
||||||
|
return ::shiftSelection(selection, byText);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
|
@ -629,7 +651,7 @@ void HistoryItem::recountAttachToPrevious() {
|
||||||
&& !previos->serviceMsg()
|
&& !previos->serviceMsg()
|
||||||
&& !previos->isEmpty()
|
&& !previos->isEmpty()
|
||||||
&& previos->from() == from()
|
&& previos->from() == from()
|
||||||
&& (qAbs(previos->date.secsTo(date)) < AttachMessageToPreviousSecondsDelta);
|
&& (qAbs(previos->date.secsTo(date)) < kAttachMessageToPreviousSecondsDelta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (attach && !(_flags & MTPDmessage_ClientFlag::f_attach_to_previous)) {
|
if (attach && !(_flags & MTPDmessage_ClientFlag::f_attach_to_previous)) {
|
||||||
|
|
|
@ -199,6 +199,7 @@ struct HistoryMessageReplyMarkup : public RuntimeComponent<HistoryMessageReplyMa
|
||||||
}
|
}
|
||||||
|
|
||||||
void create(const MTPReplyMarkup &markup);
|
void create(const MTPReplyMarkup &markup);
|
||||||
|
void create(const HistoryMessageReplyMarkup &markup);
|
||||||
|
|
||||||
struct Button {
|
struct Button {
|
||||||
enum class Type {
|
enum class Type {
|
||||||
|
@ -436,8 +437,8 @@ private:
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
TextSelection unshiftSelection(TextSelection selection, const Text &byText);
|
TextSelection unshiftSelection(TextSelection selection, const Text &byText);
|
||||||
TextSelection shiftSelection(TextSelection selection, const Text &byText);
|
TextSelection shiftSelection(TextSelection selection, const Text &byText);
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
|
@ -758,13 +759,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
PeerData *fromOriginal() const {
|
PeerData *fromOriginal() const {
|
||||||
if (const HistoryMessageForwarded *fwd = Get<HistoryMessageForwarded>()) {
|
if (auto fwd = Get<HistoryMessageForwarded>()) {
|
||||||
return fwd->_fromOriginal;
|
return fwd->_fromOriginal;
|
||||||
}
|
}
|
||||||
return from();
|
return from();
|
||||||
}
|
}
|
||||||
PeerData *authorOriginal() const {
|
PeerData *authorOriginal() const {
|
||||||
if (const HistoryMessageForwarded *fwd = Get<HistoryMessageForwarded>()) {
|
if (auto fwd = Get<HistoryMessageForwarded>()) {
|
||||||
return fwd->_authorOriginal;
|
return fwd->_authorOriginal;
|
||||||
}
|
}
|
||||||
return author();
|
return author();
|
||||||
|
@ -837,7 +838,7 @@ public:
|
||||||
|
|
||||||
void clipCallback(Media::Clip::Notification notification);
|
void clipCallback(Media::Clip::Notification notification);
|
||||||
|
|
||||||
virtual ~HistoryItem();
|
~HistoryItem();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
HistoryItem(History *history, MsgId msgId, MTPDmessage::Flags flags, QDateTime msgDate, int32 from);
|
HistoryItem(History *history, MsgId msgId, MTPDmessage::Flags flags, QDateTime msgDate, int32 from);
|
||||||
|
@ -898,6 +899,12 @@ protected:
|
||||||
void recountAttachToPrevious();
|
void recountAttachToPrevious();
|
||||||
|
|
||||||
const HistoryMessageReplyMarkup *inlineReplyMarkup() const {
|
const HistoryMessageReplyMarkup *inlineReplyMarkup() const {
|
||||||
|
return const_cast<HistoryItem*>(this)->inlineReplyMarkup();
|
||||||
|
}
|
||||||
|
const ReplyKeyboard *inlineReplyKeyboard() const {
|
||||||
|
return const_cast<HistoryItem*>(this)->inlineReplyKeyboard();
|
||||||
|
}
|
||||||
|
HistoryMessageReplyMarkup *inlineReplyMarkup() {
|
||||||
if (auto markup = Get<HistoryMessageReplyMarkup>()) {
|
if (auto markup = Get<HistoryMessageReplyMarkup>()) {
|
||||||
if (markup->flags & MTPDreplyKeyboardMarkup_ClientFlag::f_inline) {
|
if (markup->flags & MTPDreplyKeyboardMarkup_ClientFlag::f_inline) {
|
||||||
return markup;
|
return markup;
|
||||||
|
@ -905,18 +912,12 @@ protected:
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
const ReplyKeyboard *inlineReplyKeyboard() const {
|
ReplyKeyboard *inlineReplyKeyboard() {
|
||||||
if (auto markup = inlineReplyMarkup()) {
|
if (auto markup = inlineReplyMarkup()) {
|
||||||
return markup->inlineKeyboard.get();
|
return markup->inlineKeyboard.get();
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
HistoryMessageReplyMarkup *inlineReplyMarkup() {
|
|
||||||
return const_cast<HistoryMessageReplyMarkup*>(static_cast<const HistoryItem*>(this)->inlineReplyMarkup());
|
|
||||||
}
|
|
||||||
ReplyKeyboard *inlineReplyKeyboard() {
|
|
||||||
return const_cast<ReplyKeyboard*>(static_cast<const HistoryItem*>(this)->inlineReplyKeyboard());
|
|
||||||
}
|
|
||||||
|
|
||||||
TextSelection toMediaSelection(TextSelection selection) const {
|
TextSelection toMediaSelection(TextSelection selection) const {
|
||||||
return internal::unshiftSelection(selection, _text);
|
return internal::unshiftSelection(selection, _text);
|
||||||
|
|
|
@ -232,7 +232,7 @@ void HistoryFileMedia::checkAnimationFinished() {
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryFileMedia::~HistoryFileMedia() {
|
HistoryFileMedia::~HistoryFileMedia() {
|
||||||
deleteAndMark(_animation);
|
delete base::take(_animation);
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryPhoto::HistoryPhoto(HistoryItem *parent, PhotoData *photo, const QString &caption) : HistoryFileMedia(parent)
|
HistoryPhoto::HistoryPhoto(HistoryItem *parent, PhotoData *photo, const QString &caption) : HistoryFileMedia(parent)
|
||||||
|
@ -2562,7 +2562,7 @@ int HistoryWebPage::resizeGetHeight(int width) {
|
||||||
return _height;
|
return _height;
|
||||||
}
|
}
|
||||||
|
|
||||||
_width = width = qMin(width, _maxw);
|
_width = width/* = qMin(width, _maxw)*/;
|
||||||
width -= st::msgPadding.left() + st::webPageLeft + st::msgPadding.right();
|
width -= st::msgPadding.left() + st::webPageLeft + st::msgPadding.right();
|
||||||
|
|
||||||
int32 linesMax = 5;
|
int32 linesMax = 5;
|
||||||
|
@ -2686,9 +2686,9 @@ void HistoryWebPage::draw(Painter &p, const QRect &r, TextSelection selection, u
|
||||||
} else {
|
} else {
|
||||||
pix = _data->photo->thumb->pixBlurredSingle(ImageRoundRadius::Small, pixw, pixh, pw, ph);
|
pix = _data->photo->thumb->pixBlurredSingle(ImageRoundRadius::Small, pixw, pixh, pw, ph);
|
||||||
}
|
}
|
||||||
p.drawPixmapLeft(padding.left() + width - pw, 0, _width, pix);
|
p.drawPixmapLeft(padding.left() + width - pw, tshift, _width, pix);
|
||||||
if (selected) {
|
if (selected) {
|
||||||
App::roundRect(p, rtlrect(padding.left() + width - pw, 0, pw, _pixh, _width), textstyleCurrent()->selectOverlay, SelectedOverlaySmallCorners);
|
App::roundRect(p, rtlrect(padding.left() + width - pw, tshift, pw, _pixh, _width), textstyleCurrent()->selectOverlay, SelectedOverlaySmallCorners);
|
||||||
}
|
}
|
||||||
width -= pw + st::webPagePhotoDelta;
|
width -= pw + st::webPagePhotoDelta;
|
||||||
}
|
}
|
||||||
|
|
|
@ -309,7 +309,7 @@ struct HistoryDocumentVoice : public RuntimeComponent<HistoryDocumentVoice> {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
~HistoryDocumentVoice() {
|
~HistoryDocumentVoice() {
|
||||||
deleteAndMark(_playback);
|
delete base::take(_playback);
|
||||||
}
|
}
|
||||||
void ensurePlayback(const HistoryDocument *interfaces) const;
|
void ensurePlayback(const HistoryDocument *interfaces) const;
|
||||||
void checkPlaybackFinished() const;
|
void checkPlaybackFinished() const;
|
||||||
|
|
|
@ -366,7 +366,7 @@ HistoryMessage::HistoryMessage(History *history, const MTPDmessage &msg)
|
||||||
CreateConfig config;
|
CreateConfig config;
|
||||||
|
|
||||||
if (msg.has_fwd_from() && msg.vfwd_from.type() == mtpc_messageFwdHeader) {
|
if (msg.has_fwd_from() && msg.vfwd_from.type() == mtpc_messageFwdHeader) {
|
||||||
const auto &f(msg.vfwd_from.c_messageFwdHeader());
|
auto &f = msg.vfwd_from.c_messageFwdHeader();
|
||||||
if (f.has_from_id() || f.has_channel_id()) {
|
if (f.has_from_id() || f.has_channel_id()) {
|
||||||
config.authorIdOriginal = f.has_channel_id() ? peerFromChannel(f.vchannel_id) : peerFromUser(f.vfrom_id);
|
config.authorIdOriginal = f.has_channel_id() ? peerFromChannel(f.vchannel_id) : peerFromUser(f.vfrom_id);
|
||||||
config.fromIdOriginal = f.has_from_id() ? peerFromUser(f.vfrom_id) : peerFromChannel(f.vchannel_id);
|
config.fromIdOriginal = f.has_from_id() ? peerFromUser(f.vfrom_id) : peerFromChannel(f.vchannel_id);
|
||||||
|
@ -376,7 +376,7 @@ HistoryMessage::HistoryMessage(History *history, const MTPDmessage &msg)
|
||||||
if (msg.has_reply_to_msg_id()) config.replyTo = msg.vreply_to_msg_id.v;
|
if (msg.has_reply_to_msg_id()) config.replyTo = msg.vreply_to_msg_id.v;
|
||||||
if (msg.has_via_bot_id()) config.viaBotId = msg.vvia_bot_id.v;
|
if (msg.has_via_bot_id()) config.viaBotId = msg.vvia_bot_id.v;
|
||||||
if (msg.has_views()) config.viewsCount = msg.vviews.v;
|
if (msg.has_views()) config.viewsCount = msg.vviews.v;
|
||||||
if (msg.has_reply_markup()) config.markup = &msg.vreply_markup;
|
if (msg.has_reply_markup()) config.mtpMarkup = &msg.vreply_markup;
|
||||||
if (msg.has_edit_date()) config.editDate = ::date(msg.vedit_date);
|
if (msg.has_edit_date()) config.editDate = ::date(msg.vedit_date);
|
||||||
|
|
||||||
createComponents(config);
|
createComponents(config);
|
||||||
|
@ -435,9 +435,15 @@ HistoryMessage::HistoryMessage(History *history, MsgId id, MTPDmessage::Flags fl
|
||||||
config.viewsCount = 1;
|
config.viewsCount = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy inline keyboard when forwarding messages with a game.
|
||||||
|
auto mediaOriginal = fwd->getMedia();
|
||||||
|
if (mediaOriginal && mediaOriginal->type() == MediaTypeGame) {
|
||||||
|
config.inlineMarkup = fwd->inlineReplyMarkup();
|
||||||
|
}
|
||||||
|
|
||||||
createComponents(config);
|
createComponents(config);
|
||||||
|
|
||||||
if (HistoryMedia *mediaOriginal = fwd->getMedia()) {
|
if (mediaOriginal) {
|
||||||
_media.reset(mediaOriginal->clone(this));
|
_media.reset(mediaOriginal->clone(this));
|
||||||
}
|
}
|
||||||
setText(fwd->originalText());
|
setText(fwd->originalText());
|
||||||
|
@ -479,7 +485,7 @@ void HistoryMessage::createComponentsHelper(MTPDmessage::Flags flags, MsgId repl
|
||||||
|
|
||||||
if (flags & MTPDmessage::Flag::f_via_bot_id) config.viaBotId = viaBotId;
|
if (flags & MTPDmessage::Flag::f_via_bot_id) config.viaBotId = viaBotId;
|
||||||
if (flags & MTPDmessage::Flag::f_reply_to_msg_id) config.replyTo = replyTo;
|
if (flags & MTPDmessage::Flag::f_reply_to_msg_id) config.replyTo = replyTo;
|
||||||
if (flags & MTPDmessage::Flag::f_reply_markup) config.markup = &markup;
|
if (flags & MTPDmessage::Flag::f_reply_markup) config.mtpMarkup = &markup;
|
||||||
if (isPost()) config.viewsCount = 1;
|
if (isPost()) config.viewsCount = 1;
|
||||||
|
|
||||||
createComponents(config);
|
createComponents(config);
|
||||||
|
@ -518,8 +524,10 @@ void HistoryMessage::updateMediaInBubbleState() {
|
||||||
_media->setInBubbleState(computeState());
|
_media->setInBubbleState(computeState());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryMessage::displayEditedBadge(bool hasViaBot) const {
|
bool HistoryMessage::displayEditedBadge(bool hasViaBotOrInlineMarkup) const {
|
||||||
if (!(_flags & MTPDmessage::Flag::f_edit_date)) {
|
if (hasViaBotOrInlineMarkup) {
|
||||||
|
return false;
|
||||||
|
} else if (!(_flags & MTPDmessage::Flag::f_edit_date)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (auto fromUser = from()->asUser()) {
|
if (auto fromUser = from()->asUser()) {
|
||||||
|
@ -527,9 +535,6 @@ bool HistoryMessage::displayEditedBadge(bool hasViaBot) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hasViaBot) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -548,20 +553,31 @@ void HistoryMessage::createComponents(const CreateConfig &config) {
|
||||||
if (isPost() && _from->isUser()) {
|
if (isPost() && _from->isUser()) {
|
||||||
mask |= HistoryMessageSigned::Bit();
|
mask |= HistoryMessageSigned::Bit();
|
||||||
}
|
}
|
||||||
if (displayEditedBadge(config.viaBotId != 0)) {
|
auto hasViaBot = (config.viaBotId != 0);
|
||||||
|
auto hasInlineMarkup = [&config] {
|
||||||
|
if (config.mtpMarkup) {
|
||||||
|
return (config.mtpMarkup->type() == mtpc_replyInlineMarkup);
|
||||||
|
}
|
||||||
|
return (config.inlineMarkup != nullptr);
|
||||||
|
};
|
||||||
|
if (displayEditedBadge(hasViaBot || hasInlineMarkup())) {
|
||||||
mask |= HistoryMessageEdited::Bit();
|
mask |= HistoryMessageEdited::Bit();
|
||||||
}
|
}
|
||||||
if (config.authorIdOriginal && config.fromIdOriginal) {
|
if (config.authorIdOriginal && config.fromIdOriginal) {
|
||||||
mask |= HistoryMessageForwarded::Bit();
|
mask |= HistoryMessageForwarded::Bit();
|
||||||
}
|
}
|
||||||
if (config.markup) {
|
if (config.mtpMarkup) {
|
||||||
// optimization: don't create markup component for the case
|
// optimization: don't create markup component for the case
|
||||||
// MTPDreplyKeyboardHide with flags = 0, assume it has f_zero flag
|
// MTPDreplyKeyboardHide with flags = 0, assume it has f_zero flag
|
||||||
if (config.markup->type() != mtpc_replyKeyboardHide || config.markup->c_replyKeyboardHide().vflags.v != 0) {
|
if (config.mtpMarkup->type() != mtpc_replyKeyboardHide || config.mtpMarkup->c_replyKeyboardHide().vflags.v != 0) {
|
||||||
mask |= HistoryMessageReplyMarkup::Bit();
|
mask |= HistoryMessageReplyMarkup::Bit();
|
||||||
}
|
}
|
||||||
|
} else if (config.inlineMarkup) {
|
||||||
|
mask |= HistoryMessageReplyMarkup::Bit();
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateComponents(mask);
|
UpdateComponents(mask);
|
||||||
|
|
||||||
if (auto reply = Get<HistoryMessageReply>()) {
|
if (auto reply = Get<HistoryMessageReply>()) {
|
||||||
reply->replyToMsgId = config.replyTo;
|
reply->replyToMsgId = config.replyTo;
|
||||||
if (!reply->updateData(this) && App::api()) {
|
if (!reply->updateData(this) && App::api()) {
|
||||||
|
@ -586,7 +602,11 @@ void HistoryMessage::createComponents(const CreateConfig &config) {
|
||||||
fwd->_originalId = config.originalId;
|
fwd->_originalId = config.originalId;
|
||||||
}
|
}
|
||||||
if (auto markup = Get<HistoryMessageReplyMarkup>()) {
|
if (auto markup = Get<HistoryMessageReplyMarkup>()) {
|
||||||
markup->create(*config.markup);
|
if (config.mtpMarkup) {
|
||||||
|
markup->create(*config.mtpMarkup);
|
||||||
|
} else if (config.inlineMarkup) {
|
||||||
|
markup->create(*config.inlineMarkup);
|
||||||
|
}
|
||||||
if (markup->flags & MTPDreplyKeyboardMarkup_ClientFlag::f_has_switch_inline_button) {
|
if (markup->flags & MTPDreplyKeyboardMarkup_ClientFlag::f_has_switch_inline_button) {
|
||||||
_flags |= MTPDmessage_ClientFlag::f_has_switch_inline_button;
|
_flags |= MTPDmessage_ClientFlag::f_has_switch_inline_button;
|
||||||
}
|
}
|
||||||
|
@ -829,7 +849,9 @@ void HistoryMessage::applyEdition(const MTPDmessage &message) {
|
||||||
|
|
||||||
if (message.has_edit_date()) {
|
if (message.has_edit_date()) {
|
||||||
_flags |= MTPDmessage::Flag::f_edit_date;
|
_flags |= MTPDmessage::Flag::f_edit_date;
|
||||||
if (displayEditedBadge(Has<HistoryMessageVia>())) {
|
auto hasViaBotId = Has<HistoryMessageVia>();
|
||||||
|
auto hasInlineMarkup = (inlineReplyMarkup() != nullptr);
|
||||||
|
if (displayEditedBadge(hasViaBotId || hasInlineMarkup)) {
|
||||||
if (!Has<HistoryMessageEdited>()) {
|
if (!Has<HistoryMessageEdited>()) {
|
||||||
AddComponents(HistoryMessageEdited::Bit());
|
AddComponents(HistoryMessageEdited::Bit());
|
||||||
}
|
}
|
||||||
|
@ -1808,7 +1830,7 @@ void HistoryService::setMessageByAction(const MTPmessageAction &action) {
|
||||||
case mtpc_messageActionChannelCreate: {
|
case mtpc_messageActionChannelCreate: {
|
||||||
auto &d = action.c_messageActionChannelCreate();
|
auto &d = action.c_messageActionChannelCreate();
|
||||||
if (isPost()) {
|
if (isPost()) {
|
||||||
text = lng_action_created_channel(lt_title, textClean(qs(d.vtitle)));
|
text = lang(lng_action_created_channel);
|
||||||
} else {
|
} else {
|
||||||
text = lng_action_created_chat(lt_from, from, lt_title, textClean(qs(d.vtitle)));
|
text = lng_action_created_chat(lt_from, from, lt_title, textClean(qs(d.vtitle)));
|
||||||
}
|
}
|
||||||
|
@ -2009,12 +2031,21 @@ bool HistoryService::prepareGameScoreText(const QString &from, QString *outText,
|
||||||
gameTitle = lang(lng_contacts_loading);
|
gameTitle = lang(lng_contacts_loading);
|
||||||
result = true;
|
result = true;
|
||||||
} else {
|
} else {
|
||||||
gameTitle = lang(lng_deleted_message);
|
gameTitle = QString();
|
||||||
}
|
}
|
||||||
|
auto scoreNumber = gamescore ? gamescore->score : 0;
|
||||||
if (_from->isSelf()) {
|
if (_from->isSelf()) {
|
||||||
*outText = lng_action_game_you_scored(lt_count, gamescore->score, lt_game, gameTitle);
|
if (gameTitle.isEmpty()) {
|
||||||
|
*outText = lng_action_game_you_scored_no_game(lt_count, scoreNumber);
|
||||||
|
} else {
|
||||||
|
*outText = lng_action_game_you_scored(lt_count, scoreNumber, lt_game, gameTitle);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
*outText = lng_action_game_score(lt_from, from, lt_count, gamescore->score, lt_game, gameTitle);
|
if (gameTitle.isEmpty()) {
|
||||||
|
*outText = lng_action_game_score_no_game(lt_from, from, lt_count, scoreNumber);
|
||||||
|
} else {
|
||||||
|
*outText = lng_action_game_score(lt_from, from, lt_count, scoreNumber, lt_game, gameTitle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (second) {
|
if (second) {
|
||||||
outLinks->push_back(second);
|
outLinks->push_back(second);
|
||||||
|
@ -2212,12 +2243,13 @@ HistoryTextState HistoryService::getState(int x, int y, HistoryStateRequest requ
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryService::createFromMtp(const MTPDmessageService &message) {
|
void HistoryService::createFromMtp(const MTPDmessageService &message) {
|
||||||
|
if (message.vaction.type() == mtpc_messageActionGameScore) {
|
||||||
|
UpdateComponents(HistoryServiceGameScore::Bit());
|
||||||
|
Get<HistoryServiceGameScore>()->score = message.vaction.c_messageActionGameScore().vscore.v;
|
||||||
|
}
|
||||||
if (message.has_reply_to_msg_id()) {
|
if (message.has_reply_to_msg_id()) {
|
||||||
if (message.vaction.type() == mtpc_messageActionPinMessage) {
|
if (message.vaction.type() == mtpc_messageActionPinMessage) {
|
||||||
UpdateComponents(HistoryServicePinned::Bit());
|
UpdateComponents(HistoryServicePinned::Bit());
|
||||||
} else if (message.vaction.type() == mtpc_messageActionGameScore) {
|
|
||||||
UpdateComponents(HistoryServiceGameScore::Bit());
|
|
||||||
Get<HistoryServiceGameScore>()->score = message.vaction.c_messageActionGameScore().vscore.v;
|
|
||||||
}
|
}
|
||||||
if (auto dependent = GetDependentData()) {
|
if (auto dependent = GetDependentData()) {
|
||||||
dependent->msgId = message.vreply_to_msg_id.v;
|
dependent->msgId = message.vreply_to_msg_id.v;
|
||||||
|
|
|
@ -63,7 +63,7 @@ public:
|
||||||
|
|
||||||
return (!emptyText() || !_media || !_media->isDisplayed() || Has<HistoryMessageReply>() || Has<HistoryMessageForwarded>() || viaBot() || !_media->hideFromName());
|
return (!emptyText() || !_media || !_media->isDisplayed() || Has<HistoryMessageReply>() || Has<HistoryMessageForwarded>() || viaBot() || !_media->hideFromName());
|
||||||
}
|
}
|
||||||
bool displayEditedBadge(bool hasViaBot) const;
|
bool displayEditedBadge(bool hasViaBotOrInlineMarkup) const;
|
||||||
bool uploading() const {
|
bool uploading() const {
|
||||||
return _media && _media->uploading();
|
return _media && _media->uploading();
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,12 @@ private:
|
||||||
PeerId fromIdOriginal = 0;
|
PeerId fromIdOriginal = 0;
|
||||||
MsgId originalId = 0;
|
MsgId originalId = 0;
|
||||||
QDateTime editDate;
|
QDateTime editDate;
|
||||||
const MTPReplyMarkup *markup = nullptr;
|
|
||||||
|
// For messages created from MTP structs.
|
||||||
|
const MTPReplyMarkup *mtpMarkup = nullptr;
|
||||||
|
|
||||||
|
// For messages created from existing messages (forwarded).
|
||||||
|
const HistoryMessageReplyMarkup *inlineMarkup = nullptr;
|
||||||
};
|
};
|
||||||
void createComponentsHelper(MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, const MTPReplyMarkup &markup);
|
void createComponentsHelper(MTPDmessage::Flags flags, MsgId replyTo, int32 viaBotId, const MTPReplyMarkup &markup);
|
||||||
void createComponents(const CreateConfig &config);
|
void createComponents(const CreateConfig &config);
|
||||||
|
|
|
@ -2638,85 +2638,53 @@ void BotKeyboard::updateSelected() {
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryHider::HistoryHider(MainWidget *parent, bool forwardSelected) : TWidget(parent)
|
HistoryHider::HistoryHider(MainWidget *parent, bool forwardSelected) : TWidget(parent)
|
||||||
, _sharedContact(0)
|
|
||||||
, _forwardSelected(forwardSelected)
|
, _forwardSelected(forwardSelected)
|
||||||
, _sendPath(false)
|
|
||||||
, _send(this, lang(lng_forward_send), st::defaultBoxButton)
|
, _send(this, lang(lng_forward_send), st::defaultBoxButton)
|
||||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
||||||
, offered(0)
|
|
||||||
, a_opacity(0, 1)
|
, a_opacity(0, 1)
|
||||||
, _a_appearance(animation(this, &HistoryHider::step_appearance))
|
, _a_appearance(animation(this, &HistoryHider::step_appearance))
|
||||||
, hiding(false)
|
, _shadow(st::boxShadow) {
|
||||||
, _forwardRequest(0)
|
|
||||||
, toTextWidth(0)
|
|
||||||
, shadow(st::boxShadow) {
|
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryHider::HistoryHider(MainWidget *parent, UserData *sharedContact) : TWidget(parent)
|
HistoryHider::HistoryHider(MainWidget *parent, UserData *sharedContact) : TWidget(parent)
|
||||||
, _sharedContact(sharedContact)
|
, _sharedContact(sharedContact)
|
||||||
, _forwardSelected(false)
|
|
||||||
, _sendPath(false)
|
|
||||||
, _send(this, lang(lng_forward_send), st::defaultBoxButton)
|
, _send(this, lang(lng_forward_send), st::defaultBoxButton)
|
||||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
||||||
, offered(0)
|
|
||||||
, a_opacity(0, 1)
|
, a_opacity(0, 1)
|
||||||
, _a_appearance(animation(this, &HistoryHider::step_appearance))
|
, _a_appearance(animation(this, &HistoryHider::step_appearance))
|
||||||
, hiding(false)
|
, _shadow(st::boxShadow) {
|
||||||
, _forwardRequest(0)
|
|
||||||
, toTextWidth(0)
|
|
||||||
, shadow(st::boxShadow) {
|
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryHider::HistoryHider(MainWidget *parent) : TWidget(parent)
|
HistoryHider::HistoryHider(MainWidget *parent) : TWidget(parent)
|
||||||
, _sharedContact(0)
|
|
||||||
, _forwardSelected(false)
|
|
||||||
, _sendPath(true)
|
, _sendPath(true)
|
||||||
, _send(this, lang(lng_forward_send), st::defaultBoxButton)
|
, _send(this, lang(lng_forward_send), st::defaultBoxButton)
|
||||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
||||||
, offered(0)
|
|
||||||
, a_opacity(0, 1)
|
, a_opacity(0, 1)
|
||||||
, _a_appearance(animation(this, &HistoryHider::step_appearance))
|
, _a_appearance(animation(this, &HistoryHider::step_appearance))
|
||||||
, hiding(false)
|
, _shadow(st::boxShadow) {
|
||||||
, _forwardRequest(0)
|
|
||||||
, toTextWidth(0)
|
|
||||||
, shadow(st::boxShadow) {
|
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryHider::HistoryHider(MainWidget *parent, const QString &botAndQuery) : TWidget(parent)
|
HistoryHider::HistoryHider(MainWidget *parent, const QString &botAndQuery) : TWidget(parent)
|
||||||
, _sharedContact(0)
|
|
||||||
, _forwardSelected(false)
|
|
||||||
, _sendPath(false)
|
|
||||||
, _botAndQuery(botAndQuery)
|
, _botAndQuery(botAndQuery)
|
||||||
, _send(this, lang(lng_forward_send), st::defaultBoxButton)
|
, _send(this, lang(lng_forward_send), st::defaultBoxButton)
|
||||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
||||||
, offered(0)
|
|
||||||
, a_opacity(0, 1)
|
, a_opacity(0, 1)
|
||||||
, _a_appearance(animation(this, &HistoryHider::step_appearance))
|
, _a_appearance(animation(this, &HistoryHider::step_appearance))
|
||||||
, hiding(false)
|
, _shadow(st::boxShadow) {
|
||||||
, _forwardRequest(0)
|
|
||||||
, toTextWidth(0)
|
|
||||||
, shadow(st::boxShadow) {
|
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryHider::HistoryHider(MainWidget *parent, const QString &url, const QString &text) : TWidget(parent)
|
HistoryHider::HistoryHider(MainWidget *parent, const QString &url, const QString &text) : TWidget(parent)
|
||||||
, _sharedContact(0)
|
|
||||||
, _forwardSelected(false)
|
|
||||||
, _sendPath(false)
|
|
||||||
, _shareUrl(url)
|
, _shareUrl(url)
|
||||||
, _shareText(text)
|
, _shareText(text)
|
||||||
, _send(this, lang(lng_forward_send), st::defaultBoxButton)
|
, _send(this, lang(lng_forward_send), st::defaultBoxButton)
|
||||||
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
|
||||||
, offered(0)
|
|
||||||
, a_opacity(0, 1)
|
, a_opacity(0, 1)
|
||||||
, _a_appearance(animation(this, &HistoryHider::step_appearance))
|
, _a_appearance(animation(this, &HistoryHider::step_appearance))
|
||||||
, hiding(false)
|
, _shadow(st::boxShadow) {
|
||||||
, _forwardRequest(0)
|
|
||||||
, toTextWidth(0)
|
|
||||||
, shadow(st::boxShadow) {
|
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2736,7 +2704,7 @@ void HistoryHider::step_appearance(float64 ms, bool timer) {
|
||||||
if (dt >= 1) {
|
if (dt >= 1) {
|
||||||
_a_appearance.stop();
|
_a_appearance.stop();
|
||||||
a_opacity.finish();
|
a_opacity.finish();
|
||||||
if (hiding) {
|
if (_hiding) {
|
||||||
QTimer::singleShot(0, this, SLOT(deleteLater()));
|
QTimer::singleShot(0, this, SLOT(deleteLater()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2752,45 +2720,45 @@ bool HistoryHider::withConfirm() const {
|
||||||
|
|
||||||
void HistoryHider::paintEvent(QPaintEvent *e) {
|
void HistoryHider::paintEvent(QPaintEvent *e) {
|
||||||
Painter p(this);
|
Painter p(this);
|
||||||
if (!hiding || !cacheForAnim.isNull() || !offered) {
|
if (!_hiding || !_cacheForAnim.isNull() || !_offered) {
|
||||||
p.setOpacity(a_opacity.current() * st::layerAlpha);
|
p.setOpacity(a_opacity.current() * st::layerAlpha);
|
||||||
p.fillRect(rect(), st::layerBg->b);
|
p.fillRect(rect(), st::layerBg->b);
|
||||||
p.setOpacity(a_opacity.current());
|
p.setOpacity(a_opacity.current());
|
||||||
}
|
}
|
||||||
if (cacheForAnim.isNull() || !offered) {
|
if (_cacheForAnim.isNull() || !_offered) {
|
||||||
p.setFont(st::forwardFont->f);
|
p.setFont(st::forwardFont);
|
||||||
if (offered) {
|
if (_offered) {
|
||||||
shadow.paint(p, box, st::boxShadowShift);
|
_shadow.paint(p, _box, st::boxShadowShift);
|
||||||
|
|
||||||
// fill bg
|
// fill bg
|
||||||
p.fillRect(box, st::boxBg->b);
|
p.fillRect(_box, st::boxBg);
|
||||||
|
|
||||||
p.setPen(st::black->p);
|
p.setPen(st::black);
|
||||||
toText.drawElided(p, box.left() + st::boxPadding.left(), box.top() + st::boxPadding.top(), toTextWidth + 2);
|
_toText.drawElided(p, _box.left() + st::boxPadding.left(), _box.top() + st::boxPadding.top(), _toTextWidth + 2);
|
||||||
} else {
|
} else {
|
||||||
int32 w = st::forwardMargins.left() + _chooseWidth + st::forwardMargins.right(), h = st::forwardMargins.top() + st::forwardFont->height + st::forwardMargins.bottom();
|
int32 w = st::forwardMargins.left() + _chooseWidth + st::forwardMargins.right(), h = st::forwardMargins.top() + st::forwardFont->height + st::forwardMargins.bottom();
|
||||||
App::roundRect(p, (width() - w) / 2, (height() - st::titleHeight - h) / 2, w, h, st::forwardBg, ForwardCorners);
|
App::roundRect(p, (width() - w) / 2, (height() - st::titleHeight - h) / 2, w, h, st::forwardBg, ForwardCorners);
|
||||||
|
|
||||||
p.setPen(st::white->p);
|
p.setPen(st::white);
|
||||||
p.drawText(box, lang(_botAndQuery.isEmpty() ? lng_forward_choose : lng_inline_switch_choose), QTextOption(style::al_center));
|
p.drawText(_box, lang(_botAndQuery.isEmpty() ? lng_forward_choose : lng_inline_switch_choose), QTextOption(style::al_center));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
p.drawPixmap(box.left(), box.top(), cacheForAnim);
|
p.drawPixmap(_box.left(), _box.top(), _cacheForAnim);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryHider::keyPressEvent(QKeyEvent *e) {
|
void HistoryHider::keyPressEvent(QKeyEvent *e) {
|
||||||
if (e->key() == Qt::Key_Escape) {
|
if (e->key() == Qt::Key_Escape) {
|
||||||
if (offered) {
|
if (_offered) {
|
||||||
offered = 0;
|
_offered = nullptr;
|
||||||
resizeEvent(0);
|
resizeEvent(nullptr);
|
||||||
update();
|
update();
|
||||||
App::main()->dialogsActivate();
|
App::main()->dialogsActivate();
|
||||||
} else {
|
} else {
|
||||||
startHide();
|
startHide();
|
||||||
}
|
}
|
||||||
} else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
|
} else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
|
||||||
if (offered) {
|
if (_offered) {
|
||||||
forward();
|
forward();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2798,19 +2766,19 @@ void HistoryHider::keyPressEvent(QKeyEvent *e) {
|
||||||
|
|
||||||
void HistoryHider::mousePressEvent(QMouseEvent *e) {
|
void HistoryHider::mousePressEvent(QMouseEvent *e) {
|
||||||
if (e->button() == Qt::LeftButton) {
|
if (e->button() == Qt::LeftButton) {
|
||||||
if (!box.contains(e->pos())) {
|
if (!_box.contains(e->pos())) {
|
||||||
startHide();
|
startHide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryHider::startHide() {
|
void HistoryHider::startHide() {
|
||||||
if (hiding) return;
|
if (_hiding) return;
|
||||||
hiding = true;
|
_hiding = true;
|
||||||
if (Adaptive::OneColumn()) {
|
if (Adaptive::OneColumn()) {
|
||||||
QTimer::singleShot(0, this, SLOT(deleteLater()));
|
QTimer::singleShot(0, this, SLOT(deleteLater()));
|
||||||
} else {
|
} else {
|
||||||
if (offered) cacheForAnim = myGrab(this, box);
|
if (_offered) _cacheForAnim = myGrab(this, _box);
|
||||||
if (_forwardRequest) MTP::cancel(_forwardRequest);
|
if (_forwardRequest) MTP::cancel(_forwardRequest);
|
||||||
a_opacity.start(0);
|
a_opacity.start(0);
|
||||||
_send.hide();
|
_send.hide();
|
||||||
|
@ -2820,17 +2788,17 @@ void HistoryHider::startHide() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryHider::forward() {
|
void HistoryHider::forward() {
|
||||||
if (!hiding && offered) {
|
if (!_hiding && _offered) {
|
||||||
if (_sharedContact) {
|
if (_sharedContact) {
|
||||||
parent()->onShareContact(offered->id, _sharedContact);
|
parent()->onShareContact(_offered->id, _sharedContact);
|
||||||
} else if (_sendPath) {
|
} else if (_sendPath) {
|
||||||
parent()->onSendPaths(offered->id);
|
parent()->onSendPaths(_offered->id);
|
||||||
} else if (!_shareUrl.isEmpty()) {
|
} else if (!_shareUrl.isEmpty()) {
|
||||||
parent()->onShareUrl(offered->id, _shareUrl, _shareText);
|
parent()->onShareUrl(_offered->id, _shareUrl, _shareText);
|
||||||
} else if (!_botAndQuery.isEmpty()) {
|
} else if (!_botAndQuery.isEmpty()) {
|
||||||
parent()->onInlineSwitchChosen(offered->id, _botAndQuery);
|
parent()->onInlineSwitchChosen(_offered->id, _botAndQuery);
|
||||||
} else {
|
} else {
|
||||||
parent()->onForward(offered->id, _forwardSelected ? ForwardSelectedMessages : ForwardContextMessage);
|
parent()->onForward(_offered->id, _forwardSelected ? ForwardSelectedMessages : ForwardContextMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emit forwarded();
|
emit forwarded();
|
||||||
|
@ -2847,8 +2815,8 @@ MainWidget *HistoryHider::parent() {
|
||||||
|
|
||||||
void HistoryHider::resizeEvent(QResizeEvent *e) {
|
void HistoryHider::resizeEvent(QResizeEvent *e) {
|
||||||
int32 w = st::boxWidth, h = st::boxPadding.top() + st::boxPadding.bottom();
|
int32 w = st::boxWidth, h = st::boxPadding.top() + st::boxPadding.bottom();
|
||||||
if (offered) {
|
if (_offered) {
|
||||||
if (!hiding) {
|
if (!_hiding) {
|
||||||
_send.show();
|
_send.show();
|
||||||
_cancel.show();
|
_cancel.show();
|
||||||
}
|
}
|
||||||
|
@ -2858,22 +2826,22 @@ void HistoryHider::resizeEvent(QResizeEvent *e) {
|
||||||
_send.hide();
|
_send.hide();
|
||||||
_cancel.hide();
|
_cancel.hide();
|
||||||
}
|
}
|
||||||
box = QRect((width() - w) / 2, (height() - st::titleHeight - h) / 2, w, h);
|
_box = QRect((width() - w) / 2, (height() - st::titleHeight - h) / 2, w, h);
|
||||||
_send.moveToRight(width() - (box.x() + box.width()) + st::boxButtonPadding.right(), box.y() + h - st::boxButtonPadding.bottom() - _send.height());
|
_send.moveToRight(width() - (_box.x() + _box.width()) + st::boxButtonPadding.right(), _box.y() + h - st::boxButtonPadding.bottom() - _send.height());
|
||||||
_cancel.moveToRight(width() - (box.x() + box.width()) + st::boxButtonPadding.right() + _send.width() + st::boxButtonPadding.left(), _send.y());
|
_cancel.moveToRight(width() - (_box.x() + _box.width()) + st::boxButtonPadding.right() + _send.width() + st::boxButtonPadding.left(), _send.y());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryHider::offerPeer(PeerId peer) {
|
bool HistoryHider::offerPeer(PeerId peer) {
|
||||||
if (!peer) {
|
if (!peer) {
|
||||||
offered = 0;
|
_offered = nullptr;
|
||||||
toText.setText(st::boxTextFont, QString());
|
_toText.setText(st::boxTextFont, QString());
|
||||||
toTextWidth = 0;
|
_toTextWidth = 0;
|
||||||
resizeEvent(0);
|
resizeEvent(nullptr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
offered = App::peer(peer);
|
_offered = App::peer(peer);
|
||||||
LangString phrase;
|
LangString phrase;
|
||||||
QString recipient = offered->isUser() ? offered->name : '\xAB' + offered->name + '\xBB';
|
QString recipient = _offered->isUser() ? _offered->name : '\xAB' + _offered->name + '\xBB';
|
||||||
if (_sharedContact) {
|
if (_sharedContact) {
|
||||||
phrase = lng_forward_share_contact(lt_recipient, recipient);
|
phrase = lng_forward_share_contact(lt_recipient, recipient);
|
||||||
} else if (_sendPath) {
|
} else if (_sendPath) {
|
||||||
|
@ -2887,35 +2855,35 @@ bool HistoryHider::offerPeer(PeerId peer) {
|
||||||
phrase = lng_forward_send_file_confirm(lt_name, name, lt_recipient, recipient);
|
phrase = lng_forward_send_file_confirm(lt_name, name, lt_recipient, recipient);
|
||||||
}
|
}
|
||||||
} else if (!_shareUrl.isEmpty()) {
|
} else if (!_shareUrl.isEmpty()) {
|
||||||
PeerId to = offered->id;
|
PeerId to = _offered->id;
|
||||||
offered = 0;
|
_offered = nullptr;
|
||||||
if (parent()->onShareUrl(to, _shareUrl, _shareText)) {
|
if (parent()->onShareUrl(to, _shareUrl, _shareText)) {
|
||||||
startHide();
|
startHide();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} else if (!_botAndQuery.isEmpty()) {
|
} else if (!_botAndQuery.isEmpty()) {
|
||||||
PeerId to = offered->id;
|
PeerId to = _offered->id;
|
||||||
offered = 0;
|
_offered = nullptr;
|
||||||
if (parent()->onInlineSwitchChosen(to, _botAndQuery)) {
|
if (parent()->onInlineSwitchChosen(to, _botAndQuery)) {
|
||||||
startHide();
|
startHide();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
PeerId to = offered->id;
|
PeerId to = _offered->id;
|
||||||
offered = 0;
|
_offered = nullptr;
|
||||||
if (parent()->onForward(to, _forwardSelected ? ForwardSelectedMessages : ForwardContextMessage)) {
|
if (parent()->onForward(to, _forwardSelected ? ForwardSelectedMessages : ForwardContextMessage)) {
|
||||||
startHide();
|
startHide();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
toText.setText(st::boxTextFont, phrase, _textNameOptions);
|
_toText.setText(st::boxTextFont, phrase, _textNameOptions);
|
||||||
toTextWidth = toText.maxWidth();
|
_toTextWidth = _toText.maxWidth();
|
||||||
if (toTextWidth > box.width() - st::boxPadding.left() - st::boxButtonPadding.right()) {
|
if (_toTextWidth > _box.width() - st::boxPadding.left() - st::boxButtonPadding.right()) {
|
||||||
toTextWidth = box.width() - st::boxPadding.left() - st::boxButtonPadding.right();
|
_toTextWidth = _box.width() - st::boxPadding.left() - st::boxButtonPadding.right();
|
||||||
}
|
}
|
||||||
|
|
||||||
resizeEvent(0);
|
resizeEvent(nullptr);
|
||||||
update();
|
update();
|
||||||
setFocus();
|
setFocus();
|
||||||
|
|
||||||
|
@ -2923,11 +2891,11 @@ bool HistoryHider::offerPeer(PeerId peer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QString HistoryHider::offeredText() const {
|
QString HistoryHider::offeredText() const {
|
||||||
return toText.originalText();
|
return _toText.originalText();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryHider::wasOffered() const {
|
bool HistoryHider::wasOffered() const {
|
||||||
return !!offered;
|
return _offered != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryHider::~HistoryHider() {
|
HistoryHider::~HistoryHider() {
|
||||||
|
@ -3404,7 +3372,7 @@ void HistoryWidget::writeDrafts(Data::Draft **localDraft, Data::Draft **editDraf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_editMsgId) {
|
if (!_editMsgId && !_inlineBot) {
|
||||||
_saveCloudDraftTimer.start(SaveCloudDraftIdleTimeout);
|
_saveCloudDraftTimer.start(SaveCloudDraftIdleTimeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6017,7 +5985,6 @@ bool HistoryWidget::hasSilentToggle() const {
|
||||||
void HistoryWidget::inlineBotResolveDone(const MTPcontacts_ResolvedPeer &result) {
|
void HistoryWidget::inlineBotResolveDone(const MTPcontacts_ResolvedPeer &result) {
|
||||||
_inlineBotResolveRequestId = 0;
|
_inlineBotResolveRequestId = 0;
|
||||||
// Notify::inlineBotRequesting(false);
|
// Notify::inlineBotRequesting(false);
|
||||||
_inlineBotUsername = QString();
|
|
||||||
UserData *resolvedBot = nullptr;
|
UserData *resolvedBot = nullptr;
|
||||||
if (result.type() == mtpc_contacts_resolvedPeer) {
|
if (result.type() == mtpc_contacts_resolvedPeer) {
|
||||||
const auto &d(result.c_contacts_resolvedPeer());
|
const auto &d(result.c_contacts_resolvedPeer());
|
||||||
|
@ -8895,6 +8862,6 @@ bool HistoryWidget::touchScroll(const QPoint &delta) {
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryWidget::~HistoryWidget() {
|
HistoryWidget::~HistoryWidget() {
|
||||||
deleteAndMark(_pinnedBar);
|
delete base::take(_pinnedBar);
|
||||||
deleteAndMark(_list);
|
delete base::take(_list);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,10 +21,12 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "localimageloader.h"
|
#include "localimageloader.h"
|
||||||
#include "ui/boxshadow.h"
|
#include "ui/effects/rect_shadow.h"
|
||||||
|
#include "ui/popupmenu.h"
|
||||||
#include "history/history_common.h"
|
#include "history/history_common.h"
|
||||||
#include "history/field_autocomplete.h"
|
#include "history/field_autocomplete.h"
|
||||||
#include "window/section_widget.h"
|
#include "window/section_widget.h"
|
||||||
|
#include "core/single_timer.h"
|
||||||
|
|
||||||
namespace InlineBots {
|
namespace InlineBots {
|
||||||
namespace Layout {
|
namespace Layout {
|
||||||
|
@ -479,30 +481,31 @@ private:
|
||||||
void init();
|
void init();
|
||||||
MainWidget *parent();
|
MainWidget *parent();
|
||||||
|
|
||||||
UserData *_sharedContact;
|
UserData *_sharedContact = nullptr;
|
||||||
bool _forwardSelected, _sendPath;
|
bool _forwardSelected = false;
|
||||||
|
bool _sendPath = false;
|
||||||
|
|
||||||
QString _shareUrl, _shareText;
|
QString _shareUrl, _shareText;
|
||||||
QString _botAndQuery;
|
QString _botAndQuery;
|
||||||
|
|
||||||
BoxButton _send, _cancel;
|
BoxButton _send, _cancel;
|
||||||
PeerData *offered;
|
PeerData *_offered = nullptr;
|
||||||
|
|
||||||
anim::fvalue a_opacity;
|
anim::fvalue a_opacity;
|
||||||
Animation _a_appearance;
|
Animation _a_appearance;
|
||||||
|
|
||||||
QRect box;
|
QRect _box;
|
||||||
bool hiding;
|
bool _hiding = false;
|
||||||
|
|
||||||
mtpRequestId _forwardRequest;
|
mtpRequestId _forwardRequest = 0;
|
||||||
|
|
||||||
int32 _chooseWidth;
|
int _chooseWidth = 0;
|
||||||
|
|
||||||
Text toText;
|
Text _toText;
|
||||||
int32 toTextWidth;
|
int32 _toTextWidth = 0;
|
||||||
QPixmap cacheForAnim;
|
QPixmap _cacheForAnim;
|
||||||
|
|
||||||
BoxShadow shadow;
|
Ui::RectShadow _shadow;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ constexpr const str_const LanguageCodes[] = {
|
||||||
"pt_BR",
|
"pt_BR",
|
||||||
"ko",
|
"ko",
|
||||||
};
|
};
|
||||||
constexpr const int languageTest = -1, languageDefault = 0, languageCount = arraysize(LanguageCodes);
|
constexpr const int languageTest = -1, languageDefault = 0, languageCount = base::array_size(LanguageCodes);
|
||||||
|
|
||||||
class LangString : public QString {
|
class LangString : public QString {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -83,7 +83,7 @@ private:
|
||||||
QRect _box, _hiddenSpecialBox;
|
QRect _box, _hiddenSpecialBox;
|
||||||
float64 _opacity = 0.;
|
float64 _opacity = 0.;
|
||||||
|
|
||||||
BoxShadow _shadow;
|
Ui::RectShadow _shadow;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ui/boxshadow.h"
|
#include "ui/effects/rect_shadow.h"
|
||||||
|
|
||||||
class LayerWidget : public TWidget {
|
class LayerWidget : public TWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
|
@ -32,6 +32,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "lang.h"
|
#include "lang.h"
|
||||||
#include "media/media_audio.h"
|
#include "media/media_audio.h"
|
||||||
|
#include "application.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
|
|
||||||
namespace Local {
|
namespace Local {
|
||||||
|
@ -534,7 +535,7 @@ enum {
|
||||||
dbiDcOption = 0x27,
|
dbiDcOption = 0x27,
|
||||||
dbiTryIPv6 = 0x28,
|
dbiTryIPv6 = 0x28,
|
||||||
dbiSongVolume = 0x29,
|
dbiSongVolume = 0x29,
|
||||||
dbiWindowsNotifications = 0x30,
|
dbiWindowsNotificationsOld = 0x30,
|
||||||
dbiIncludeMuted = 0x31,
|
dbiIncludeMuted = 0x31,
|
||||||
dbiMegagroupSizeMax = 0x32,
|
dbiMegagroupSizeMax = 0x32,
|
||||||
dbiDownloadPath = 0x33,
|
dbiDownloadPath = 0x33,
|
||||||
|
@ -548,6 +549,9 @@ enum {
|
||||||
dbiModerateMode = 0x41,
|
dbiModerateMode = 0x41,
|
||||||
dbiVideoVolume = 0x42,
|
dbiVideoVolume = 0x42,
|
||||||
dbiStickersRecentLimit = 0x43,
|
dbiStickersRecentLimit = 0x43,
|
||||||
|
dbiNativeNotifications = 0x44,
|
||||||
|
dbiNotificationsCount = 0x45,
|
||||||
|
dbiNotificationsCorner = 0x46,
|
||||||
|
|
||||||
dbiEncryptedWithSalt = 333,
|
dbiEncryptedWithSalt = 333,
|
||||||
dbiEncrypted = 444,
|
dbiEncrypted = 444,
|
||||||
|
@ -989,15 +993,34 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version) {
|
||||||
if (App::wnd()) App::wnd()->updateTrayMenu();
|
if (App::wnd()) App::wnd()->updateTrayMenu();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case dbiWindowsNotifications: {
|
case dbiWindowsNotificationsOld: {
|
||||||
|
qint32 v;
|
||||||
|
stream >> v;
|
||||||
|
if (!_checkStreamStatus(stream)) return false;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case dbiNativeNotifications: {
|
||||||
qint32 v;
|
qint32 v;
|
||||||
stream >> v;
|
stream >> v;
|
||||||
if (!_checkStreamStatus(stream)) return false;
|
if (!_checkStreamStatus(stream)) return false;
|
||||||
|
|
||||||
Global::SetWindowsNotifications(v == 1);
|
Global::SetNativeNotifications(v == 1);
|
||||||
if (cPlatform() == dbipWindows) {
|
} break;
|
||||||
Global::SetCustomNotifies((App::wnd() ? !App::wnd()->psHasNativeNotifications() : true) || !Global::WindowsNotifications());
|
|
||||||
}
|
case dbiNotificationsCount: {
|
||||||
|
qint32 v;
|
||||||
|
stream >> v;
|
||||||
|
if (!_checkStreamStatus(stream)) return false;
|
||||||
|
|
||||||
|
Global::SetNotificationsCount((v > 0 ? v : 3));
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case dbiNotificationsCorner: {
|
||||||
|
qint32 v;
|
||||||
|
stream >> v;
|
||||||
|
if (!_checkStreamStatus(stream)) return false;
|
||||||
|
|
||||||
|
Global::SetNotificationsCorner(static_cast<Notify::ScreenCorner>((v >= 0 && v < 4) ? v : 2));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case dbiWorkMode: {
|
case dbiWorkMode: {
|
||||||
|
@ -1056,6 +1079,9 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version) {
|
||||||
if (!_checkStreamStatus(stream)) return false;
|
if (!_checkStreamStatus(stream)) return false;
|
||||||
|
|
||||||
cSetAutoUpdate(v == 1);
|
cSetAutoUpdate(v == 1);
|
||||||
|
if (!cAutoUpdate()) {
|
||||||
|
Sandbox::stopUpdate();
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case dbiLastUpdateCheck: {
|
case dbiLastUpdateCheck: {
|
||||||
|
@ -1568,7 +1594,7 @@ void _writeUserSettings() {
|
||||||
_writeMap(WriteMapFast);
|
_writeMap(WriteMapFast);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 size = 18 * (sizeof(quint32) + sizeof(qint32));
|
uint32 size = 20 * (sizeof(quint32) + sizeof(qint32));
|
||||||
size += sizeof(quint32) + Serialize::stringSize(Global::AskDownloadPath() ? QString() : Global::DownloadPath()) + Serialize::bytearraySize(Global::AskDownloadPath() ? QByteArray() : Global::DownloadPathBookmark());
|
size += sizeof(quint32) + Serialize::stringSize(Global::AskDownloadPath() ? QString() : Global::DownloadPath()) + Serialize::bytearraySize(Global::AskDownloadPath() ? QByteArray() : Global::DownloadPathBookmark());
|
||||||
size += sizeof(quint32) + sizeof(qint32) + (cRecentEmojisPreload().isEmpty() ? cGetRecentEmojis().size() : cRecentEmojisPreload().size()) * (sizeof(uint64) + sizeof(ushort));
|
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));
|
size += sizeof(quint32) + sizeof(qint32) + cEmojiVariants().size() * (sizeof(uint32) + sizeof(uint64));
|
||||||
|
@ -1592,7 +1618,9 @@ void _writeUserSettings() {
|
||||||
data.stream << quint32(dbiShowingSavedGifs) << qint32(cShowingSavedGifs());
|
data.stream << quint32(dbiShowingSavedGifs) << qint32(cShowingSavedGifs());
|
||||||
data.stream << quint32(dbiDesktopNotify) << qint32(Global::DesktopNotify());
|
data.stream << quint32(dbiDesktopNotify) << qint32(Global::DesktopNotify());
|
||||||
data.stream << quint32(dbiNotifyView) << qint32(Global::NotifyView());
|
data.stream << quint32(dbiNotifyView) << qint32(Global::NotifyView());
|
||||||
data.stream << quint32(dbiWindowsNotifications) << qint32(Global::WindowsNotifications());
|
data.stream << quint32(dbiNativeNotifications) << qint32(Global::NativeNotifications());
|
||||||
|
data.stream << quint32(dbiNotificationsCount) << qint32(Global::NotificationsCount());
|
||||||
|
data.stream << quint32(dbiNotificationsCorner) << qint32(Global::NotificationsCorner());
|
||||||
data.stream << quint32(dbiAskDownloadPath) << qint32(Global::AskDownloadPath());
|
data.stream << quint32(dbiAskDownloadPath) << qint32(Global::AskDownloadPath());
|
||||||
data.stream << quint32(dbiDownloadPath) << (Global::AskDownloadPath() ? QString() : Global::DownloadPath()) << (Global::AskDownloadPath() ? QByteArray() : Global::DownloadPathBookmark());
|
data.stream << quint32(dbiDownloadPath) << (Global::AskDownloadPath() ? QString() : Global::DownloadPath()) << (Global::AskDownloadPath() ? QByteArray() : Global::DownloadPathBookmark());
|
||||||
data.stream << quint32(dbiCompressPastedImage) << qint32(cCompressPastedImage());
|
data.stream << quint32(dbiCompressPastedImage) << qint32(cCompressPastedImage());
|
||||||
|
@ -2627,7 +2655,7 @@ public:
|
||||||
virtual void readFromStream(QDataStream &stream, quint64 &first, quint64 &second, quint32 &type, QByteArray &data) = 0;
|
virtual void readFromStream(QDataStream &stream, quint64 &first, quint64 &second, quint32 &type, QByteArray &data) = 0;
|
||||||
virtual void clearInMap() = 0;
|
virtual void clearInMap() = 0;
|
||||||
virtual ~AbstractCachedLoadTask() {
|
virtual ~AbstractCachedLoadTask() {
|
||||||
deleteAndMark(_result);
|
delete base::take(_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -2903,7 +2931,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual ~WebFileLoadTask() {
|
virtual ~WebFileLoadTask() {
|
||||||
deleteAndMark(_result);
|
delete base::take(_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -1015,8 +1015,7 @@ namespace internal {
|
||||||
|
|
||||||
#if !defined Q_OS_MAC || defined MAC_USE_BREAKPAD
|
#if !defined Q_OS_MAC || defined MAC_USE_BREAKPAD
|
||||||
if (internal::BreakpadExceptionHandler) {
|
if (internal::BreakpadExceptionHandler) {
|
||||||
google_breakpad::ExceptionHandler *h = getPointerAndReset(internal::BreakpadExceptionHandler);
|
delete base::take(internal::BreakpadExceptionHandler);
|
||||||
delete h;
|
|
||||||
}
|
}
|
||||||
#endif // !Q_OS_MAC || MAC_USE_BREAKPAD
|
#endif // !Q_OS_MAC || MAC_USE_BREAKPAD
|
||||||
|
|
||||||
|
|
|
@ -3324,10 +3324,7 @@ void MainWidget::start(const MTPUser &user) {
|
||||||
App::feedUsers(MTP_vector<MTPUser>(1, user));
|
App::feedUsers(MTP_vector<MTPUser>(1, user));
|
||||||
MTP::send(MTPupdates_GetState(), rpcDone(&MainWidget::gotState));
|
MTP::send(MTPupdates_GetState(), rpcDone(&MainWidget::gotState));
|
||||||
update();
|
update();
|
||||||
if (!cStartUrl().isEmpty()) {
|
|
||||||
openLocalUrl(cStartUrl());
|
|
||||||
cSetStartUrl(QString());
|
|
||||||
}
|
|
||||||
_started = true;
|
_started = true;
|
||||||
App::wnd()->sendServiceHistoryRequest();
|
App::wnd()->sendServiceHistoryRequest();
|
||||||
Local::readInstalledStickers();
|
Local::readInstalledStickers();
|
||||||
|
@ -3335,12 +3332,23 @@ void MainWidget::start(const MTPUser &user) {
|
||||||
Local::readRecentStickers();
|
Local::readRecentStickers();
|
||||||
Local::readSavedGifs();
|
Local::readSavedGifs();
|
||||||
_history->start();
|
_history->start();
|
||||||
|
|
||||||
|
checkStartUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainWidget::started() {
|
bool MainWidget::started() {
|
||||||
return _started;
|
return _started;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWidget::checkStartUrl() {
|
||||||
|
if (!cStartUrl().isEmpty() && App::self() && !App::passcoded()) {
|
||||||
|
auto url = cStartUrl();
|
||||||
|
cSetStartUrl(QString());
|
||||||
|
|
||||||
|
openLocalUrl(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MainWidget::openLocalUrl(const QString &url) {
|
void MainWidget::openLocalUrl(const QString &url) {
|
||||||
auto urlTrimmed = url.trimmed();
|
auto urlTrimmed = url.trimmed();
|
||||||
if (urlTrimmed.size() > 8192) urlTrimmed = urlTrimmed.mid(0, 8192);
|
if (urlTrimmed.size() > 8192) urlTrimmed = urlTrimmed.mid(0, 8192);
|
||||||
|
|
|
@ -22,6 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
#include "localimageloader.h"
|
#include "localimageloader.h"
|
||||||
#include "history/history_common.h"
|
#include "history/history_common.h"
|
||||||
|
#include "core/single_timer.h"
|
||||||
|
|
||||||
namespace Dialogs {
|
namespace Dialogs {
|
||||||
class Row;
|
class Row;
|
||||||
|
@ -156,6 +157,7 @@ public:
|
||||||
|
|
||||||
void start(const MTPUser &user);
|
void start(const MTPUser &user);
|
||||||
|
|
||||||
|
void checkStartUrl();
|
||||||
void openLocalUrl(const QString &str);
|
void openLocalUrl(const QString &str);
|
||||||
void openPeerByName(const QString &name, MsgId msgId = ShowAtUnreadMsgId, const QString &startToken = QString());
|
void openPeerByName(const QString &name, MsgId msgId = ShowAtUnreadMsgId, const QString &startToken = QString());
|
||||||
void joinGroupByHash(const QString &hash);
|
void joinGroupByHash(const QString &hash);
|
||||||
|
|
|
@ -23,6 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
#include "dialogs/dialogs_layout.h"
|
#include "dialogs/dialogs_layout.h"
|
||||||
#include "styles/style_dialogs.h"
|
#include "styles/style_dialogs.h"
|
||||||
|
#include "ui/popupmenu.h"
|
||||||
#include "zip.h"
|
#include "zip.h"
|
||||||
#include "lang.h"
|
#include "lang.h"
|
||||||
#include "shortcuts.h"
|
#include "shortcuts.h"
|
||||||
|
@ -42,8 +43,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#include "localstorage.h"
|
#include "localstorage.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
#include "settings/settings_widget.h"
|
#include "settings/settings_widget.h"
|
||||||
|
#include "window/notifications_manager.h"
|
||||||
|
|
||||||
ConnectingWidget::ConnectingWidget(QWidget *parent, const QString &text, const QString &reconnect) : QWidget(parent), _shadow(st::boxShadow), _reconnect(this, QString()) {
|
ConnectingWidget::ConnectingWidget(QWidget *parent, const QString &text, const QString &reconnect) : QWidget(parent)
|
||||||
|
, _shadow(st::boxShadow)
|
||||||
|
, _reconnect(this, QString()) {
|
||||||
set(text, reconnect);
|
set(text, reconnect);
|
||||||
connect(&_reconnect, SIGNAL(clicked()), this, SLOT(onReconnect()));
|
connect(&_reconnect, SIGNAL(clicked()), this, SLOT(onReconnect()));
|
||||||
}
|
}
|
||||||
|
@ -57,310 +61,27 @@ void ConnectingWidget::set(const QString &text, const QString &reconnect) {
|
||||||
} else {
|
} else {
|
||||||
_reconnect.setText(reconnect);
|
_reconnect.setText(reconnect);
|
||||||
_reconnect.show();
|
_reconnect.show();
|
||||||
_reconnect.move(st::connectingPadding.left() + _textWidth, st::boxShadow.pxHeight() + st::connectingPadding.top());
|
_reconnect.move(st::connectingPadding.left() + _textWidth, st::boxShadow.height() + st::connectingPadding.top());
|
||||||
_reconnectWidth = _reconnect.width();
|
_reconnectWidth = _reconnect.width();
|
||||||
}
|
}
|
||||||
resize(st::connectingPadding.left() + _textWidth + _reconnectWidth + st::connectingPadding.right() + st::boxShadow.pxWidth(), st::boxShadow.pxHeight() + st::connectingPadding.top() + st::linkFont->height + st::connectingPadding.bottom());
|
resize(st::connectingPadding.left() + _textWidth + _reconnectWidth + st::connectingPadding.right() + st::boxShadow.width(), st::boxShadow.height() + st::connectingPadding.top() + st::linkFont->height + st::connectingPadding.bottom());
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectingWidget::paintEvent(QPaintEvent *e) {
|
void ConnectingWidget::paintEvent(QPaintEvent *e) {
|
||||||
QPainter p(this);
|
Painter p(this);
|
||||||
|
|
||||||
_shadow.paint(p, QRect(0, st::boxShadow.pxHeight(), width() - st::boxShadow.pxWidth(), height() - st::boxShadow.pxHeight()), 0, BoxShadow::Top | BoxShadow::Right);
|
_shadow.paint(p, QRect(0, st::boxShadow.height(), width() - st::boxShadow.width(), height() - st::boxShadow.height()), 0, Ui::RectShadow::Side::Top | Ui::RectShadow::Side::Right);
|
||||||
p.fillRect(0, st::boxShadow.pxHeight(), width() - st::boxShadow.pxWidth(), height() - st::boxShadow.pxHeight(), st::connectingBG->b);
|
p.fillRect(0, st::boxShadow.height(), width() - st::boxShadow.width(), height() - st::boxShadow.height(), st::connectingBG->b);
|
||||||
p.setFont(st::linkFont->f);
|
p.setFont(st::linkFont->f);
|
||||||
p.setPen(st::connectingColor->p);
|
p.setPen(st::connectingColor->p);
|
||||||
p.drawText(st::connectingPadding.left(), st::boxShadow.pxHeight() + st::connectingPadding.top() + st::linkFont->ascent, _text);
|
p.drawText(st::connectingPadding.left(), st::boxShadow.height() + st::connectingPadding.top() + st::linkFont->ascent, _text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectingWidget::onReconnect() {
|
void ConnectingWidget::onReconnect() {
|
||||||
MTP::restart();
|
MTP::restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
NotifyWindow::NotifyWindow(HistoryItem *msg, int32 x, int32 y, int32 fwdCount) : TWidget(0)
|
|
||||||
, history(msg->history())
|
|
||||||
, item(msg)
|
|
||||||
, fwdCount(fwdCount)
|
|
||||||
#if defined Q_OS_WIN && !defined Q_OS_WINRT
|
|
||||||
, started(GetTickCount())
|
|
||||||
#endif // Q_OS_WIN && !Q_OS_WINRT
|
|
||||||
, close(this, st::notifyClose)
|
|
||||||
, alphaDuration(st::notifyFastAnim)
|
|
||||||
, posDuration(st::notifyFastAnim)
|
|
||||||
, hiding(false)
|
|
||||||
, _index(0)
|
|
||||||
, a_opacity(0)
|
|
||||||
, a_func(anim::linear)
|
|
||||||
, a_y(y + st::notifyHeight + st::notifyDeltaY)
|
|
||||||
, _a_appearance(animation(this, &NotifyWindow::step_appearance)) {
|
|
||||||
|
|
||||||
updateNotifyDisplay();
|
|
||||||
|
|
||||||
hideTimer.setSingleShot(true);
|
|
||||||
connect(&hideTimer, SIGNAL(timeout()), this, SLOT(hideByTimer()));
|
|
||||||
|
|
||||||
inputTimer.setSingleShot(true);
|
|
||||||
connect(&inputTimer, SIGNAL(timeout()), this, SLOT(checkLastInput()));
|
|
||||||
|
|
||||||
connect(&close, SIGNAL(clicked()), this, SLOT(unlinkHistoryAndNotify()));
|
|
||||||
close.setAcceptBoth(true);
|
|
||||||
close.move(st::notifyWidth - st::notifyClose.width - st::notifyClosePos.x(), st::notifyClosePos.y());
|
|
||||||
close.show();
|
|
||||||
|
|
||||||
a_y.start(y);
|
|
||||||
setGeometry(x, a_y.current(), st::notifyWidth, st::notifyHeight);
|
|
||||||
|
|
||||||
a_opacity.start(1);
|
|
||||||
setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint);
|
|
||||||
setAttribute(Qt::WA_MacAlwaysShowToolWindow);
|
|
||||||
|
|
||||||
show();
|
|
||||||
|
|
||||||
setWindowOpacity(a_opacity.current());
|
|
||||||
|
|
||||||
alphaDuration = posDuration = st::notifyFastAnim;
|
|
||||||
_a_appearance.start();
|
|
||||||
|
|
||||||
checkLastInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifyWindow::checkLastInput() {
|
|
||||||
#if defined Q_OS_WIN && !defined Q_OS_WINRT
|
|
||||||
LASTINPUTINFO lii;
|
|
||||||
lii.cbSize = sizeof(LASTINPUTINFO);
|
|
||||||
BOOL res = GetLastInputInfo(&lii);
|
|
||||||
if (!res || lii.dwTime >= started) {
|
|
||||||
hideTimer.start(st::notifyWaitLongHide);
|
|
||||||
} else {
|
|
||||||
inputTimer.start(300);
|
|
||||||
}
|
|
||||||
#else // Q_OS_WIN && !Q_OS_WINRT
|
|
||||||
// TODO
|
|
||||||
if (true) {
|
|
||||||
hideTimer.start(st::notifyWaitLongHide);
|
|
||||||
} else {
|
|
||||||
inputTimer.start(300);
|
|
||||||
}
|
|
||||||
#endif // else for Q_OS_WIN && !Q_OS_WINRT
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifyWindow::moveTo(int32 x, int32 y, int32 index) {
|
|
||||||
if (index >= 0) {
|
|
||||||
_index = index;
|
|
||||||
}
|
|
||||||
move(x, a_y.current());
|
|
||||||
a_y.start(y);
|
|
||||||
a_opacity.restart();
|
|
||||||
posDuration = st::notifyFastAnim;
|
|
||||||
_a_appearance.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifyWindow::updateNotifyDisplay() {
|
|
||||||
if (!item) return;
|
|
||||||
|
|
||||||
int32 w = st::notifyWidth, h = st::notifyHeight;
|
|
||||||
QImage img(w * cIntRetinaFactor(), h * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
|
||||||
if (cRetina()) img.setDevicePixelRatio(cRetinaFactor());
|
|
||||||
img.fill(st::notifyBG->c);
|
|
||||||
|
|
||||||
{
|
|
||||||
Painter p(&img);
|
|
||||||
p.fillRect(0, 0, w - st::notifyBorderWidth, st::notifyBorderWidth, st::notifyBorder->b);
|
|
||||||
p.fillRect(w - st::notifyBorderWidth, 0, st::notifyBorderWidth, h - st::notifyBorderWidth, st::notifyBorder->b);
|
|
||||||
p.fillRect(st::notifyBorderWidth, h - st::notifyBorderWidth, w - st::notifyBorderWidth, st::notifyBorderWidth, st::notifyBorder->b);
|
|
||||||
p.fillRect(0, st::notifyBorderWidth, st::notifyBorderWidth, h - st::notifyBorderWidth, st::notifyBorder->b);
|
|
||||||
|
|
||||||
if (!App::passcoded() && Global::NotifyView() <= dbinvShowName) {
|
|
||||||
history->peer->loadUserpic(true, true);
|
|
||||||
history->peer->paintUserpicLeft(p, st::notifyPhotoSize, st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), width());
|
|
||||||
} else {
|
|
||||||
static QPixmap icon = App::pixmapFromImageInPlace(App::wnd()->iconLarge().scaled(st::notifyPhotoSize, st::notifyPhotoSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
|
||||||
p.drawPixmap(st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), icon);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 itemWidth = w - st::notifyPhotoPos.x() - st::notifyPhotoSize - st::notifyTextLeft - st::notifyClosePos.x() - st::notifyClose.width;
|
|
||||||
|
|
||||||
QRect rectForName(st::notifyPhotoPos.x() + st::notifyPhotoSize + st::notifyTextLeft, st::notifyTextTop, itemWidth, st::msgNameFont->height);
|
|
||||||
if (!App::passcoded() && Global::NotifyView() <= dbinvShowName) {
|
|
||||||
if (auto chatTypeIcon = Dialogs::Layout::ChatTypeIcon(history->peer, false)) {
|
|
||||||
chatTypeIcon->paint(p, rectForName.topLeft(), w);
|
|
||||||
rectForName.setLeft(rectForName.left() + st::dialogsChatTypeSkip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QDateTime now(QDateTime::currentDateTime()), lastTime(item->date);
|
|
||||||
QDate nowDate(now.date()), lastDate(lastTime.date());
|
|
||||||
QString dt = lastTime.toString(cTimeFormat());
|
|
||||||
int32 dtWidth = st::dialogsTextFont->width(dt);
|
|
||||||
rectForName.setWidth(rectForName.width() - dtWidth - st::dialogsDateSkip);
|
|
||||||
p.setFont(st::dialogsDateFont);
|
|
||||||
p.setPen(st::dialogsDateFg);
|
|
||||||
p.drawText(rectForName.left() + rectForName.width() + st::dialogsDateSkip, rectForName.top() + st::dialogsTextFont->ascent, dt);
|
|
||||||
|
|
||||||
if (!App::passcoded() && Global::NotifyView() <= dbinvShowPreview) {
|
|
||||||
const HistoryItem *textCachedFor = 0;
|
|
||||||
Text itemTextCache(itemWidth);
|
|
||||||
QRect r(st::notifyPhotoPos.x() + st::notifyPhotoSize + st::notifyTextLeft, st::notifyItemTop + st::msgNameFont->height, itemWidth, 2 * st::dialogsTextFont->height);
|
|
||||||
if (fwdCount < 2) {
|
|
||||||
bool active = false;
|
|
||||||
item->drawInDialog(p, r, active, textCachedFor, itemTextCache);
|
|
||||||
} else {
|
|
||||||
p.setFont(st::dialogsTextFont);
|
|
||||||
if (item->hasFromName() && !item->isPost()) {
|
|
||||||
itemTextCache.setText(st::dialogsTextFont, item->author()->name);
|
|
||||||
p.setPen(st::dialogsTextFgService);
|
|
||||||
itemTextCache.drawElided(p, r.left(), r.top(), r.width(), st::dialogsTextFont->height);
|
|
||||||
r.setTop(r.top() + st::dialogsTextFont->height);
|
|
||||||
}
|
|
||||||
p.setPen(st::dialogsTextFg);
|
|
||||||
p.drawText(r.left(), r.top() + st::dialogsTextFont->ascent, lng_forward_messages(lt_count, fwdCount));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
static QString notifyText = st::dialogsTextFont->elided(lang(lng_notification_preview), itemWidth);
|
|
||||||
p.setPen(st::dialogsTextFgService);
|
|
||||||
p.drawText(st::notifyPhotoPos.x() + st::notifyPhotoSize + st::notifyTextLeft, st::notifyItemTop + st::msgNameFont->height + st::dialogsTextFont->ascent, notifyText);
|
|
||||||
}
|
|
||||||
|
|
||||||
p.setPen(st::dialogsNameFg);
|
|
||||||
if (!App::passcoded() && Global::NotifyView() <= dbinvShowName) {
|
|
||||||
history->peer->dialogName().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
|
|
||||||
} else {
|
|
||||||
p.setFont(st::msgNameFont->f);
|
|
||||||
static QString notifyTitle = st::msgNameFont->elided(qsl("Telegram Desktop"), rectForName.width());
|
|
||||||
p.drawText(rectForName.left(), rectForName.top() + st::msgNameFont->ascent, notifyTitle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pm = App::pixmapFromImageInPlace(std_::move(img));
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifyWindow::updatePeerPhoto() {
|
|
||||||
if (!peerPhoto->isNull() && peerPhoto->loaded()) {
|
|
||||||
QImage img(pm.toImage());
|
|
||||||
{
|
|
||||||
QPainter p(&img);
|
|
||||||
p.drawPixmap(st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), peerPhoto->pix(st::notifyPhotoSize));
|
|
||||||
}
|
|
||||||
peerPhoto = ImagePtr();
|
|
||||||
pm = App::pixmapFromImageInPlace(std_::move(img));
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifyWindow::itemRemoved(HistoryItem *del) {
|
|
||||||
if (item == del) {
|
|
||||||
item = 0;
|
|
||||||
unlinkHistoryAndNotify();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifyWindow::unlinkHistoryAndNotify() {
|
|
||||||
unlinkHistory();
|
|
||||||
App::wnd()->notifyShowNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifyWindow::unlinkHistory(History *hist) {
|
|
||||||
if (!hist || hist == history) {
|
|
||||||
animHide(st::notifyFastAnim, anim::linear);
|
|
||||||
history = 0;
|
|
||||||
item = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifyWindow::enterEvent(QEvent *e) {
|
|
||||||
if (!history) return;
|
|
||||||
if (App::wnd()) App::wnd()->notifyStopHiding();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifyWindow::leaveEvent(QEvent *e) {
|
|
||||||
if (!history) return;
|
|
||||||
App::wnd()->notifyStartHiding();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifyWindow::startHiding() {
|
|
||||||
hideTimer.start(st::notifyWaitShortHide);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifyWindow::mousePressEvent(QMouseEvent *e) {
|
|
||||||
if (!history) return;
|
|
||||||
|
|
||||||
PeerId peer = history->peer->id;
|
|
||||||
MsgId msgId = (!history->peer->isUser() && item && item->mentionsMe() && item->id > 0) ? item->id : ShowAtUnreadMsgId;
|
|
||||||
|
|
||||||
if (e->button() == Qt::RightButton) {
|
|
||||||
unlinkHistoryAndNotify();
|
|
||||||
} else {
|
|
||||||
App::wnd()->showFromTray();
|
|
||||||
if (App::passcoded()) {
|
|
||||||
App::wnd()->setInnerFocus();
|
|
||||||
App::wnd()->notifyClear();
|
|
||||||
} else {
|
|
||||||
Ui::showPeerHistory(peer, msgId);
|
|
||||||
}
|
|
||||||
e->ignore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifyWindow::paintEvent(QPaintEvent *e) {
|
|
||||||
QPainter p(this);
|
|
||||||
p.drawPixmap(0, 0, pm);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifyWindow::animHide(float64 duration, anim::transition func) {
|
|
||||||
if (!history) return;
|
|
||||||
alphaDuration = duration;
|
|
||||||
a_func = func;
|
|
||||||
a_opacity.start(0);
|
|
||||||
a_y.restart();
|
|
||||||
hiding = true;
|
|
||||||
_a_appearance.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifyWindow::stopHiding() {
|
|
||||||
if (!history) return;
|
|
||||||
alphaDuration = st::notifyFastAnim;
|
|
||||||
a_func = anim::linear;
|
|
||||||
a_opacity.start(1);
|
|
||||||
a_y.restart();
|
|
||||||
hiding = false;
|
|
||||||
hideTimer.stop();
|
|
||||||
_a_appearance.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifyWindow::hideByTimer() {
|
|
||||||
if (!history) return;
|
|
||||||
animHide(st::notifySlowHide, st::notifySlowHideFunc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifyWindow::step_appearance(float64 ms, bool timer) {
|
|
||||||
float64 dtAlpha = ms / alphaDuration, dtPos = ms / posDuration;
|
|
||||||
if (dtAlpha >= 1) {
|
|
||||||
a_opacity.finish();
|
|
||||||
if (hiding) {
|
|
||||||
_a_appearance.stop();
|
|
||||||
deleteLater();
|
|
||||||
} else if (dtPos >= 1) {
|
|
||||||
_a_appearance.stop();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
a_opacity.update(dtAlpha, a_func);
|
|
||||||
}
|
|
||||||
setWindowOpacity(a_opacity.current());
|
|
||||||
if (dtPos >= 1) {
|
|
||||||
a_y.finish();
|
|
||||||
} else {
|
|
||||||
a_y.update(dtPos, anim::linear);
|
|
||||||
}
|
|
||||||
move(x(), a_y.current());
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
NotifyWindow::~NotifyWindow() {
|
|
||||||
if (App::wnd()) App::wnd()->notifyShowNext(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
MainWindow::MainWindow() {
|
MainWindow::MainWindow() {
|
||||||
icon16 = icon256.scaledToWidth(16, Qt::SmoothTransformation);
|
icon16 = icon256.scaledToWidth(16, Qt::SmoothTransformation);
|
||||||
icon32 = icon256.scaledToWidth(32, Qt::SmoothTransformation);
|
icon32 = icon256.scaledToWidth(32, Qt::SmoothTransformation);
|
||||||
|
@ -375,8 +96,6 @@ MainWindow::MainWindow() {
|
||||||
notifyClear();
|
notifyClear();
|
||||||
} else if (type == Notify::ChangeType::ViewParams) {
|
} else if (type == Notify::ChangeType::ViewParams) {
|
||||||
notifyUpdateAll();
|
notifyUpdateAll();
|
||||||
} else if (type == Notify::ChangeType::UseNative) {
|
|
||||||
notifyClearFast();
|
|
||||||
} else if (type == Notify::ChangeType::IncludeMuted) {
|
} else if (type == Notify::ChangeType::IncludeMuted) {
|
||||||
Notify::unreadCounterUpdated();
|
Notify::unreadCounterUpdated();
|
||||||
}
|
}
|
||||||
|
@ -397,14 +116,13 @@ MainWindow::MainWindow() {
|
||||||
_inactiveTimer.setSingleShot(true);
|
_inactiveTimer.setSingleShot(true);
|
||||||
connect(&_inactiveTimer, SIGNAL(timeout()), this, SLOT(onInactiveTimer()));
|
connect(&_inactiveTimer, SIGNAL(timeout()), this, SLOT(onInactiveTimer()));
|
||||||
|
|
||||||
connect(¬ifyWaitTimer, SIGNAL(timeout()), this, SLOT(notifyFire()));
|
connect(&_notifyWaitTimer, SIGNAL(timeout()), this, SLOT(notifyShowNext()));
|
||||||
|
|
||||||
_isActiveTimer.setSingleShot(true);
|
_isActiveTimer.setSingleShot(true);
|
||||||
connect(&_isActiveTimer, SIGNAL(timeout()), this, SLOT(updateIsActive()));
|
connect(&_isActiveTimer, SIGNAL(timeout()), this, SLOT(updateIsActive()));
|
||||||
|
|
||||||
connect(&_autoLockTimer, SIGNAL(timeout()), this, SLOT(checkAutoLock()));
|
connect(&_autoLockTimer, SIGNAL(timeout()), this, SLOT(checkAutoLock()));
|
||||||
|
|
||||||
subscribe(FileDownload::ImageLoaded(), [this] { notifyUpdateAllPhotos(); });
|
|
||||||
subscribe(Global::RefSelfChanged(), [this]() { updateGlobalMenu(); });
|
subscribe(Global::RefSelfChanged(), [this]() { updateGlobalMenu(); });
|
||||||
|
|
||||||
setAttribute(Qt::WA_NoSystemBackground);
|
setAttribute(Qt::WA_NoSystemBackground);
|
||||||
|
@ -547,6 +265,10 @@ void MainWindow::clearPasscode() {
|
||||||
notifyUpdateAll();
|
notifyUpdateAll();
|
||||||
title->updateControlsVisibility();
|
title->updateControlsVisibility();
|
||||||
updateGlobalMenu();
|
updateGlobalMenu();
|
||||||
|
|
||||||
|
if (auto main = App::main()) {
|
||||||
|
main->checkStartUrl();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::setupPasscode(bool anim) {
|
void MainWindow::setupPasscode(bool anim) {
|
||||||
|
@ -1030,9 +752,8 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *e) {
|
||||||
QString url = static_cast<QFileOpenEvent*>(e)->url().toEncoded().trimmed();
|
QString url = static_cast<QFileOpenEvent*>(e)->url().toEncoded().trimmed();
|
||||||
if (url.startsWith(qstr("tg://"), Qt::CaseInsensitive)) {
|
if (url.startsWith(qstr("tg://"), Qt::CaseInsensitive)) {
|
||||||
cSetStartUrl(url.mid(0, 8192));
|
cSetStartUrl(url.mid(0, 8192));
|
||||||
if (!cStartUrl().isEmpty() && App::main() && App::self()) {
|
if (auto main = App::main()) {
|
||||||
App::main()->openLocalUrl(cStartUrl());
|
main->checkStartUrl();
|
||||||
cSetStartUrl(QString());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
activate();
|
activate();
|
||||||
|
@ -1402,72 +1123,66 @@ void MainWindow::notifySchedule(History *history, HistoryItem *item) {
|
||||||
// LOG(("Is online: %1, otherOnline: %2, currentTime: %3, otherNotOld: %4, otherLaterThanMe: %5").arg(Logs::b(isOnline)).arg(cOtherOnline()).arg(t).arg(Logs::b(otherNotOld)).arg(Logs::b(otherLaterThanMe)));
|
// LOG(("Is online: %1, otherOnline: %2, currentTime: %3, otherNotOld: %4, otherLaterThanMe: %5").arg(Logs::b(isOnline)).arg(cOtherOnline()).arg(t).arg(Logs::b(otherNotOld)).arg(Logs::b(otherLaterThanMe)));
|
||||||
|
|
||||||
uint64 when = ms + delay;
|
uint64 when = ms + delay;
|
||||||
notifyWhenAlerts[history].insert(when, notifyByFrom);
|
_notifyWhenAlerts[history].insert(when, notifyByFrom);
|
||||||
if (Global::DesktopNotify() && !psSkipDesktopNotify()) {
|
if (Global::DesktopNotify() && !psSkipDesktopNotify()) {
|
||||||
NotifyWhenMaps::iterator i = notifyWhenMaps.find(history);
|
NotifyWhenMaps::iterator i = _notifyWhenMaps.find(history);
|
||||||
if (i == notifyWhenMaps.end()) {
|
if (i == _notifyWhenMaps.end()) {
|
||||||
i = notifyWhenMaps.insert(history, NotifyWhenMap());
|
i = _notifyWhenMaps.insert(history, NotifyWhenMap());
|
||||||
}
|
}
|
||||||
if (i.value().constFind(item->id) == i.value().cend()) {
|
if (i.value().constFind(item->id) == i.value().cend()) {
|
||||||
i.value().insert(item->id, when);
|
i.value().insert(item->id, when);
|
||||||
}
|
}
|
||||||
NotifyWaiters *addTo = haveSetting ? ¬ifyWaiters : ¬ifySettingWaiters;
|
NotifyWaiters *addTo = haveSetting ? &_notifyWaiters : &_notifySettingWaiters;
|
||||||
NotifyWaiters::const_iterator it = addTo->constFind(history);
|
NotifyWaiters::const_iterator it = addTo->constFind(history);
|
||||||
if (it == addTo->cend() || it->when > when) {
|
if (it == addTo->cend() || it->when > when) {
|
||||||
addTo->insert(history, NotifyWaiter(item->id, when, notifyByFrom));
|
addTo->insert(history, NotifyWaiter(item->id, when, notifyByFrom));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (haveSetting) {
|
if (haveSetting) {
|
||||||
if (!notifyWaitTimer.isActive() || notifyWaitTimer.remainingTime() > delay) {
|
if (!_notifyWaitTimer.isActive() || _notifyWaitTimer.remainingTime() > delay) {
|
||||||
notifyWaitTimer.start(delay);
|
_notifyWaitTimer.start(delay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::notifyFire() {
|
|
||||||
notifyShowNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::notifyClear(History *history) {
|
void MainWindow::notifyClear(History *history) {
|
||||||
if (!history) {
|
if (!history) {
|
||||||
for (NotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
|
Window::Notifications::manager()->clearAll();
|
||||||
(*i)->unlinkHistory();
|
|
||||||
}
|
for (auto i = _notifyWhenMaps.cbegin(), e = _notifyWhenMaps.cend(); i != e; ++i) {
|
||||||
psClearNotifies();
|
|
||||||
for (NotifyWhenMaps::const_iterator i = notifyWhenMaps.cbegin(), e = notifyWhenMaps.cend(); i != e; ++i) {
|
|
||||||
i.key()->clearNotifications();
|
i.key()->clearNotifications();
|
||||||
}
|
}
|
||||||
notifyWaiters.clear();
|
_notifyWhenMaps.clear();
|
||||||
notifySettingWaiters.clear();
|
_notifyWhenAlerts.clear();
|
||||||
notifyWhenMaps.clear();
|
_notifyWaiters.clear();
|
||||||
|
_notifySettingWaiters.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
notifyWaiters.remove(history);
|
|
||||||
notifySettingWaiters.remove(history);
|
Window::Notifications::manager()->clearFromHistory(history);
|
||||||
for (NotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
|
|
||||||
(*i)->unlinkHistory(history);
|
history->clearNotifications();
|
||||||
}
|
_notifyWhenMaps.remove(history);
|
||||||
psClearNotifies(history->peer->id);
|
_notifyWhenAlerts.remove(history);
|
||||||
notifyWhenMaps.remove(history);
|
_notifyWaiters.remove(history);
|
||||||
notifyWhenAlerts.remove(history);
|
_notifySettingWaiters.remove(history);
|
||||||
|
|
||||||
|
_notifyWaitTimer.stop();
|
||||||
notifyShowNext();
|
notifyShowNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::notifyClearFast() {
|
void MainWindow::notifyClearFast() {
|
||||||
notifyWaiters.clear();
|
Window::Notifications::manager()->clearAllFast();
|
||||||
notifySettingWaiters.clear();
|
|
||||||
for (NotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
|
_notifyWhenMaps.clear();
|
||||||
(*i)->deleteLater();
|
_notifyWhenAlerts.clear();
|
||||||
}
|
_notifyWaiters.clear();
|
||||||
psClearNotifies();
|
_notifySettingWaiters.clear();
|
||||||
notifyWindows.clear();
|
|
||||||
notifyWhenMaps.clear();
|
|
||||||
notifyWhenAlerts.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::notifySettingGot() {
|
void MainWindow::notifySettingGot() {
|
||||||
int32 t = unixtime();
|
int32 t = unixtime();
|
||||||
for (NotifyWaiters::iterator i = notifySettingWaiters.begin(); i != notifySettingWaiters.end();) {
|
for (NotifyWaiters::iterator i = _notifySettingWaiters.begin(); i != _notifySettingWaiters.end();) {
|
||||||
History *history = i.key();
|
History *history = i.key();
|
||||||
bool loaded = false, muted = false;
|
bool loaded = false, muted = false;
|
||||||
if (history->peer->notify != UnknownNotifySettings) {
|
if (history->peer->notify != UnknownNotifySettings) {
|
||||||
|
@ -1496,34 +1211,24 @@ void MainWindow::notifySettingGot() {
|
||||||
}
|
}
|
||||||
if (loaded) {
|
if (loaded) {
|
||||||
if (!muted) {
|
if (!muted) {
|
||||||
notifyWaiters.insert(i.key(), i.value());
|
_notifyWaiters.insert(i.key(), i.value());
|
||||||
}
|
}
|
||||||
i = notifySettingWaiters.erase(i);
|
i = _notifySettingWaiters.erase(i);
|
||||||
} else {
|
} else {
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
notifyWaitTimer.stop();
|
_notifyWaitTimer.stop();
|
||||||
notifyShowNext();
|
notifyShowNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::notifyShowNext(NotifyWindow *remove) {
|
void MainWindow::notifyShowNext() {
|
||||||
if (App::quitting()) return;
|
if (App::quitting()) return;
|
||||||
|
|
||||||
int32 count = NotifyWindowsCount;
|
|
||||||
if (remove) {
|
|
||||||
for (NotifyWindows::iterator i = notifyWindows.begin(), e = notifyWindows.end(); i != e; ++i) {
|
|
||||||
if ((*i) == remove) {
|
|
||||||
notifyWindows.erase(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64 ms = getms(true), nextAlert = 0;
|
uint64 ms = getms(true), nextAlert = 0;
|
||||||
bool alert = false;
|
bool alert = false;
|
||||||
int32 now = unixtime();
|
int32 now = unixtime();
|
||||||
for (NotifyWhenAlerts::iterator i = notifyWhenAlerts.begin(); i != notifyWhenAlerts.end();) {
|
for (NotifyWhenAlerts::iterator i = _notifyWhenAlerts.begin(); i != _notifyWhenAlerts.end();) {
|
||||||
while (!i.value().isEmpty() && i.value().begin().key() <= ms) {
|
while (!i.value().isEmpty() && i.value().begin().key() <= ms) {
|
||||||
NotifySettingsPtr n = i.key()->peer->notify, f = i.value().begin().value() ? i.value().begin().value()->notify : UnknownNotifySettings;
|
NotifySettingsPtr n = i.key()->peer->notify, f = i.value().begin().value() ? i.value().begin().value()->notify : UnknownNotifySettings;
|
||||||
while (!i.value().isEmpty() && i.value().begin().key() <= ms + 500) { // not more than one sound in 500ms from one peer - grouping
|
while (!i.value().isEmpty() && i.value().begin().key() <= ms + 500) { // not more than one sound in 500ms from one peer - grouping
|
||||||
|
@ -1536,7 +1241,7 @@ void MainWindow::notifyShowNext(NotifyWindow *remove) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i.value().isEmpty()) {
|
if (i.value().isEmpty()) {
|
||||||
i = notifyWhenAlerts.erase(i);
|
i = _notifyWhenAlerts.erase(i);
|
||||||
} else {
|
} else {
|
||||||
if (!nextAlert || nextAlert > i.value().begin().key()) {
|
if (!nextAlert || nextAlert > i.value().begin().key()) {
|
||||||
nextAlert = i.value().begin().key();
|
nextAlert = i.value().begin().key();
|
||||||
|
@ -1549,33 +1254,24 @@ void MainWindow::notifyShowNext(NotifyWindow *remove) {
|
||||||
App::playSound();
|
App::playSound();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Global::CustomNotifies()) {
|
if (_notifyWaiters.isEmpty() || !Global::DesktopNotify() || psSkipDesktopNotify()) {
|
||||||
for (NotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
|
|
||||||
int32 ind = (*i)->index();
|
|
||||||
if (ind < 0) continue;
|
|
||||||
--count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (count <= 0 || notifyWaiters.isEmpty() || !Global::DesktopNotify() || psSkipDesktopNotify()) {
|
|
||||||
if (nextAlert) {
|
if (nextAlert) {
|
||||||
notifyWaitTimer.start(nextAlert - ms);
|
_notifyWaitTimer.start(nextAlert - ms);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRect r = psDesktopRect();
|
while (true) {
|
||||||
int32 x = r.x() + r.width() - st::notifyWidth - st::notifyDeltaX, y = r.y() + r.height() - st::notifyHeight - st::notifyDeltaY;
|
|
||||||
while (count > 0) {
|
|
||||||
uint64 next = 0;
|
uint64 next = 0;
|
||||||
HistoryItem *notifyItem = 0;
|
HistoryItem *notifyItem = 0;
|
||||||
History *notifyHistory = 0;
|
History *notifyHistory = 0;
|
||||||
for (NotifyWaiters::iterator i = notifyWaiters.begin(); i != notifyWaiters.end();) {
|
for (NotifyWaiters::iterator i = _notifyWaiters.begin(); i != _notifyWaiters.end();) {
|
||||||
History *history = i.key();
|
History *history = i.key();
|
||||||
if (history->currentNotification() && history->currentNotification()->id != i.value().msg) {
|
if (history->currentNotification() && history->currentNotification()->id != i.value().msg) {
|
||||||
NotifyWhenMaps::iterator j = notifyWhenMaps.find(history);
|
NotifyWhenMaps::iterator j = _notifyWhenMaps.find(history);
|
||||||
if (j == notifyWhenMaps.end()) {
|
if (j == _notifyWhenMaps.end()) {
|
||||||
history->clearNotifications();
|
history->clearNotifications();
|
||||||
i = notifyWaiters.erase(i);
|
i = _notifyWaiters.erase(i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
@ -1589,8 +1285,8 @@ void MainWindow::notifyShowNext(NotifyWindow *remove) {
|
||||||
} while (history->currentNotification());
|
} while (history->currentNotification());
|
||||||
}
|
}
|
||||||
if (!history->currentNotification()) {
|
if (!history->currentNotification()) {
|
||||||
notifyWhenMaps.remove(history);
|
_notifyWhenMaps.remove(history);
|
||||||
i = notifyWaiters.erase(i);
|
i = _notifyWaiters.erase(i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
uint64 when = i.value().when;
|
uint64 when = i.value().when;
|
||||||
|
@ -1607,7 +1303,7 @@ void MainWindow::notifyShowNext(NotifyWindow *remove) {
|
||||||
next = nextAlert;
|
next = nextAlert;
|
||||||
nextAlert = 0;
|
nextAlert = 0;
|
||||||
}
|
}
|
||||||
notifyWaitTimer.start(next - ms);
|
_notifyWaitTimer.start(next - ms);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
HistoryItem *fwd = notifyItem->Has<HistoryMessageForwarded>() ? notifyItem : nullptr; // forwarded notify grouping
|
HistoryItem *fwd = notifyItem->Has<HistoryMessageForwarded>() ? notifyItem : nullptr; // forwarded notify grouping
|
||||||
|
@ -1615,8 +1311,8 @@ void MainWindow::notifyShowNext(NotifyWindow *remove) {
|
||||||
|
|
||||||
uint64 ms = getms(true);
|
uint64 ms = getms(true);
|
||||||
History *history = notifyItem->history();
|
History *history = notifyItem->history();
|
||||||
NotifyWhenMaps::iterator j = notifyWhenMaps.find(history);
|
NotifyWhenMaps::iterator j = _notifyWhenMaps.find(history);
|
||||||
if (j == notifyWhenMaps.cend()) {
|
if (j == _notifyWhenMaps.cend()) {
|
||||||
history->clearNotifications();
|
history->clearNotifications();
|
||||||
} else {
|
} else {
|
||||||
HistoryItem *nextNotify = 0;
|
HistoryItem *nextNotify = 0;
|
||||||
|
@ -1631,7 +1327,7 @@ void MainWindow::notifyShowNext(NotifyWindow *remove) {
|
||||||
NotifyWhenMap::const_iterator k = j.value().constFind(history->currentNotification()->id);
|
NotifyWhenMap::const_iterator k = j.value().constFind(history->currentNotification()->id);
|
||||||
if (k != j.value().cend()) {
|
if (k != j.value().cend()) {
|
||||||
nextNotify = history->currentNotification();
|
nextNotify = history->currentNotification();
|
||||||
notifyWaiters.insert(notifyHistory, NotifyWaiter(k.key(), k.value(), 0));
|
_notifyWaiters.insert(notifyHistory, NotifyWaiter(k.key(), k.value(), 0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
history->skipNotification();
|
history->skipNotification();
|
||||||
|
@ -1652,18 +1348,11 @@ void MainWindow::notifyShowNext(NotifyWindow *remove) {
|
||||||
} while (nextNotify);
|
} while (nextNotify);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Global::CustomNotifies()) {
|
Window::Notifications::manager()->showNotification(notifyItem, fwdCount);
|
||||||
NotifyWindow *notify = new NotifyWindow(notifyItem, x, y, fwdCount);
|
|
||||||
notifyWindows.push_back(notify);
|
|
||||||
psNotifyShown(notify);
|
|
||||||
--count;
|
|
||||||
} else {
|
|
||||||
psPlatformNotify(notifyItem, fwdCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!history->hasNotification()) {
|
if (!history->hasNotification()) {
|
||||||
notifyWaiters.remove(history);
|
_notifyWaiters.remove(history);
|
||||||
notifyWhenMaps.remove(history);
|
_notifyWhenMaps.remove(history);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1672,49 +1361,8 @@ void MainWindow::notifyShowNext(NotifyWindow *remove) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nextAlert) {
|
if (nextAlert) {
|
||||||
notifyWaitTimer.start(nextAlert - ms);
|
_notifyWaitTimer.start(nextAlert - ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
count = NotifyWindowsCount - count;
|
|
||||||
for (NotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
|
|
||||||
int32 ind = (*i)->index();
|
|
||||||
if (ind < 0) continue;
|
|
||||||
--count;
|
|
||||||
(*i)->moveTo(x, y - count * (st::notifyHeight + st::notifyDeltaY));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::notifyItemRemoved(HistoryItem *item) {
|
|
||||||
if (Global::CustomNotifies()) {
|
|
||||||
for (NotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
|
|
||||||
(*i)->itemRemoved(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::notifyStopHiding() {
|
|
||||||
if (Global::CustomNotifies()) {
|
|
||||||
for (NotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
|
|
||||||
(*i)->stopHiding();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::notifyStartHiding() {
|
|
||||||
if (Global::CustomNotifies()) {
|
|
||||||
for (NotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
|
|
||||||
(*i)->startHiding();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::notifyUpdateAllPhotos() {
|
|
||||||
if (Global::CustomNotifies()) {
|
|
||||||
for (NotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
|
|
||||||
(*i)->updatePeerPhoto();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_mediaView && !_mediaView->isHidden()) _mediaView->updateControls();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::app_activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button) {
|
void MainWindow::app_activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button) {
|
||||||
|
@ -1722,20 +1370,7 @@ void MainWindow::app_activateClickHandler(ClickHandlerPtr handler, Qt::MouseButt
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::notifyUpdateAll() {
|
void MainWindow::notifyUpdateAll() {
|
||||||
if (Global::CustomNotifies()) {
|
Window::Notifications::manager()->updateAll();
|
||||||
for (NotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
|
|
||||||
(*i)->updateNotifyDisplay();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
psClearNotifies();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::notifyActivateAll() {
|
|
||||||
if (Global::CustomNotifies()) {
|
|
||||||
for (NotifyWindows::const_iterator i = notifyWindows.cbegin(), e = notifyWindows.cend(); i != e; ++i) {
|
|
||||||
psActivateNotify(*i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage MainWindow::iconLarge() const {
|
QImage MainWindow::iconLarge() const {
|
||||||
|
|
|
@ -22,8 +22,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
#include "title.h"
|
#include "title.h"
|
||||||
#include "pspecific.h"
|
#include "pspecific.h"
|
||||||
#include "ui/boxshadow.h"
|
#include "ui/effects/rect_shadow.h"
|
||||||
#include "platform/platform_main_window.h"
|
#include "platform/platform_main_window.h"
|
||||||
|
#include "core/single_timer.h"
|
||||||
|
|
||||||
class MediaView;
|
class MediaView;
|
||||||
class TitleWidget;
|
class TitleWidget;
|
||||||
|
@ -32,9 +33,11 @@ class IntroWidget;
|
||||||
class MainWidget;
|
class MainWidget;
|
||||||
class LayerStackWidget;
|
class LayerStackWidget;
|
||||||
class LayerWidget;
|
class LayerWidget;
|
||||||
|
|
||||||
namespace Local {
|
namespace Local {
|
||||||
class ClearManager;
|
class ClearManager;
|
||||||
} // namespace Local
|
} // namespace Local
|
||||||
|
|
||||||
namespace Settings {
|
namespace Settings {
|
||||||
class Widget;
|
class Widget;
|
||||||
} // namespace Settings
|
} // namespace Settings
|
||||||
|
@ -43,87 +46,21 @@ class ConnectingWidget : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ConnectingWidget(QWidget *parent, const QString &text, const QString &reconnect);
|
ConnectingWidget(QWidget *parent, const QString &text, const QString &reconnect);
|
||||||
void set(const QString &text, const QString &reconnect);
|
void set(const QString &text, const QString &reconnect);
|
||||||
void paintEvent(QPaintEvent *e);
|
void paintEvent(QPaintEvent *e);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void onReconnect();
|
void onReconnect();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Ui::RectShadow _shadow;
|
||||||
BoxShadow _shadow;
|
|
||||||
QString _text;
|
QString _text;
|
||||||
int32 _textWidth;
|
int32 _textWidth;
|
||||||
LinkButton _reconnect;
|
LinkButton _reconnect;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class NotifyWindow : public TWidget {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
NotifyWindow(HistoryItem *item, int32 x, int32 y, int32 fwdCount);
|
|
||||||
|
|
||||||
void enterEvent(QEvent *e);
|
|
||||||
void leaveEvent(QEvent *e);
|
|
||||||
void mousePressEvent(QMouseEvent *e);
|
|
||||||
void paintEvent(QPaintEvent *e);
|
|
||||||
|
|
||||||
void step_appearance(float64 ms, bool timer);
|
|
||||||
void animHide(float64 duration, anim::transition func);
|
|
||||||
void startHiding();
|
|
||||||
void stopHiding();
|
|
||||||
void moveTo(int32 x, int32 y, int32 index = -1);
|
|
||||||
|
|
||||||
void updateNotifyDisplay();
|
|
||||||
void updatePeerPhoto();
|
|
||||||
|
|
||||||
void itemRemoved(HistoryItem *del);
|
|
||||||
|
|
||||||
int32 index() const {
|
|
||||||
return history ? _index : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void unlinkHistory(History *hist = 0);
|
|
||||||
|
|
||||||
~NotifyWindow();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
|
|
||||||
void hideByTimer();
|
|
||||||
void checkLastInput();
|
|
||||||
|
|
||||||
void unlinkHistoryAndNotify();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
#if defined Q_OS_WIN && !defined Q_OS_WINRT
|
|
||||||
DWORD started;
|
|
||||||
#endif // Q_OS_WIN && !Q_OS_WINRT
|
|
||||||
History *history;
|
|
||||||
HistoryItem *item;
|
|
||||||
int32 fwdCount;
|
|
||||||
IconedButton close;
|
|
||||||
QPixmap pm;
|
|
||||||
float64 alphaDuration, posDuration;
|
|
||||||
QTimer hideTimer, inputTimer;
|
|
||||||
bool hiding;
|
|
||||||
int32 _index;
|
|
||||||
anim::fvalue a_opacity;
|
|
||||||
anim::transition a_func;
|
|
||||||
anim::ivalue a_y;
|
|
||||||
Animation _a_appearance;
|
|
||||||
|
|
||||||
ImagePtr peerPhoto;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef QList<NotifyWindow*> NotifyWindows;
|
|
||||||
|
|
||||||
class MediaPreviewWidget;
|
class MediaPreviewWidget;
|
||||||
|
|
||||||
class MainWindow : public Platform::MainWindow, private base::Subscriber {
|
class MainWindow : public Platform::MainWindow, private base::Subscriber {
|
||||||
|
@ -204,12 +141,7 @@ public:
|
||||||
void notifySchedule(History *history, HistoryItem *item);
|
void notifySchedule(History *history, HistoryItem *item);
|
||||||
void notifyClear(History *history = 0);
|
void notifyClear(History *history = 0);
|
||||||
void notifyClearFast();
|
void notifyClearFast();
|
||||||
void notifyShowNext(NotifyWindow *remove = 0);
|
|
||||||
void notifyItemRemoved(HistoryItem *item);
|
|
||||||
void notifyStopHiding();
|
|
||||||
void notifyStartHiding();
|
|
||||||
void notifyUpdateAll();
|
void notifyUpdateAll();
|
||||||
void notifyActivateAll();
|
|
||||||
|
|
||||||
QImage iconLarge() const;
|
QImage iconLarge() const;
|
||||||
|
|
||||||
|
@ -266,7 +198,7 @@ public slots:
|
||||||
void onClearFinished(int task, void *manager);
|
void onClearFinished(int task, void *manager);
|
||||||
void onClearFailed(int task, void *manager);
|
void onClearFailed(int task, void *manager);
|
||||||
|
|
||||||
void notifyFire();
|
void notifyShowNext();
|
||||||
void updateTrayMenu(bool force = false);
|
void updateTrayMenu(bool force = false);
|
||||||
|
|
||||||
void onShowAddContact();
|
void onShowAddContact();
|
||||||
|
@ -278,8 +210,6 @@ public slots:
|
||||||
|
|
||||||
void onReActivate();
|
void onReActivate();
|
||||||
|
|
||||||
void notifyUpdateAllPhotos();
|
|
||||||
|
|
||||||
void app_activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button);
|
void app_activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -333,28 +263,30 @@ private:
|
||||||
SingleTimer _autoLockTimer;
|
SingleTimer _autoLockTimer;
|
||||||
uint64 _shouldLockAt = 0;
|
uint64 _shouldLockAt = 0;
|
||||||
|
|
||||||
typedef QMap<MsgId, uint64> NotifyWhenMap;
|
using NotifyWhenMap = QMap<MsgId, uint64>;
|
||||||
typedef QMap<History*, NotifyWhenMap> NotifyWhenMaps;
|
using NotifyWhenMaps = QMap<History*, NotifyWhenMap>;
|
||||||
NotifyWhenMaps notifyWhenMaps;
|
NotifyWhenMaps _notifyWhenMaps;
|
||||||
struct NotifyWaiter {
|
struct NotifyWaiter {
|
||||||
NotifyWaiter(MsgId msg, uint64 when, PeerData *notifyByFrom) : msg(msg), when(when), notifyByFrom(notifyByFrom) {
|
NotifyWaiter(MsgId msg, uint64 when, PeerData *notifyByFrom)
|
||||||
|
: msg(msg)
|
||||||
|
, when(when)
|
||||||
|
, notifyByFrom(notifyByFrom) {
|
||||||
}
|
}
|
||||||
MsgId msg;
|
MsgId msg;
|
||||||
uint64 when;
|
uint64 when;
|
||||||
PeerData *notifyByFrom;
|
PeerData *notifyByFrom;
|
||||||
};
|
};
|
||||||
typedef QMap<History*, NotifyWaiter> NotifyWaiters;
|
using NotifyWaiters = QMap<History*, NotifyWaiter>;
|
||||||
NotifyWaiters notifyWaiters;
|
NotifyWaiters _notifyWaiters;
|
||||||
NotifyWaiters notifySettingWaiters;
|
NotifyWaiters _notifySettingWaiters;
|
||||||
SingleTimer notifyWaitTimer;
|
SingleTimer _notifyWaitTimer;
|
||||||
|
|
||||||
typedef QMap<uint64, PeerData*> NotifyWhenAlert;
|
using NotifyWhenAlert = QMap<uint64, PeerData*>;
|
||||||
typedef QMap<History*, NotifyWhenAlert> NotifyWhenAlerts;
|
using NotifyWhenAlerts = QMap<History*, NotifyWhenAlert>;
|
||||||
NotifyWhenAlerts notifyWhenAlerts;
|
NotifyWhenAlerts _notifyWhenAlerts;
|
||||||
|
|
||||||
NotifyWindows notifyWindows;
|
|
||||||
|
|
||||||
MediaView *_mediaView = nullptr;
|
MediaView *_mediaView = nullptr;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class PreLaunchWindow : public TWidget {
|
class PreLaunchWindow : public TWidget {
|
||||||
|
|
|
@ -985,13 +985,13 @@ void AudioPlayerFader::onTimer() {
|
||||||
} else if (ms > _suppressAllStart + notifyLengthMs - AudioFadeDuration) {
|
} else if (ms > _suppressAllStart + notifyLengthMs - AudioFadeDuration) {
|
||||||
if (_suppressAllGain.to() != 1.) _suppressAllGain.start(1.);
|
if (_suppressAllGain.to() != 1.) _suppressAllGain.start(1.);
|
||||||
_suppressAllGain.update(1. - ((_suppressAllStart + notifyLengthMs - ms) / float64(AudioFadeDuration)), anim::linear);
|
_suppressAllGain.update(1. - ((_suppressAllStart + notifyLengthMs - ms) / float64(AudioFadeDuration)), anim::linear);
|
||||||
} else if (ms >= _suppressAllStart + st::notifyFastAnim) {
|
} else if (ms >= _suppressAllStart + st::mediaPlayerSuppressDuration) {
|
||||||
if (_suppressAllAnim) {
|
if (_suppressAllAnim) {
|
||||||
_suppressAllGain.finish();
|
_suppressAllGain.finish();
|
||||||
_suppressAllAnim = false;
|
_suppressAllAnim = false;
|
||||||
}
|
}
|
||||||
} else if (ms > _suppressAllStart) {
|
} else if (ms > _suppressAllStart) {
|
||||||
_suppressAllGain.update((ms - _suppressAllStart) / st::notifyFastAnim, anim::linear);
|
_suppressAllGain.update((ms - _suppressAllStart) / st::mediaPlayerSuppressDuration, anim::linear);
|
||||||
}
|
}
|
||||||
suppressAllGain = _suppressAllGain.current();
|
suppressAllGain = _suppressAllGain.current();
|
||||||
suppressAudioChanged = (suppressAllGain != wasAudio);
|
suppressAudioChanged = (suppressAllGain != wasAudio);
|
||||||
|
|
|
@ -75,7 +75,7 @@ AudioPlayerLoaders::~AudioPlayerLoaders() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioPlayerLoaders::clearFromVideoQueue() {
|
void AudioPlayerLoaders::clearFromVideoQueue() {
|
||||||
auto queue = createAndSwap(_fromVideoQueue);
|
auto queue = base::take(_fromVideoQueue);
|
||||||
for (auto &packetData : queue) {
|
for (auto &packetData : queue) {
|
||||||
AVPacket packet;
|
AVPacket packet;
|
||||||
FFMpeg::packetFromDataWrap(packet, packetData);
|
FFMpeg::packetFromDataWrap(packet, packetData);
|
||||||
|
|
|
@ -197,7 +197,7 @@ void ChildFFMpegLoader::enqueuePackets(QQueue<FFMpeg::AVPacketDataWrap> &packets
|
||||||
}
|
}
|
||||||
|
|
||||||
ChildFFMpegLoader::~ChildFFMpegLoader() {
|
ChildFFMpegLoader::~ChildFFMpegLoader() {
|
||||||
auto queue = createAndSwap(_queue);
|
auto queue = base::take(_queue);
|
||||||
for (auto &packetData : queue) {
|
for (auto &packetData : queue) {
|
||||||
AVPacket packet;
|
AVPacket packet;
|
||||||
FFMpeg::packetFromDataWrap(packet, packetData);
|
FFMpeg::packetFromDataWrap(packet, packetData);
|
||||||
|
|
|
@ -525,7 +525,7 @@ void FFMpegReaderImplementation::finishPacket() {
|
||||||
|
|
||||||
void FFMpegReaderImplementation::clearPacketQueue() {
|
void FFMpegReaderImplementation::clearPacketQueue() {
|
||||||
finishPacket();
|
finishPacket();
|
||||||
auto packets = createAndSwap(_packetQueue);
|
auto packets = base::take(_packetQueue);
|
||||||
for (auto &packetData : packets) {
|
for (auto &packetData : packets) {
|
||||||
AVPacket packet;
|
AVPacket packet;
|
||||||
FFMpeg::packetFromDataWrap(packet, packetData);
|
FFMpeg::packetFromDataWrap(packet, packetData);
|
||||||
|
|
|
@ -106,7 +106,7 @@ bool QtGifReaderImplementation::start(Mode mode, int64 &positionMs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QtGifReaderImplementation::~QtGifReaderImplementation() {
|
QtGifReaderImplementation::~QtGifReaderImplementation() {
|
||||||
deleteAndMark(_reader);
|
delete base::take(_reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QtGifReaderImplementation::jumpToStart() {
|
bool QtGifReaderImplementation::jumpToStart() {
|
||||||
|
|
|
@ -44,8 +44,7 @@ bool exists() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void finish() {
|
void finish() {
|
||||||
auto temp = createAndSwap(SingleInstance);
|
delete base::take(SingleInstance);
|
||||||
delete temp;
|
|
||||||
|
|
||||||
audioFinish();
|
audioFinish();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ui/boxshadow.h"
|
#include "ui/effects/rect_shadow.h"
|
||||||
|
|
||||||
class ScrollArea;
|
class ScrollArea;
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "application.h"
|
#include "application.h"
|
||||||
#include "ui/filedialog.h"
|
#include "ui/filedialog.h"
|
||||||
|
#include "ui/popupmenu.h"
|
||||||
#include "media/media_clip_reader.h"
|
#include "media/media_clip_reader.h"
|
||||||
#include "media/view/media_clip_controller.h"
|
#include "media/view/media_clip_controller.h"
|
||||||
#include "styles/style_mediaview.h"
|
#include "styles/style_mediaview.h"
|
||||||
|
@ -96,6 +97,12 @@ MediaView::MediaView() : TWidget(App::wnd())
|
||||||
|
|
||||||
connect(QApplication::desktop(), SIGNAL(resized(int)), this, SLOT(onScreenResized(int)));
|
connect(QApplication::desktop(), SIGNAL(resized(int)), this, SLOT(onScreenResized(int)));
|
||||||
|
|
||||||
|
subscribe(FileDownload::ImageLoaded(), [this] {
|
||||||
|
if (!isHidden()) {
|
||||||
|
updateControls();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
_transparentBrush = QBrush(App::sprite().copy(st::mvTransparentBrush.rect()));
|
_transparentBrush = QBrush(App::sprite().copy(st::mvTransparentBrush.rect()));
|
||||||
|
|
||||||
setWindowFlags(Qt::FramelessWindowHint | Qt::BypassWindowManagerHint | Qt::Tool | Qt::NoDropShadowWindowHint);
|
setWindowFlags(Qt::FramelessWindowHint | Qt::BypassWindowManagerHint | Qt::Tool | Qt::NoDropShadowWindowHint);
|
||||||
|
@ -612,7 +619,7 @@ void MediaView::clearData() {
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaView::~MediaView() {
|
MediaView::~MediaView() {
|
||||||
deleteAndMark(_menu);
|
delete base::take(_menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaView::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
|
void MediaView::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
|
||||||
|
|
|
@ -29,9 +29,11 @@ class Controller;
|
||||||
} // namespace Clip
|
} // namespace Clip
|
||||||
} // namespace Media
|
} // namespace Media
|
||||||
|
|
||||||
|
class PopupMenu;
|
||||||
|
|
||||||
struct AudioPlaybackState;
|
struct AudioPlaybackState;
|
||||||
|
|
||||||
class MediaView : public TWidget, public RPCSender, public ClickHandlerHost {
|
class MediaView : public TWidget, private base::Subscriber, public RPCSender, public ClickHandlerHost {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -44,17 +44,17 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 getDC() const {
|
uint32 getDC() const {
|
||||||
if (!_isset) throw mtpErrorKeyNotReady("getDC()");
|
t_assert(_isset);
|
||||||
return _dc;
|
return _dc;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 keyId() const {
|
uint64 keyId() const {
|
||||||
if (!_isset) throw mtpErrorKeyNotReady("keyId()");
|
t_assert(_isset);
|
||||||
return _keyId;
|
return _keyId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepareAES(const MTPint128 &msgKey, MTPint256 &aesKey, MTPint256 &aesIV, bool send = true) const {
|
void prepareAES(const MTPint128 &msgKey, MTPint256 &aesKey, MTPint256 &aesIV, bool send = true) const {
|
||||||
if (!_isset) throw mtpErrorKeyNotReady(QString("prepareAES(..., %1)").arg(Logs::b(send)));
|
t_assert(_isset);
|
||||||
|
|
||||||
uint32 x = send ? 0 : 8;
|
uint32 x = send ? 0 : 8;
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void write(QDataStream &to) const {
|
void write(QDataStream &to) const {
|
||||||
if (!_isset) throw mtpErrorKeyNotReady("write(...)");
|
t_assert(_isset);
|
||||||
to.writeRawData(_key, 256);
|
to.writeRawData(_key, 256);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#include "mtproto/core_types.h"
|
#include "mtproto/core_types.h"
|
||||||
#include "mtproto/auth_key.h"
|
#include "mtproto/auth_key.h"
|
||||||
#include "mtproto/connection_abstract.h"
|
#include "mtproto/connection_abstract.h"
|
||||||
|
#include "core/single_timer.h"
|
||||||
|
|
||||||
namespace MTP {
|
namespace MTP {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
|
@ -298,7 +298,7 @@ void AbstractTCPConnection::tcpSend(mtpBuffer &buffer) {
|
||||||
// prepare decryption key/iv
|
// prepare decryption key/iv
|
||||||
char reversed[48];
|
char reversed[48];
|
||||||
memcpy(reversed, nonce + 8, sizeof(reversed));
|
memcpy(reversed, nonce + 8, sizeof(reversed));
|
||||||
std::reverse(reversed, reversed + arraysize(reversed));
|
std::reverse(reversed, reversed + base::array_size(reversed));
|
||||||
memcpy(_receiveKey, reversed, CTRState::KeySize);
|
memcpy(_receiveKey, reversed, CTRState::KeySize);
|
||||||
memcpy(_receiveState.ivec, reversed + CTRState::KeySize, CTRState::IvecSize);
|
memcpy(_receiveState.ivec, reversed + CTRState::KeySize, CTRState::IvecSize);
|
||||||
|
|
||||||
|
|
|
@ -199,30 +199,12 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class mtpErrorUninitialized : public Exception {
|
|
||||||
public:
|
|
||||||
mtpErrorUninitialized() : Exception("MTP Uninitialized variable write attempt") {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class mtpErrorBadTypeId : public Exception {
|
class mtpErrorBadTypeId : public Exception {
|
||||||
public:
|
public:
|
||||||
mtpErrorBadTypeId(mtpTypeId typeId, const QString &type) : Exception(QString("MTP Bad type id %1 passed to constructor of %2").arg(typeId).arg(type)) {
|
mtpErrorBadTypeId(mtpTypeId typeId, const QString &type) : Exception(QString("MTP Bad type id %1 passed to constructor of %2").arg(typeId).arg(type)) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class mtpErrorWrongTypeId : public Exception {
|
|
||||||
public:
|
|
||||||
mtpErrorWrongTypeId(mtpTypeId typeId, mtpTypeId required) : Exception(QString("MTP Wrong type id %1 for this data conversion, must be %2").arg(typeId).arg(required)) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class mtpErrorKeyNotReady : public Exception {
|
|
||||||
public:
|
|
||||||
mtpErrorKeyNotReady(const QString &method) : Exception(QString("MTP Auth key is used in %1 without being created").arg(method)) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class mtpData {
|
class mtpData {
|
||||||
public:
|
public:
|
||||||
mtpData() : cnt(1) {
|
mtpData() : cnt(1) {
|
||||||
|
@ -686,12 +668,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
MTPDstring &_string() {
|
MTPDstring &_string() {
|
||||||
if (!data) throw mtpErrorUninitialized();
|
t_assert(data != nullptr);
|
||||||
split();
|
split();
|
||||||
return *(MTPDstring*)data;
|
return *(MTPDstring*)data;
|
||||||
}
|
}
|
||||||
const MTPDstring &c_string() const {
|
const MTPDstring &c_string() const {
|
||||||
if (!data) throw mtpErrorUninitialized();
|
t_assert(data != nullptr);
|
||||||
return *(const MTPDstring*)data;
|
return *(const MTPDstring*)data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -823,12 +805,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
MTPDvector<T> &_vector() {
|
MTPDvector<T> &_vector() {
|
||||||
if (!data) throw mtpErrorUninitialized();
|
t_assert(data != nullptr);
|
||||||
split();
|
split();
|
||||||
return *(MTPDvector<T>*)data;
|
return *(MTPDvector<T>*)data;
|
||||||
}
|
}
|
||||||
const MTPDvector<T> &c_vector() const {
|
const MTPDvector<T> &c_vector() const {
|
||||||
if (!data) throw mtpErrorUninitialized();
|
t_assert(data != nullptr);
|
||||||
return *(const MTPDvector<T>*)data;
|
return *(const MTPDvector<T>*)data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/single_timer.h"
|
||||||
|
|
||||||
namespace MTP {
|
namespace MTP {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
@ -27,7 +29,6 @@ class Dcenter : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Dcenter(int32 id, const AuthKeyPtr &key);
|
Dcenter(int32 id, const AuthKeyPtr &key);
|
||||||
|
|
||||||
QReadWriteLock *keyMutex() const;
|
QReadWriteLock *keyMutex() const;
|
||||||
|
@ -46,21 +47,19 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void authKeyCreated();
|
void authKeyCreated();
|
||||||
void layerWasInited(bool was);
|
void layerWasInited(bool was);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void authKeyWrite();
|
void authKeyWrite();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
mutable QReadWriteLock keyLock;
|
mutable QReadWriteLock keyLock;
|
||||||
mutable QMutex initLock;
|
mutable QMutex initLock;
|
||||||
int32 _id;
|
int32 _id;
|
||||||
AuthKeyPtr _key;
|
AuthKeyPtr _key;
|
||||||
bool _connectionInited;
|
bool _connectionInited;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef QSharedPointer<Dcenter> DcenterPtr;
|
typedef QSharedPointer<Dcenter> DcenterPtr;
|
||||||
|
@ -70,21 +69,17 @@ class ConfigLoader : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ConfigLoader();
|
ConfigLoader();
|
||||||
void load();
|
void load();
|
||||||
void done();
|
void done();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void enumDC();
|
void enumDC();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void loaded();
|
void loaded();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
SingleTimer _enumDCTimer;
|
SingleTimer _enumDCTimer;
|
||||||
int32 _enumCurrent;
|
int32 _enumCurrent;
|
||||||
mtpRequestId _enumRequest;
|
mtpRequestId _enumRequest;
|
||||||
|
|
|
@ -22,6 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
#include "mtproto/core_types.h"
|
#include "mtproto/core_types.h"
|
||||||
#include "mtproto/session.h"
|
#include "mtproto/session.h"
|
||||||
|
#include "core/single_timer.h"
|
||||||
|
|
||||||
namespace MTP {
|
namespace MTP {
|
||||||
|
|
||||||
|
@ -57,17 +58,15 @@ class GlobalSlotCarrier : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
GlobalSlotCarrier();
|
GlobalSlotCarrier();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void checkDelayed();
|
void checkDelayed();
|
||||||
void connectionFinished(Connection *connection);
|
void connectionFinished(Connection *connection);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
SingleTimer _timer;
|
SingleTimer _timer;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
GlobalSlotCarrier *globalSlotCarrier();
|
GlobalSlotCarrier *globalSlotCarrier();
|
||||||
|
|
|
@ -612,17 +612,19 @@ for restype in typesList:
|
||||||
withData = 1;
|
withData = 1;
|
||||||
|
|
||||||
getters += '\n\tMTPD' + name + ' &_' + name + '() {\n'; # splitting getter
|
getters += '\n\tMTPD' + name + ' &_' + name + '() {\n'; # splitting getter
|
||||||
getters += '\t\tif (!data) throw mtpErrorUninitialized();\n';
|
|
||||||
if (withType):
|
if (withType):
|
||||||
getters += '\t\tif (_type != mtpc_' + name + ') throw mtpErrorWrongTypeId(_type, mtpc_' + name + ');\n';
|
getters += '\t\tt_assert(data != nullptr && _type == mtpc_' + name + ');\n';
|
||||||
|
else:
|
||||||
|
getters += '\t\tt_assert(data != nullptr);\n';
|
||||||
getters += '\t\tsplit();\n';
|
getters += '\t\tsplit();\n';
|
||||||
getters += '\t\treturn *(MTPD' + name + '*)data;\n';
|
getters += '\t\treturn *(MTPD' + name + '*)data;\n';
|
||||||
getters += '\t}\n';
|
getters += '\t}\n';
|
||||||
|
|
||||||
getters += '\tconst MTPD' + name + ' &c_' + name + '() const {\n'; # const getter
|
getters += '\tconst MTPD' + name + ' &c_' + name + '() const {\n'; # const getter
|
||||||
getters += '\t\tif (!data) throw mtpErrorUninitialized();\n';
|
|
||||||
if (withType):
|
if (withType):
|
||||||
getters += '\t\tif (_type != mtpc_' + name + ') throw mtpErrorWrongTypeId(_type, mtpc_' + name + ');\n';
|
getters += '\t\tt_assert(data != nullptr && _type == mtpc_' + name + ');\n';
|
||||||
|
else:
|
||||||
|
getters += '\t\tt_assert(data != nullptr);\n';
|
||||||
getters += '\t\treturn *(const MTPD' + name + '*)data;\n';
|
getters += '\t\treturn *(const MTPD' + name + '*)data;\n';
|
||||||
getters += '\t}\n';
|
getters += '\t}\n';
|
||||||
|
|
||||||
|
@ -783,7 +785,7 @@ for restype in typesList:
|
||||||
typesText += '\tmtpTypeId type() const;\n'; # type id method
|
typesText += '\tmtpTypeId type() const;\n'; # type id method
|
||||||
inlineMethods += 'inline mtpTypeId MTP' + restype + '::type() const {\n';
|
inlineMethods += 'inline mtpTypeId MTP' + restype + '::type() const {\n';
|
||||||
if (withType):
|
if (withType):
|
||||||
inlineMethods += '\tif (!_type) throw mtpErrorUninitialized();\n';
|
inlineMethods += '\tt_assert(_type != 0);\n';
|
||||||
inlineMethods += '\treturn _type;\n';
|
inlineMethods += '\treturn _type;\n';
|
||||||
else:
|
else:
|
||||||
inlineMethods += '\treturn mtpc_' + v[0][0] + ';\n';
|
inlineMethods += '\treturn mtpc_' + v[0][0] + ';\n';
|
||||||
|
|
|
@ -20,9 +20,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/lambda_wrap.h"
|
||||||
|
|
||||||
class RPCError {
|
class RPCError {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
RPCError(const MTPrpcError &error) : _code(error.c_rpc_error().verror_code.v) {
|
RPCError(const MTPrpcError &error) : _code(error.c_rpc_error().verror_code.v) {
|
||||||
QString text = qs(error.c_rpc_error().verror_message);
|
QString text = qs(error.c_rpc_error().verror_message);
|
||||||
if (_code < 0 || _code >= 500) {
|
if (_code < 0 || _code >= 500) {
|
||||||
|
@ -827,3 +828,187 @@ protected:
|
||||||
|
|
||||||
typedef void (*MTPStateChangedHandler)(int32 dcId, int32 state);
|
typedef void (*MTPStateChangedHandler)(int32 dcId, int32 state);
|
||||||
typedef void(*MTPSessionResetHandler)(int32 dcId);
|
typedef void(*MTPSessionResetHandler)(int32 dcId);
|
||||||
|
|
||||||
|
template <typename FunctionType>
|
||||||
|
struct LambdaUniqueHelper;
|
||||||
|
|
||||||
|
template <typename Lambda, typename R, typename ...Args>
|
||||||
|
struct LambdaUniqueHelper<R(Lambda::*)(Args...) const> {
|
||||||
|
using UniqueType = base::lambda_unique<R(Args...)>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename FunctionType>
|
||||||
|
using LambdaGetUnique = typename LambdaUniqueHelper<FunctionType>::UniqueType;
|
||||||
|
|
||||||
|
template <typename Base, typename FunctionType>
|
||||||
|
class RPCHandlerImplementation : public Base {
|
||||||
|
protected:
|
||||||
|
using Lambda = base::lambda_unique<FunctionType>;
|
||||||
|
using Parent = RPCHandlerImplementation<Base, FunctionType>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RPCHandlerImplementation(Lambda &&handler) : _handler(std_::move(handler)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Lambda _handler;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename FunctionType>
|
||||||
|
using RPCDoneHandlerImplementation = RPCHandlerImplementation<RPCAbstractDoneHandler, FunctionType>;
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
class RPCDoneHandlerImplementationBare : public RPCDoneHandlerImplementation<R(const mtpPrime*, const mtpPrime*)> { // done(from, end)
|
||||||
|
public:
|
||||||
|
using RPCDoneHandlerImplementation<R(const mtpPrime*, const mtpPrime*)>::Parent::Parent;
|
||||||
|
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) const override {
|
||||||
|
return this->_handler ? this->_handler(from, end) : void(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
class RPCDoneHandlerImplementationBareReq : public RPCDoneHandlerImplementation<R(const mtpPrime*, const mtpPrime*, mtpRequestId)> { // done(from, end, req_id)
|
||||||
|
public:
|
||||||
|
using RPCDoneHandlerImplementation<R(const mtpPrime*, const mtpPrime*, mtpRequestId)>::Parent::Parent;
|
||||||
|
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) const override {
|
||||||
|
return this->_handler ? this->_handler(from, end, requestId) : void(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename T>
|
||||||
|
class RPCDoneHandlerImplementationPlain : public RPCDoneHandlerImplementation<R(const T&)> { // done(result)
|
||||||
|
public:
|
||||||
|
using RPCDoneHandlerImplementation<R(const T&)>::Parent::Parent;
|
||||||
|
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) const override {
|
||||||
|
return this->_handler ? this->_handler(T(from, end)) : void(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename T>
|
||||||
|
class RPCDoneHandlerImplementationReq : public RPCDoneHandlerImplementation<R(const T&, mtpRequestId)> { // done(result, req_id)
|
||||||
|
public:
|
||||||
|
using RPCDoneHandlerImplementation<R(const T&, mtpRequestId)>::Parent::Parent;
|
||||||
|
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) const override {
|
||||||
|
return this->_handler ? this->_handler(T(from, end), requestId) : void(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
class RPCDoneHandlerImplementationNo : public RPCDoneHandlerImplementation<R()> { // done()
|
||||||
|
public:
|
||||||
|
using RPCDoneHandlerImplementation<R()>::Parent::Parent;
|
||||||
|
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) const override {
|
||||||
|
return this->_handler ? this->_handler() : void(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
class RPCDoneHandlerImplementationNoReq : public RPCDoneHandlerImplementation<R(mtpRequestId)> { // done(req_id)
|
||||||
|
public:
|
||||||
|
using RPCDoneHandlerImplementation<R(mtpRequestId)>::Parent::Parent;
|
||||||
|
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) const override {
|
||||||
|
return this->_handler ? this->_handler(requestId) : void(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
inline RPCDoneHandlerPtr rpcDone_lambda_wrap_helper(base::lambda_unique<R(const mtpPrime*, const mtpPrime*)> &&lambda) {
|
||||||
|
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationBare<R>(std_::move(lambda)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
inline RPCDoneHandlerPtr rpcDone_lambda_wrap_helper(base::lambda_unique<R(const mtpPrime*, const mtpPrime*, mtpRequestId)> &&lambda) {
|
||||||
|
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationBareReq<R>(std_::move(lambda)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R, typename T>
|
||||||
|
inline RPCDoneHandlerPtr rpcDone_lambda_wrap_helper(base::lambda_unique<R(const T&)> &&lambda) {
|
||||||
|
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationPlain<R, T>(std_::move(lambda)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R, typename T>
|
||||||
|
inline RPCDoneHandlerPtr rpcDone_lambda_wrap_helper(base::lambda_unique<R(const T&, mtpRequestId)> &&lambda) {
|
||||||
|
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationReq<R, T>(std_::move(lambda)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
inline RPCDoneHandlerPtr rpcDone_lambda_wrap_helper(base::lambda_unique<R()> &&lambda) {
|
||||||
|
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationNo<R>(std_::move(lambda)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
inline RPCDoneHandlerPtr rpcDone_lambda_wrap_helper(base::lambda_unique<R(mtpRequestId)> &&lambda) {
|
||||||
|
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationNoReq<R>(std_::move(lambda)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Lambda, typename = std_::enable_if_t<std_::is_rvalue_reference<Lambda&&>::value>>
|
||||||
|
RPCDoneHandlerPtr rpcDone(Lambda &&lambda) {
|
||||||
|
return rpcDone_lambda_wrap_helper(LambdaGetUnique<decltype(&Lambda::operator())>(std_::move(lambda)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FunctionType>
|
||||||
|
using RPCFailHandlerImplementation = RPCHandlerImplementation<RPCAbstractFailHandler, FunctionType>;
|
||||||
|
|
||||||
|
class RPCFailHandlerImplementationPlain : public RPCFailHandlerImplementation<bool(const RPCError&)> { // fail(error)
|
||||||
|
public:
|
||||||
|
using Parent::Parent;
|
||||||
|
bool operator()(mtpRequestId requestId, const RPCError &error) const override {
|
||||||
|
return _handler ? _handler(error) : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class RPCFailHandlerImplementationReq : public RPCFailHandlerImplementation<bool(const RPCError&, mtpRequestId)> { // fail(error, req_id)
|
||||||
|
public:
|
||||||
|
using Parent::Parent;
|
||||||
|
bool operator()(mtpRequestId requestId, const RPCError &error) const override {
|
||||||
|
return this->_handler ? this->_handler(error, requestId) : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class RPCFailHandlerImplementationNo : public RPCFailHandlerImplementation<bool()> { // fail()
|
||||||
|
public:
|
||||||
|
using Parent::Parent;
|
||||||
|
bool operator()(mtpRequestId requestId, const RPCError &error) const override {
|
||||||
|
return this->_handler ? this->_handler() : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class RPCFailHandlerImplementationNoReq : public RPCFailHandlerImplementation<bool(mtpRequestId)> { // fail(req_id)
|
||||||
|
public:
|
||||||
|
using Parent::Parent;
|
||||||
|
bool operator()(mtpRequestId requestId, const RPCError &error) const override {
|
||||||
|
return this->_handler ? this->_handler(requestId) : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
inline RPCFailHandlerPtr rpcFail_lambda_wrap_helper(base::lambda_unique<bool(const RPCError&)> &&lambda) {
|
||||||
|
return RPCFailHandlerPtr(new RPCFailHandlerImplementationPlain(std_::move(lambda)));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline RPCFailHandlerPtr rpcFail_lambda_wrap_helper(base::lambda_unique<bool(const RPCError&, mtpRequestId)> &&lambda) {
|
||||||
|
return RPCFailHandlerPtr(new RPCFailHandlerImplementationReq(std_::move(lambda)));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline RPCFailHandlerPtr rpcFail_lambda_wrap_helper(base::lambda_unique<bool()> &&lambda) {
|
||||||
|
return RPCFailHandlerPtr(new RPCFailHandlerImplementationNo(std_::move(lambda)));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline RPCFailHandlerPtr rpcFail_lambda_wrap_helper(base::lambda_unique<bool(mtpRequestId)> &&lambda) {
|
||||||
|
return RPCFailHandlerPtr(new RPCFailHandlerImplementationNoReq(std_::move(lambda)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Lambda, typename = std_::enable_if_t<std_::is_rvalue_reference<Lambda&&>::value>>
|
||||||
|
RPCFailHandlerPtr rpcFail(Lambda &&lambda) {
|
||||||
|
return rpcFail_lambda_wrap_helper(LambdaGetUnique<decltype(&Lambda::operator())>(std_::move(lambda)));
|
||||||
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#include "mtproto/connection.h"
|
#include "mtproto/connection.h"
|
||||||
#include "mtproto/dcenter.h"
|
#include "mtproto/dcenter.h"
|
||||||
#include "mtproto/rpc_sender.h"
|
#include "mtproto/rpc_sender.h"
|
||||||
|
#include "core/single_timer.h"
|
||||||
|
|
||||||
namespace MTP {
|
namespace MTP {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
@ -31,7 +32,6 @@ class Session;
|
||||||
|
|
||||||
class SessionData {
|
class SessionData {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
SessionData(Session *creator)
|
SessionData(Session *creator)
|
||||||
: _session(0)
|
: _session(0)
|
||||||
, _salt(0)
|
, _salt(0)
|
||||||
|
@ -227,7 +227,6 @@ class Session : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Session(int32 dcenter);
|
Session(int32 dcenter);
|
||||||
|
|
||||||
void restart();
|
void restart();
|
||||||
|
@ -237,7 +236,6 @@ public:
|
||||||
void unpaused();
|
void unpaused();
|
||||||
|
|
||||||
int32 getDcWithShift() const;
|
int32 getDcWithShift() const;
|
||||||
~Session();
|
|
||||||
|
|
||||||
QReadWriteLock *keyMutex() const;
|
QReadWriteLock *keyMutex() const;
|
||||||
void notifyKeyCreated(const AuthKeyPtr &key);
|
void notifyKeyCreated(const AuthKeyPtr &key);
|
||||||
|
@ -255,15 +253,15 @@ public:
|
||||||
|
|
||||||
void sendPrepared(const mtpRequest &request, uint64 msCanWait = 0, bool newRequest = true); // nulls msgId and seqNo in request, if newRequest = true
|
void sendPrepared(const mtpRequest &request, uint64 msCanWait = 0, bool newRequest = true); // nulls msgId and seqNo in request, if newRequest = true
|
||||||
|
|
||||||
signals:
|
~Session();
|
||||||
|
|
||||||
|
signals:
|
||||||
void authKeyCreated();
|
void authKeyCreated();
|
||||||
void needToSend();
|
void needToSend();
|
||||||
void needToPing();
|
void needToPing();
|
||||||
void needToRestart();
|
void needToRestart();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void needToResumeAndSend();
|
void needToResumeAndSend();
|
||||||
|
|
||||||
mtpRequestId resend(quint64 msgId, quint64 msCanWait = 0, bool forceContainer = false, bool sendMsgStateInfo = false);
|
mtpRequestId resend(quint64 msgId, quint64 msCanWait = 0, bool forceContainer = false, bool sendMsgStateInfo = false);
|
||||||
|
@ -283,7 +281,6 @@ public slots:
|
||||||
void sendMsgsStateInfo(quint64 msgId, QByteArray data);
|
void sendMsgsStateInfo(quint64 msgId, QByteArray data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Connection *_connection;
|
Connection *_connection;
|
||||||
|
|
||||||
bool _killed;
|
bool _killed;
|
||||||
|
|
|
@ -98,8 +98,8 @@ void peerUpdatedSendDelayed() {
|
||||||
|
|
||||||
if (!SmallUpdates || !AllUpdates || SmallUpdates->empty()) return;
|
if (!SmallUpdates || !AllUpdates || SmallUpdates->empty()) return;
|
||||||
|
|
||||||
auto smallList = createAndSwap(*SmallUpdates);
|
auto smallList = base::take(*SmallUpdates);
|
||||||
auto allList = createAndSwap(*AllUpdates);
|
auto allList = base::take(*AllUpdates);
|
||||||
for (auto &update : smallList) {
|
for (auto &update : smallList) {
|
||||||
PeerUpdated().notify(std_::move(update), true);
|
PeerUpdated().notify(std_::move(update), true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,7 +106,7 @@ void RadialProgressItem::checkRadialFinished() {
|
||||||
}
|
}
|
||||||
|
|
||||||
RadialProgressItem::~RadialProgressItem() {
|
RadialProgressItem::~RadialProgressItem() {
|
||||||
deleteAndMark(_radial);
|
delete base::take(_radial);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileBase::setStatusSize(int32 newSize, int32 fullSize, int32 duration, qint64 realDuration) const {
|
void FileBase::setStatusSize(int32 newSize, int32 fullSize, int32 duration, qint64 realDuration) const {
|
||||||
|
|
|
@ -21,6 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "window/section_widget.h"
|
#include "window/section_widget.h"
|
||||||
|
#include "ui/popupmenu.h"
|
||||||
|
|
||||||
namespace Overview {
|
namespace Overview {
|
||||||
namespace Layout {
|
namespace Layout {
|
||||||
|
|
122
Telegram/SourceFiles/platform/linux/linux_libnotify.cpp
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||||
|
|
||||||
|
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
It is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
In addition, as a special exception, the copyright holders give permission
|
||||||
|
to link the code of portions of this program with the OpenSSL library.
|
||||||
|
|
||||||
|
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||||
|
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
*/
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "platform/linux/linux_libnotify.h"
|
||||||
|
|
||||||
|
#include "platform/linux/linux_libs.h"
|
||||||
|
|
||||||
|
namespace Platform {
|
||||||
|
namespace Libs {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool loadLibrary(QLibrary &lib, const char *name, int version) {
|
||||||
|
DEBUG_LOG(("Loading '%1' with version %2...").arg(QLatin1String(name)).arg(version));
|
||||||
|
lib.setFileNameAndVersion(QLatin1String(name), version);
|
||||||
|
if (lib.load()) {
|
||||||
|
DEBUG_LOG(("Loaded '%1' with version %2!").arg(QLatin1String(name)).arg(version));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
lib.setFileNameAndVersion(QLatin1String(name), QString());
|
||||||
|
if (lib.load()) {
|
||||||
|
DEBUG_LOG(("Loaded '%1' without version!").arg(QLatin1String(name)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
LOG(("Could not load '%1' with version %2 :(").arg(QLatin1String(name)).arg(version));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
f_notify_init notify_init = nullptr;
|
||||||
|
f_notify_uninit notify_uninit = nullptr;
|
||||||
|
f_notify_is_initted notify_is_initted = nullptr;
|
||||||
|
//f_notify_get_app_name notify_get_app_name = nullptr;
|
||||||
|
//f_notify_set_app_name notify_set_app_name = nullptr;
|
||||||
|
f_notify_get_server_caps notify_get_server_caps = nullptr;
|
||||||
|
f_notify_get_server_info notify_get_server_info = nullptr;
|
||||||
|
|
||||||
|
f_notify_notification_new notify_notification_new = nullptr;
|
||||||
|
//f_notify_notification_update notify_notification_update = nullptr;
|
||||||
|
f_notify_notification_show notify_notification_show = nullptr;
|
||||||
|
//f_notify_notification_set_app_name notify_notification_set_app_name = nullptr;
|
||||||
|
f_notify_notification_set_timeout notify_notification_set_timeout = nullptr;
|
||||||
|
//f_notify_notification_set_category notify_notification_set_category = nullptr;
|
||||||
|
//f_notify_notification_set_urgency notify_notification_set_urgency = nullptr;
|
||||||
|
//f_notify_notification_set_icon_from_pixbuf notify_notification_set_icon_from_pixbuf = nullptr;
|
||||||
|
f_notify_notification_set_image_from_pixbuf notify_notification_set_image_from_pixbuf = nullptr;
|
||||||
|
//f_notify_notification_set_hint notify_notification_set_hint = nullptr;
|
||||||
|
//f_notify_notification_set_hint_int32 notify_notification_set_hint_int32 = nullptr;
|
||||||
|
//f_notify_notification_set_hint_uint32 notify_notification_set_hint_uint32 = nullptr;
|
||||||
|
//f_notify_notification_set_hint_double notify_notification_set_hint_double = nullptr;
|
||||||
|
f_notify_notification_set_hint_string notify_notification_set_hint_string = nullptr;
|
||||||
|
//f_notify_notification_set_hint_byte notify_notification_set_hint_byte = nullptr;
|
||||||
|
//f_notify_notification_set_hint_byte_array notify_notification_set_hint_byte_array = nullptr;
|
||||||
|
//f_notify_notification_clear_hints notify_notification_clear_hints = nullptr;
|
||||||
|
f_notify_notification_add_action notify_notification_add_action = nullptr;
|
||||||
|
f_notify_notification_clear_actions notify_notification_clear_actions = nullptr;
|
||||||
|
f_notify_notification_close notify_notification_close = nullptr;
|
||||||
|
f_notify_notification_get_closed_reason notify_notification_get_closed_reason = nullptr;
|
||||||
|
|
||||||
|
void startLibNotify() {
|
||||||
|
DEBUG_LOG(("Loading libnotify"));
|
||||||
|
|
||||||
|
QLibrary lib_notify;
|
||||||
|
if (!loadLibrary(lib_notify, "notify", 4)) {
|
||||||
|
if (!loadLibrary(lib_notify, "notify", 5)) {
|
||||||
|
if (!loadLibrary(lib_notify, "notify", 1)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
load(lib_notify, "notify_init", notify_init);
|
||||||
|
load(lib_notify, "notify_uninit", notify_uninit);
|
||||||
|
load(lib_notify, "notify_is_initted", notify_is_initted);
|
||||||
|
// load(lib_notify, "notify_get_app_name", notify_get_app_name);
|
||||||
|
// load(lib_notify, "notify_set_app_name", notify_set_app_name);
|
||||||
|
load(lib_notify, "notify_get_server_caps", notify_get_server_caps);
|
||||||
|
load(lib_notify, "notify_get_server_info", notify_get_server_info);
|
||||||
|
|
||||||
|
load(lib_notify, "notify_notification_new", notify_notification_new);
|
||||||
|
// load(lib_notify, "notify_notification_update", notify_notification_update);
|
||||||
|
load(lib_notify, "notify_notification_show", notify_notification_show);
|
||||||
|
// load(lib_notify, "notify_notification_set_app_name", notify_notification_set_app_name);
|
||||||
|
load(lib_notify, "notify_notification_set_timeout", notify_notification_set_timeout);
|
||||||
|
// load(lib_notify, "notify_notification_set_category", notify_notification_set_category);
|
||||||
|
// load(lib_notify, "notify_notification_set_urgency", notify_notification_set_urgency);
|
||||||
|
// load(lib_notify, "notify_notification_set_icon_from_pixbuf", notify_notification_set_icon_from_pixbuf);
|
||||||
|
load(lib_notify, "notify_notification_set_image_from_pixbuf", notify_notification_set_image_from_pixbuf);
|
||||||
|
// load(lib_notify, "notify_notification_set_hint", notify_notification_set_hint);
|
||||||
|
// load(lib_notify, "notify_notification_set_hint_int32", notify_notification_set_hint_int32);
|
||||||
|
// load(lib_notify, "notify_notification_set_hint_uint32", notify_notification_set_hint_uint32);
|
||||||
|
// load(lib_notify, "notify_notification_set_hint_double", notify_notification_set_hint_double);
|
||||||
|
load(lib_notify, "notify_notification_set_hint_string", notify_notification_set_hint_string);
|
||||||
|
// load(lib_notify, "notify_notification_set_hint_byte", notify_notification_set_hint_byte);
|
||||||
|
// load(lib_notify, "notify_notification_set_hint_byte_array", notify_notification_set_hint_byte_array);
|
||||||
|
// load(lib_notify, "notify_notification_clear_hints", notify_notification_clear_hints);
|
||||||
|
load(lib_notify, "notify_notification_add_action", notify_notification_add_action);
|
||||||
|
load(lib_notify, "notify_notification_clear_actions", notify_notification_clear_actions);
|
||||||
|
load(lib_notify, "notify_notification_close", notify_notification_close);
|
||||||
|
load(lib_notify, "notify_notification_get_closed_reason", notify_notification_get_closed_reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Libs
|
||||||
|
} // namespace Platform
|
131
Telegram/SourceFiles/platform/linux/linux_libnotify.h
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||||
|
|
||||||
|
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
It is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
In addition, as a special exception, the copyright holders give permission
|
||||||
|
to link the code of portions of this program with the OpenSSL library.
|
||||||
|
|
||||||
|
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||||
|
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#undef signals
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#define signals public
|
||||||
|
} // extern "C"
|
||||||
|
|
||||||
|
namespace Platform {
|
||||||
|
namespace Libs {
|
||||||
|
|
||||||
|
void startLibNotify();
|
||||||
|
|
||||||
|
constexpr gint NOTIFY_EXPIRES_DEFAULT = -1;
|
||||||
|
constexpr gint NOTIFY_EXPIRES_NEVER = 0;
|
||||||
|
|
||||||
|
struct NotifyNotification;
|
||||||
|
typedef enum {
|
||||||
|
NOTIFY_URGENCY_LOW,
|
||||||
|
NOTIFY_URGENCY_NORMAL,
|
||||||
|
NOTIFY_URGENCY_CRITICAL,
|
||||||
|
} NotifyUrgency;
|
||||||
|
|
||||||
|
using NotifyActionCallback = void (*)(NotifyNotification *notification, char *action, gpointer user_data);
|
||||||
|
|
||||||
|
using f_notify_init = gboolean (*)(const char *app_name);
|
||||||
|
extern f_notify_init notify_init;
|
||||||
|
|
||||||
|
using f_notify_uninit = void (*)(void);
|
||||||
|
extern f_notify_uninit notify_uninit;
|
||||||
|
|
||||||
|
using f_notify_is_initted = gboolean (*)(void);
|
||||||
|
extern f_notify_is_initted notify_is_initted;
|
||||||
|
|
||||||
|
//using f_notify_get_app_name = const char* (*)(void);
|
||||||
|
//extern f_notify_get_app_name notify_get_app_name;
|
||||||
|
|
||||||
|
//using f_notify_set_app_name = void (*)(const char *app_name);
|
||||||
|
//extern f_notify_set_app_name notify_set_app_name;
|
||||||
|
|
||||||
|
using f_notify_get_server_caps = GList* (*)(void);
|
||||||
|
extern f_notify_get_server_caps notify_get_server_caps;
|
||||||
|
|
||||||
|
using f_notify_get_server_info = gboolean (*)(char **ret_name, char **ret_vendor, char **ret_version, char **ret_spec_version);
|
||||||
|
extern f_notify_get_server_info notify_get_server_info;
|
||||||
|
|
||||||
|
using f_notify_notification_new = NotifyNotification* (*)(const char *summary, const char *body, const char *icon);
|
||||||
|
extern f_notify_notification_new notify_notification_new;
|
||||||
|
|
||||||
|
//using f_notify_notification_update = gboolean (*)(NotifyNotification *notification, const char *summary, const char *body, const char *icon);
|
||||||
|
//extern f_notify_notification_update notify_notification_update;
|
||||||
|
|
||||||
|
using f_notify_notification_show = gboolean (*)(NotifyNotification *notification, GError **error);
|
||||||
|
extern f_notify_notification_show notify_notification_show;
|
||||||
|
|
||||||
|
//using f_notify_notification_set_app_name = void (*)(NotifyNotification *notification, const char *app_name);
|
||||||
|
//extern f_notify_notification_set_app_name notify_notification_set_app_name;
|
||||||
|
|
||||||
|
using f_notify_notification_set_timeout = void (*)(NotifyNotification *notification, gint timeout);
|
||||||
|
extern f_notify_notification_set_timeout notify_notification_set_timeout;
|
||||||
|
|
||||||
|
//using f_notify_notification_set_category = void (*)(NotifyNotification *notification, const char *category);
|
||||||
|
//extern f_notify_notification_set_category notify_notification_set_category;
|
||||||
|
|
||||||
|
//using f_notify_notification_set_urgency = void (*)(NotifyNotification *notification, NotifyUrgency urgency);
|
||||||
|
//extern f_notify_notification_set_urgency notify_notification_set_urgency;
|
||||||
|
|
||||||
|
//using f_notify_notification_set_icon_from_pixbuf = void (*)(NotifyNotification *notification, GdkPixbuf *icon);
|
||||||
|
//extern f_notify_notification_set_icon_from_pixbuf notify_notification_set_icon_from_pixbuf;
|
||||||
|
|
||||||
|
using f_notify_notification_set_image_from_pixbuf = void (*)(NotifyNotification *notification, GdkPixbuf *pixbuf);
|
||||||
|
extern f_notify_notification_set_image_from_pixbuf notify_notification_set_image_from_pixbuf;
|
||||||
|
|
||||||
|
//using f_notify_notification_set_hint = void (*)(NotifyNotification *notification, const char *key, GVariant *value);
|
||||||
|
//extern f_notify_notification_set_hint notify_notification_set_hint;
|
||||||
|
|
||||||
|
//using f_notify_notification_set_hint_int32 = void (*)(NotifyNotification *notification, const char *key, gint value);
|
||||||
|
//extern f_notify_notification_set_hint_int32 notify_notification_set_hint_int32;
|
||||||
|
|
||||||
|
//using f_notify_notification_set_hint_uint32 = void (*)(NotifyNotification *notification, const char *key, guint value);
|
||||||
|
//extern f_notify_notification_set_hint_uint32 notify_notification_set_hint_uint32;
|
||||||
|
|
||||||
|
//using f_notify_notification_set_hint_double = void (*)(NotifyNotification *notification, const char *key, gdouble value);
|
||||||
|
//extern f_notify_notification_set_hint_double notify_notification_set_hint_double;
|
||||||
|
|
||||||
|
using f_notify_notification_set_hint_string = void (*)(NotifyNotification *notification, const char *key, const char *value);
|
||||||
|
extern f_notify_notification_set_hint_string notify_notification_set_hint_string;
|
||||||
|
|
||||||
|
//using f_notify_notification_set_hint_byte = void (*)(NotifyNotification *notification, const char *key, guchar value);
|
||||||
|
//extern f_notify_notification_set_hint_byte notify_notification_set_hint_byte;
|
||||||
|
|
||||||
|
//using f_notify_notification_set_hint_byte_array = void (*)(NotifyNotification *notification, const char *key, const guchar *value, gsize len);
|
||||||
|
//extern f_notify_notification_set_hint_byte_array notify_notification_set_hint_byte_array;
|
||||||
|
|
||||||
|
//using f_notify_notification_clear_hints = void (*)(NotifyNotification *notification);
|
||||||
|
//extern f_notify_notification_clear_hints notify_notification_clear_hints;
|
||||||
|
|
||||||
|
using f_notify_notification_add_action = void (*)(NotifyNotification *notification, const char *action, const char *label, NotifyActionCallback callback, gpointer user_data, GFreeFunc free_func);
|
||||||
|
extern f_notify_notification_add_action notify_notification_add_action;
|
||||||
|
|
||||||
|
using f_notify_notification_clear_actions = void (*)(NotifyNotification *notification);
|
||||||
|
extern f_notify_notification_clear_actions notify_notification_clear_actions;
|
||||||
|
|
||||||
|
using f_notify_notification_close = gboolean (*)(NotifyNotification *notification, GError **error);
|
||||||
|
extern f_notify_notification_close notify_notification_close;
|
||||||
|
|
||||||
|
using f_notify_notification_get_closed_reason = gint (*)(const NotifyNotification *notification);
|
||||||
|
extern f_notify_notification_get_closed_reason notify_notification_get_closed_reason;
|
||||||
|
|
||||||
|
} // namespace Libs
|
||||||
|
} // namespace Platform
|
|
@ -22,6 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#include "platform/linux/linux_libs.h"
|
#include "platform/linux/linux_libs.h"
|
||||||
|
|
||||||
#include "platform/linux/linux_gdk_helper.h"
|
#include "platform/linux/linux_gdk_helper.h"
|
||||||
|
#include "platform/linux/linux_libnotify.h"
|
||||||
|
|
||||||
namespace Platform {
|
namespace Platform {
|
||||||
namespace Libs {
|
namespace Libs {
|
||||||
|
@ -92,10 +93,16 @@ bool setupGtkBase(QLibrary &lib_gtk) {
|
||||||
if (!load(lib_gtk, "g_type_check_instance_cast", g_type_check_instance_cast)) return false;
|
if (!load(lib_gtk, "g_type_check_instance_cast", g_type_check_instance_cast)) return false;
|
||||||
if (!load(lib_gtk, "g_type_check_instance_is_a", g_type_check_instance_is_a)) return false;
|
if (!load(lib_gtk, "g_type_check_instance_is_a", g_type_check_instance_is_a)) return false;
|
||||||
if (!load(lib_gtk, "g_signal_connect_data", g_signal_connect_data)) return false;
|
if (!load(lib_gtk, "g_signal_connect_data", g_signal_connect_data)) return false;
|
||||||
|
if (!load(lib_gtk, "g_signal_handler_disconnect", g_signal_handler_disconnect)) return false;
|
||||||
|
|
||||||
if (!load(lib_gtk, "g_object_ref_sink", g_object_ref_sink)) return false;
|
if (!load(lib_gtk, "g_object_ref_sink", g_object_ref_sink)) return false;
|
||||||
if (!load(lib_gtk, "g_object_unref", g_object_unref)) return false;
|
if (!load(lib_gtk, "g_object_unref", g_object_unref)) return false;
|
||||||
if (!load(lib_gtk, "g_free", g_free)) return false;
|
if (!load(lib_gtk, "g_free", g_free)) return false;
|
||||||
|
if (!load(lib_gtk, "g_list_foreach", g_list_foreach)) return false;
|
||||||
|
if (!load(lib_gtk, "g_list_free", g_list_free)) return false;
|
||||||
|
if (!load(lib_gtk, "g_list_free_full", g_list_free_full)) return false;
|
||||||
|
|
||||||
|
if (!load(lib_gtk, "g_error_free", g_error_free)) return false;
|
||||||
if (!load(lib_gtk, "g_slist_free", g_slist_free)) return false;
|
if (!load(lib_gtk, "g_slist_free", g_slist_free)) return false;
|
||||||
|
|
||||||
DEBUG_LOG(("Library gtk functions loaded!"));
|
DEBUG_LOG(("Library gtk functions loaded!"));
|
||||||
|
@ -169,12 +176,14 @@ f_gtk_dialog_run gtk_dialog_run = nullptr;
|
||||||
f_g_type_check_instance_cast g_type_check_instance_cast = nullptr;
|
f_g_type_check_instance_cast g_type_check_instance_cast = nullptr;
|
||||||
f_g_type_check_instance_is_a g_type_check_instance_is_a = nullptr;
|
f_g_type_check_instance_is_a g_type_check_instance_is_a = nullptr;
|
||||||
f_g_signal_connect_data g_signal_connect_data = nullptr;
|
f_g_signal_connect_data g_signal_connect_data = nullptr;
|
||||||
|
f_g_signal_handler_disconnect g_signal_handler_disconnect = nullptr;
|
||||||
f_app_indicator_new app_indicator_new = nullptr;
|
f_app_indicator_new app_indicator_new = nullptr;
|
||||||
f_app_indicator_set_status app_indicator_set_status = nullptr;
|
f_app_indicator_set_status app_indicator_set_status = nullptr;
|
||||||
f_app_indicator_set_menu app_indicator_set_menu = nullptr;
|
f_app_indicator_set_menu app_indicator_set_menu = nullptr;
|
||||||
f_app_indicator_set_icon_full app_indicator_set_icon_full = nullptr;
|
f_app_indicator_set_icon_full app_indicator_set_icon_full = nullptr;
|
||||||
f_gdk_init_check gdk_init_check = nullptr;
|
f_gdk_init_check gdk_init_check = nullptr;
|
||||||
f_gdk_pixbuf_new_from_data gdk_pixbuf_new_from_data = nullptr;
|
f_gdk_pixbuf_new_from_data gdk_pixbuf_new_from_data = nullptr;
|
||||||
|
f_gdk_pixbuf_new_from_file gdk_pixbuf_new_from_file = nullptr;
|
||||||
f_gtk_status_icon_new_from_pixbuf gtk_status_icon_new_from_pixbuf = nullptr;
|
f_gtk_status_icon_new_from_pixbuf gtk_status_icon_new_from_pixbuf = nullptr;
|
||||||
f_gtk_status_icon_set_from_pixbuf gtk_status_icon_set_from_pixbuf = nullptr;
|
f_gtk_status_icon_set_from_pixbuf gtk_status_icon_set_from_pixbuf = nullptr;
|
||||||
f_gtk_status_icon_new_from_file gtk_status_icon_new_from_file = nullptr;
|
f_gtk_status_icon_new_from_file gtk_status_icon_new_from_file = nullptr;
|
||||||
|
@ -191,6 +200,10 @@ f_g_object_ref_sink g_object_ref_sink = nullptr;
|
||||||
f_g_object_unref g_object_unref = nullptr;
|
f_g_object_unref g_object_unref = nullptr;
|
||||||
f_g_idle_add g_idle_add = nullptr;
|
f_g_idle_add g_idle_add = nullptr;
|
||||||
f_g_free g_free = nullptr;
|
f_g_free g_free = nullptr;
|
||||||
|
f_g_list_foreach g_list_foreach = nullptr;
|
||||||
|
f_g_list_free g_list_free = nullptr;
|
||||||
|
f_g_list_free_full g_list_free_full = nullptr;
|
||||||
|
f_g_error_free g_error_free = nullptr;
|
||||||
f_g_slist_free g_slist_free = nullptr;
|
f_g_slist_free g_slist_free = nullptr;
|
||||||
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
|
#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
|
||||||
f_unity_launcher_entry_set_count unity_launcher_entry_set_count = nullptr;
|
f_unity_launcher_entry_set_count unity_launcher_entry_set_count = nullptr;
|
||||||
|
@ -233,6 +246,7 @@ void start() {
|
||||||
if (gtkLoaded) {
|
if (gtkLoaded) {
|
||||||
load(lib_gtk, "gdk_init_check", gdk_init_check);
|
load(lib_gtk, "gdk_init_check", gdk_init_check);
|
||||||
load(lib_gtk, "gdk_pixbuf_new_from_data", gdk_pixbuf_new_from_data);
|
load(lib_gtk, "gdk_pixbuf_new_from_data", gdk_pixbuf_new_from_data);
|
||||||
|
load(lib_gtk, "gdk_pixbuf_new_from_file", gdk_pixbuf_new_from_file);
|
||||||
load(lib_gtk, "gtk_status_icon_new_from_pixbuf", gtk_status_icon_new_from_pixbuf);
|
load(lib_gtk, "gtk_status_icon_new_from_pixbuf", gtk_status_icon_new_from_pixbuf);
|
||||||
load(lib_gtk, "gtk_status_icon_set_from_pixbuf", gtk_status_icon_set_from_pixbuf);
|
load(lib_gtk, "gtk_status_icon_set_from_pixbuf", gtk_status_icon_set_from_pixbuf);
|
||||||
load(lib_gtk, "gtk_status_icon_new_from_file", gtk_status_icon_new_from_file);
|
load(lib_gtk, "gtk_status_icon_new_from_file", gtk_status_icon_new_from_file);
|
||||||
|
@ -266,6 +280,10 @@ void start() {
|
||||||
load(lib_unity, "unity_launcher_entry_set_count_visible", unity_launcher_entry_set_count_visible);
|
load(lib_unity, "unity_launcher_entry_set_count_visible", unity_launcher_entry_set_count_visible);
|
||||||
}
|
}
|
||||||
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
|
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
|
||||||
|
|
||||||
|
if (gtkLoaded) {
|
||||||
|
startLibNotify();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Libs
|
} // namespace Libs
|
||||||
|
|
|
@ -247,14 +247,17 @@ extern f_gtk_dialog_run gtk_dialog_run;
|
||||||
typedef gulong (*f_g_signal_connect_data)(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags);
|
typedef gulong (*f_g_signal_connect_data)(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags);
|
||||||
extern f_g_signal_connect_data g_signal_connect_data;
|
extern f_g_signal_connect_data g_signal_connect_data;
|
||||||
|
|
||||||
inline gulong g_signal_connect_helper(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data) {
|
inline gulong g_signal_connect_helper(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data = nullptr) {
|
||||||
return g_signal_connect_data(instance, detailed_signal, c_handler, data, NULL, (GConnectFlags)0);
|
return g_signal_connect_data(instance, detailed_signal, c_handler, data, destroy_data, (GConnectFlags)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline gulong g_signal_connect_swapped_helper(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data) {
|
inline gulong g_signal_connect_swapped_helper(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data = nullptr) {
|
||||||
return g_signal_connect_data(instance, detailed_signal, c_handler, data, NULL, G_CONNECT_SWAPPED);
|
return g_signal_connect_data(instance, detailed_signal, c_handler, data, destroy_data, G_CONNECT_SWAPPED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef void (*f_g_signal_handler_disconnect)(gpointer instance, gulong handler_id);
|
||||||
|
extern f_g_signal_handler_disconnect g_signal_handler_disconnect;
|
||||||
|
|
||||||
typedef AppIndicator* (*f_app_indicator_new)(const gchar *id, const gchar *icon_name, AppIndicatorCategory category);
|
typedef AppIndicator* (*f_app_indicator_new)(const gchar *id, const gchar *icon_name, AppIndicatorCategory category);
|
||||||
extern f_app_indicator_new app_indicator_new;
|
extern f_app_indicator_new app_indicator_new;
|
||||||
|
|
||||||
|
@ -273,6 +276,9 @@ extern f_gdk_init_check gdk_init_check;
|
||||||
typedef GdkPixbuf* (*f_gdk_pixbuf_new_from_data)(const guchar *data, GdkColorspace colorspace, gboolean has_alpha, int bits_per_sample, int width, int height, int rowstride, GdkPixbufDestroyNotify destroy_fn, gpointer destroy_fn_data);
|
typedef GdkPixbuf* (*f_gdk_pixbuf_new_from_data)(const guchar *data, GdkColorspace colorspace, gboolean has_alpha, int bits_per_sample, int width, int height, int rowstride, GdkPixbufDestroyNotify destroy_fn, gpointer destroy_fn_data);
|
||||||
extern f_gdk_pixbuf_new_from_data gdk_pixbuf_new_from_data;
|
extern f_gdk_pixbuf_new_from_data gdk_pixbuf_new_from_data;
|
||||||
|
|
||||||
|
typedef GdkPixbuf* (*f_gdk_pixbuf_new_from_file)(const gchar *filename, GError **error);
|
||||||
|
extern f_gdk_pixbuf_new_from_file gdk_pixbuf_new_from_file;
|
||||||
|
|
||||||
typedef GtkStatusIcon* (*f_gtk_status_icon_new_from_pixbuf)(GdkPixbuf *pixbuf);
|
typedef GtkStatusIcon* (*f_gtk_status_icon_new_from_pixbuf)(GdkPixbuf *pixbuf);
|
||||||
extern f_gtk_status_icon_new_from_pixbuf gtk_status_icon_new_from_pixbuf;
|
extern f_gtk_status_icon_new_from_pixbuf gtk_status_icon_new_from_pixbuf;
|
||||||
|
|
||||||
|
@ -321,6 +327,18 @@ extern f_g_idle_add g_idle_add;
|
||||||
typedef void (*f_g_free)(gpointer mem);
|
typedef void (*f_g_free)(gpointer mem);
|
||||||
extern f_g_free g_free;
|
extern f_g_free g_free;
|
||||||
|
|
||||||
|
typedef void (*f_g_list_foreach)(GList *list, GFunc func, gpointer user_data);
|
||||||
|
extern f_g_list_foreach g_list_foreach;
|
||||||
|
|
||||||
|
typedef void (*f_g_list_free)(GList *list);
|
||||||
|
extern f_g_list_free g_list_free;
|
||||||
|
|
||||||
|
typedef void (*f_g_list_free_full)(GList *list, GDestroyNotify free_func);
|
||||||
|
extern f_g_list_free_full g_list_free_full;
|
||||||
|
|
||||||
|
typedef void (*f_g_error_free)(GError *error);
|
||||||
|
extern f_g_error_free g_error_free;
|
||||||
|
|
||||||
typedef void (*f_g_slist_free)(GSList *list);
|
typedef void (*f_g_slist_free)(GSList *list);
|
||||||
extern f_g_slist_free g_slist_free;
|
extern f_g_slist_free g_slist_free;
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
#include "platform/linux/main_window_linux.h"
|
#include "platform/linux/main_window_linux.h"
|
||||||
|
|
||||||
#include "platform/linux/linux_libs.h"
|
#include "platform/linux/linux_libs.h"
|
||||||
|
#include "platform/platform_notifications_manager.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "application.h"
|
#include "application.h"
|
||||||
#include "lang.h"
|
#include "lang.h"
|
||||||
|
@ -63,22 +64,11 @@ gboolean _trayIconResized(GtkStatusIcon *status_icon, gint size, gpointer popup_
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
|
|
||||||
|
|
||||||
#define QT_RED 3
|
|
||||||
#define QT_GREEN 2
|
|
||||||
#define QT_BLUE 1
|
|
||||||
#define QT_ALPHA 0
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define QT_RED 0
|
#define QT_RED 0
|
||||||
#define QT_GREEN 1
|
#define QT_GREEN 1
|
||||||
#define QT_BLUE 2
|
#define QT_BLUE 2
|
||||||
#define QT_ALPHA 3
|
#define QT_ALPHA 3
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define GTK_RED 2
|
#define GTK_RED 2
|
||||||
#define GTK_GREEN 1
|
#define GTK_GREEN 1
|
||||||
#define GTK_BLUE 0
|
#define GTK_BLUE 0
|
||||||
|
@ -262,13 +252,19 @@ void MainWindow::psSetupTrayIcon() {
|
||||||
|
|
||||||
trayIcon->setToolTip(str_const_toString(AppName));
|
trayIcon->setToolTip(str_const_toString(AppName));
|
||||||
connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(toggleTray(QSystemTrayIcon::ActivationReason)), Qt::UniqueConnection);
|
connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(toggleTray(QSystemTrayIcon::ActivationReason)), Qt::UniqueConnection);
|
||||||
|
|
||||||
|
// This is very important for native notifications via libnotify!
|
||||||
|
// Some notification servers compose several notifications with a "Reply"
|
||||||
|
// action into one and after that a click on "Reply" button does not call
|
||||||
|
// the specified callback from any of the sent notification - libnotify
|
||||||
|
// just ignores ibus messages, but Qt tray icon at least emits this signal.
|
||||||
connect(trayIcon, SIGNAL(messageClicked()), this, SLOT(showFromTray()));
|
connect(trayIcon, SIGNAL(messageClicked()), this, SLOT(showFromTray()));
|
||||||
|
|
||||||
App::wnd()->updateTrayMenu();
|
App::wnd()->updateTrayMenu();
|
||||||
}
|
}
|
||||||
psUpdateCounter();
|
psUpdateCounter();
|
||||||
|
|
||||||
trayIcon->show();
|
trayIcon->show();
|
||||||
psUpdateDelegate();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,6 +363,10 @@ void MainWindow::psUpdateCounter() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MainWindow::psHasNativeNotifications() {
|
||||||
|
return Notifications::supported();
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::LibsLoaded() {
|
void MainWindow::LibsLoaded() {
|
||||||
QString cdesktop = QString(getenv("XDG_CURRENT_DESKTOP")).toLower();
|
QString cdesktop = QString(getenv("XDG_CURRENT_DESKTOP")).toLower();
|
||||||
noQtTrayIcon = (cdesktop == qstr("pantheon")) || (cdesktop == qstr("gnome"));
|
noQtTrayIcon = (cdesktop == qstr("pantheon")) || (cdesktop == qstr("gnome"));
|
||||||
|
@ -430,9 +430,6 @@ void MainWindow::LibsLoaded() {
|
||||||
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
|
#endif // TDESKTOP_DISABLE_UNITY_INTEGRATION
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::psUpdateDelegate() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::psInitSize() {
|
void MainWindow::psInitSize() {
|
||||||
setMinimumWidth(st::wndMinWidth);
|
setMinimumWidth(st::wndMinWidth);
|
||||||
setMinimumHeight(st::wndMinHeight);
|
setMinimumHeight(st::wndMinHeight);
|
||||||
|
@ -663,18 +660,6 @@ void MainWindow::psUpdateMargins() {
|
||||||
void MainWindow::psFlash() {
|
void MainWindow::psFlash() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::psActivateNotify(NotifyWindow *w) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::psClearNotifies(PeerId peerId) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::psNotifyShown(NotifyWindow *w) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::psPlatformNotify(HistoryItem *item, int32 fwdCount) {
|
|
||||||
}
|
|
||||||
|
|
||||||
MainWindow::~MainWindow() {
|
MainWindow::~MainWindow() {
|
||||||
if (_trayIcon) {
|
if (_trayIcon) {
|
||||||
Libs::g_object_unref(_trayIcon);
|
Libs::g_object_unref(_trayIcon);
|
||||||
|
|
|
@ -22,8 +22,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
#include "window/main_window.h"
|
#include "window/main_window.h"
|
||||||
|
|
||||||
class NotifyWindow;
|
|
||||||
|
|
||||||
namespace Platform {
|
namespace Platform {
|
||||||
|
|
||||||
class MainWindow : public Window::MainWindow {
|
class MainWindow : public Window::MainWindow {
|
||||||
|
@ -58,16 +56,9 @@ public:
|
||||||
return posInited;
|
return posInited;
|
||||||
}
|
}
|
||||||
|
|
||||||
void psActivateNotify(NotifyWindow *w);
|
|
||||||
void psClearNotifies(PeerId peerId = 0);
|
|
||||||
void psNotifyShown(NotifyWindow *w);
|
|
||||||
void psPlatformNotify(HistoryItem *item, int32 fwdCount);
|
|
||||||
|
|
||||||
void psUpdateCounter();
|
void psUpdateCounter();
|
||||||
|
|
||||||
bool psHasNativeNotifications() {
|
bool psHasNativeNotifications();
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual QImage iconWithCounter(int size, int count, style::color bg, bool smallIcon) = 0;
|
virtual QImage iconWithCounter(int size, int count, style::color bg, bool smallIcon) = 0;
|
||||||
|
|
||||||
|
@ -76,8 +67,6 @@ public:
|
||||||
~MainWindow();
|
~MainWindow();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void psUpdateDelegate();
|
|
||||||
void psSavePosition(Qt::WindowState state = Qt::WindowActive);
|
void psSavePosition(Qt::WindowState state = Qt::WindowActive);
|
||||||
void psShowTrayMenu();
|
void psShowTrayMenu();
|
||||||
|
|
||||||
|
|