2014-11-05 20:43:32 +03:00
/*
2014-05-30 12:53:19 +04:00
This file is part of Telegram Desktop ,
2014-12-01 13:47:38 +03:00
the official desktop version of Telegram messaging app , see https : //telegram.org
2014-05-30 12:53:19 +04:00
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 .
2015-10-03 16:16:42 +03:00
In addition , as a special exception , the copyright holders give permission
to link the code of portions of this program with the OpenSSL library .
2014-05-30 12:53:19 +04:00
Full license : https : //github.com/telegramdesktop/tdesktop/blob/master/LICENSE
2017-01-11 22:31:31 +04:00
Copyright ( c ) 2014 - 2017 John Preston , https : //desktop.telegram.org
2014-05-30 12:53:19 +04:00
*/
# include "stdafx.h"
2016-04-10 22:18:26 +04:00
# include "mainwidget.h"
2016-06-07 22:59:39 +03:00
# include "styles/style_dialogs.h"
2016-11-15 14:56:49 +03:00
# include "styles/style_history.h"
2016-04-13 00:31:28 +03:00
# include "ui/buttons/peer_avatar_button.h"
2016-11-11 16:46:04 +03:00
# include "ui/widgets/buttons.h"
2016-10-12 22:34:25 +03:00
# include "ui/widgets/shadow.h"
2016-05-19 15:03:51 +03:00
# include "window/section_memento.h"
# include "window/section_widget.h"
2016-04-13 00:31:28 +03:00
# include "window/top_bar_widget.h"
2016-06-09 14:51:24 +03:00
# include "data/data_drafts.h"
2016-10-26 19:43:13 +03:00
# include "ui/widgets/dropdown_menu.h"
2016-05-25 15:09:05 +03:00
# include "observer_peer.h"
2016-04-13 00:31:28 +03:00
# include "apiwrap.h"
# include "dialogswidget.h"
# include "historywidget.h"
# include "overviewwidget.h"
2014-05-30 12:53:19 +04:00
# include "lang.h"
# include "boxes/addcontactbox.h"
2015-12-24 22:26:28 +03:00
# include "fileuploader.h"
2014-05-30 12:53:19 +04:00
# include "application.h"
2016-04-13 00:31:28 +03:00
# include "mainwindow.h"
2016-04-10 22:18:26 +04:00
# include "inline_bots/inline_bot_layout_item.h"
2014-05-30 12:53:19 +04:00
# include "boxes/confirmbox.h"
2015-05-19 18:46:45 +03:00
# include "boxes/stickersetbox.h"
2015-06-17 22:43:03 +03:00
# include "boxes/contactsbox.h"
2015-11-26 20:34:52 +03:00
# include "boxes/downloadpathbox.h"
2016-07-28 20:01:08 +03:00
# include "boxes/confirmphonebox.h"
2016-09-07 12:04:57 +03:00
# include "boxes/sharebox.h"
2015-01-02 17:55:24 +03:00
# include "localstorage.h"
2016-03-17 12:23:38 +03:00
# include "shortcuts.h"
2016-07-05 20:44:02 +03:00
# include "media/media_audio.h"
2016-10-12 22:34:25 +03:00
# include "media/player/media_player_panel.h"
2016-09-17 22:28:33 +03:00
# include "media/player/media_player_widget.h"
2016-10-12 22:34:25 +03:00
# include "media/player/media_player_volume_controller.h"
2016-09-23 19:04:26 +03:00
# include "media/player/media_player_instance.h"
2016-07-28 20:01:08 +03:00
# include "core/qthelp_regex.h"
# include "core/qthelp_url.h"
2017-02-03 23:07:26 +03:00
# include "window/themes/window_theme.h"
2016-10-12 22:34:25 +03:00
# include "window/player_wrap_widget.h"
2016-11-15 14:56:49 +03:00
# include "styles/style_boxes.h"
2016-04-05 11:45:53 +04:00
2016-05-19 15:03:51 +03:00
StackItemSection : : StackItemSection ( std_ : : unique_ptr < Window : : SectionMemento > & & memento ) : StackItem ( nullptr )
, _memento ( std_ : : move ( memento ) ) {
}
StackItemSection : : ~ StackItemSection ( ) {
}
2016-11-04 11:23:50 +03:00
MainWidget : : MainWidget ( QWidget * parent ) : TWidget ( parent )
2016-06-07 22:59:39 +03:00
, _dialogsWidth ( st : : dialogsWidthMin )
2016-12-21 18:05:58 +03:00
, _sideShadow ( this , st : : shadowFg )
2017-01-14 21:50:16 +03:00
, _sideResizeArea ( this )
2016-04-13 00:31:28 +03:00
, _dialogs ( this )
, _history ( this )
2015-10-17 16:52:26 +02:00
, _topBar ( this )
2016-10-14 20:10:15 +03:00
, _playerPlaylist ( this , Media : : Player : : Panel : : Layout : : OnlyPlaylist )
, _playerPanel ( this , Media : : Player : : Panel : : Layout : : Full )
2016-11-07 19:08:24 +03:00
, _mediaType ( this , st : : defaultDropdownMenu )
2015-10-17 16:52:26 +02:00
, _api ( new ApiWrap ( this ) ) {
2015-09-21 23:57:42 +03:00
MTP : : setGlobalDoneHandler ( rpcDone ( & MainWidget : : updateReceived ) ) ;
2015-09-13 11:41:27 +03:00
_ptsWaiter . setRequesting ( true ) ;
2015-02-13 21:09:01 +03:00
updateScrollColors ( ) ;
2015-02-03 18:02:46 +03:00
2016-04-13 00:31:28 +03:00
connect ( _dialogs , SIGNAL ( cancelled ( ) ) , this , SLOT ( dialogsCancelled ( ) ) ) ;
2016-11-05 11:36:24 +03:00
connect ( this , SIGNAL ( dialogsUpdated ( ) ) , _dialogs , SLOT ( onListScroll ( ) ) ) ;
2016-04-13 00:31:28 +03:00
connect ( _history , SIGNAL ( cancelled ( ) ) , _dialogs , SLOT ( activate ( ) ) ) ;
2015-01-26 16:04:41 +03:00
connect ( this , SIGNAL ( peerPhotoChanged ( PeerData * ) ) , this , SIGNAL ( dialogsUpdated ( ) ) ) ;
2015-04-16 17:59:42 +03:00
connect ( & noUpdatesTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( mtpPing ( ) ) ) ;
2015-01-26 16:04:41 +03:00
connect ( & _onlineTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( updateOnline ( ) ) ) ;
connect ( & _onlineUpdater , SIGNAL ( timeout ( ) ) , this , SLOT ( updateOnlineDisplay ( ) ) ) ;
connect ( & _idleFinishTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( checkIdleFinish ( ) ) ) ;
2014-11-05 20:43:32 +03:00
connect ( & _bySeqTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( getDifference ( ) ) ) ;
2015-09-13 11:41:27 +03:00
connect ( & _byPtsTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( onGetDifferenceTimeByPts ( ) ) ) ;
2016-03-11 18:01:32 +03:00
connect ( & _byMinChannelTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( getDifference ( ) ) ) ;
2015-09-13 11:41:27 +03:00
connect ( & _failDifferenceTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( onGetDifferenceTimeAfterFail ( ) ) ) ;
2016-04-13 00:31:28 +03:00
connect ( _api . get ( ) , SIGNAL ( fullPeerUpdated ( PeerData * ) ) , this , SLOT ( onFullPeerUpdated ( PeerData * ) ) ) ;
connect ( this , SIGNAL ( peerUpdated ( PeerData * ) ) , _history , SLOT ( peerUpdated ( PeerData * ) ) ) ;
connect ( _topBar , SIGNAL ( clicked ( ) ) , this , SLOT ( onTopBarClick ( ) ) ) ;
connect ( _history , SIGNAL ( historyShown ( History * , MsgId ) ) , this , SLOT ( onHistoryShown ( History * , MsgId ) ) ) ;
2014-05-30 12:53:19 +04:00
connect ( & updateNotifySettingTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( onUpdateNotifySettings ( ) ) ) ;
2017-01-19 11:24:43 +03:00
subscribe ( Media : : Player : : Updated ( ) , [ this ] ( const AudioMsgId & audioId ) {
if ( audioId . type ( ) ! = AudioMsgId : : Type : : Video ) {
handleAudioUpdate ( audioId ) ;
}
} ) ;
2016-09-23 19:04:26 +03:00
2017-01-14 21:50:16 +03:00
subscribe ( Global : : RefDialogsListFocused ( ) , [ this ] ( bool ) {
updateDialogsWidthAnimated ( ) ;
} ) ;
subscribe ( Global : : RefDialogsListDisplayForced ( ) , [ this ] ( bool ) {
updateDialogsWidthAnimated ( ) ;
} ) ;
Sandbox : : installEventFilter ( this ) ;
2015-04-30 16:53:36 +03:00
connect ( & _updateMutedTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( onUpdateMuted ( ) ) ) ;
2015-09-21 23:57:42 +03:00
connect ( & _viewsIncrementTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( onViewsIncrement ( ) ) ) ;
2014-05-30 12:53:19 +04:00
2016-09-27 16:37:18 +03:00
_webPageOrGameUpdater . setSingleShot ( true ) ;
connect ( & _webPageOrGameUpdater , SIGNAL ( timeout ( ) ) , this , SLOT ( webPagesOrGamesUpdate ( ) ) ) ;
2015-04-08 02:03:32 +03:00
2017-01-14 21:50:16 +03:00
_sideResizeArea - > setCursor ( style : : cur_sizehor ) ;
2016-10-28 15:44:28 +03:00
using Update = Window : : Theme : : BackgroundUpdate ;
subscribe ( Window : : Theme : : Background ( ) , [ this ] ( const Update & update ) {
2016-08-26 22:49:18 -06:00
if ( update . type = = Update : : Type : : New | | update . type = = Update : : Type : : Changed ) {
clearCachedBackground ( ) ;
}
} ) ;
2015-02-03 18:02:46 +03:00
connect ( & _cacheBackgroundTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( onCacheBackground ( ) ) ) ;
2017-01-19 11:24:43 +03:00
_playerPanel - > setPinCallback ( [ this ] { switchToFixedPlayer ( ) ; } ) ;
_playerPanel - > setCloseCallback ( [ this ] { closeBothPlayers ( ) ; } ) ;
subscribe ( Media : : Player : : instance ( ) - > titleButtonOver ( ) , [ this ] ( bool over ) {
if ( over ) {
_playerPanel - > showFromOther ( ) ;
} else {
_playerPanel - > hideFromOther ( ) ;
}
} ) ;
subscribe ( Media : : Player : : instance ( ) - > playerWidgetOver ( ) , [ this ] ( bool over ) {
if ( over ) {
if ( _playerPlaylist - > isHidden ( ) ) {
auto position = mapFromGlobal ( QCursor : : pos ( ) ) . x ( ) ;
auto bestPosition = _playerPlaylist - > bestPositionFor ( position ) ;
if ( rtl ( ) ) bestPosition = position + 2 * ( position - bestPosition ) - _playerPlaylist - > width ( ) ;
updateMediaPlaylistPosition ( bestPosition ) ;
2016-10-14 20:10:15 +03:00
}
2017-01-19 11:24:43 +03:00
_playerPlaylist - > showFromOther ( ) ;
} else {
_playerPlaylist - > hideFromOther ( ) ;
}
} ) ;
2016-10-14 20:10:15 +03:00
2017-01-14 21:50:16 +03:00
subscribe ( Adaptive : : Changed ( ) , [ this ] ( ) { handleAdaptiveLayoutUpdate ( ) ; } ) ;
2016-08-26 22:49:18 -06:00
2017-01-01 20:45:20 +04:00
auto observeEvents = Notify : : PeerUpdate : : Flag : : SharedMediaChanged ;
subscribe ( Notify : : PeerUpdated ( ) , Notify : : PeerUpdatedHandler ( observeEvents , [ this ] ( const Notify : : PeerUpdate & update ) {
mediaOverviewUpdated ( update ) ;
} ) ) ;
2016-04-13 00:31:28 +03:00
_dialogs - > show ( ) ;
2016-02-08 17:54:55 +03:00
if ( Adaptive : : OneColumn ( ) ) {
2016-04-13 00:31:28 +03:00
_history - > hide ( ) ;
2016-02-08 17:54:55 +03:00
} else {
2016-04-13 00:31:28 +03:00
_history - > show ( ) ;
2014-12-12 19:27:03 +03:00
}
2016-04-13 00:31:28 +03:00
_topBar - > hide ( ) ;
2014-05-30 12:53:19 +04:00
2015-07-17 22:17:37 +03:00
orderWidgets ( ) ;
2014-05-30 12:53:19 +04:00
MTP : : setGlobalFailHandler ( rpcFail ( & MainWidget : : updateFail ) ) ;
2016-04-13 00:31:28 +03:00
_mediaType - > hide ( ) ;
2016-11-09 16:40:51 +03:00
_mediaType - > setOrigin ( Ui : : PanelAnimation : : Origin : : TopRight ) ;
2016-04-13 00:31:28 +03:00
_topBar - > mediaTypeButton ( ) - > installEventFilter ( _mediaType ) ;
2017-01-14 21:50:16 +03:00
_sideResizeArea - > installEventFilter ( this ) ;
2015-03-02 15:34:16 +03:00
2015-03-19 12:18:19 +03:00
_api - > init ( ) ;
2016-04-14 22:24:42 +03:00
# ifndef TDESKTOP_DISABLE_AUTOUPDATE
Sandbox : : startUpdateCheck ( ) ;
2016-10-18 10:56:38 +03:00
# endif // !TDESKTOP_DISABLE_AUTOUPDATE
2014-05-30 12:53:19 +04:00
}
2015-09-07 10:52:37 +03:00
bool MainWidget : : onForward ( const PeerId & peer , ForwardWhatMessages what ) {
PeerData * p = App : : peer ( peer ) ;
2017-01-16 16:27:11 +03:00
if ( ! peer | | ( p - > isChannel ( ) & & ! p - > asChannel ( ) - > canPublish ( ) & & p - > asChannel ( ) - > isBroadcast ( ) ) | | ( p - > isChat ( ) & & ! p - > asChat ( ) - > canWrite ( ) ) | | ( p - > isUser ( ) & & p - > asUser ( ) - > isInaccessible ( ) ) ) {
2016-12-13 20:07:56 +03:00
Ui : : show ( Box < InformBox > ( lang ( lng_forward_cant ) ) ) ;
2015-09-07 10:52:37 +03:00
return false ;
}
2016-04-13 00:31:28 +03:00
_history - > cancelReply ( ) ;
2015-03-24 13:00:27 +03:00
_toForward . clear ( ) ;
2015-06-27 16:02:00 +03:00
if ( what = = ForwardSelectedMessages ) {
2016-04-13 00:31:28 +03:00
if ( _overview ) {
_overview - > fillSelectedItems ( _toForward , false ) ;
2014-08-20 09:32:50 +04:00
} else {
2016-04-13 00:31:28 +03:00
_history - > fillSelectedItems ( _toForward , false ) ;
2014-08-20 09:32:50 +04:00
}
2015-06-27 16:02:00 +03:00
} else {
HistoryItem * item = 0 ;
if ( what = = ForwardContextMessage ) {
item = App : : contextItem ( ) ;
} else if ( what = = ForwardPressedMessage ) {
item = App : : pressedItem ( ) ;
} else if ( what = = ForwardPressedLinkMessage ) {
item = App : : pressedLinkItem ( ) ;
}
2015-11-13 18:14:33 +03:00
if ( item & & item - > toHistoryMessage ( ) & & item - > id > 0 ) {
2015-06-27 16:02:00 +03:00
_toForward . insert ( item - > id , item ) ;
}
2015-03-24 13:00:27 +03:00
}
2016-10-14 20:10:15 +03:00
updateForwardingItemRemovedSubscription ( ) ;
2015-03-24 13:00:27 +03:00
updateForwardingTexts ( ) ;
2015-12-13 14:36:08 +03:00
Ui : : showPeerHistory ( peer , ShowAtUnreadMsgId ) ;
2016-04-13 00:31:28 +03:00
_history - > onClearSelected ( ) ;
_history - > updateForwarding ( ) ;
2015-09-07 10:52:37 +03:00
return true ;
2015-03-24 13:00:27 +03:00
}
2015-10-18 14:49:34 +02:00
bool MainWidget : : onShareUrl ( const PeerId & peer , const QString & url , const QString & text ) {
PeerData * p = App : : peer ( peer ) ;
2017-01-16 16:27:11 +03:00
if ( ! peer | | ( p - > isChannel ( ) & & ! p - > asChannel ( ) - > canPublish ( ) & & p - > asChannel ( ) - > isBroadcast ( ) ) | | ( p - > isChat ( ) & & ! p - > asChat ( ) - > canWrite ( ) ) | | ( p - > isUser ( ) & & p - > asUser ( ) - > isInaccessible ( ) ) ) {
2016-12-13 20:07:56 +03:00
Ui : : show ( Box < InformBox > ( lang ( lng_share_cant ) ) ) ;
2015-10-18 14:49:34 +02:00
return false ;
}
History * h = App : : history ( peer ) ;
2016-05-05 19:04:17 +03:00
TextWithTags textWithTags = { url + ' \n ' + text , TextWithTags : : Tags ( ) } ;
MessageCursor cursor = { url . size ( ) + 1 , url . size ( ) + 1 + text . size ( ) , QFIXED_MAX } ;
2016-06-09 17:31:10 +03:00
h - > setLocalDraft ( std_ : : make_unique < Data : : Draft > ( textWithTags , 0 , cursor , false ) ) ;
2016-04-08 18:16:52 +04:00
h - > clearEditDraft ( ) ;
2016-04-13 00:31:28 +03:00
bool opened = _history - > peer ( ) & & ( _history - > peer ( ) - > id = = peer ) ;
2016-04-08 18:16:52 +04:00
if ( opened ) {
2016-04-13 00:31:28 +03:00
_history - > applyDraft ( ) ;
2016-04-08 18:16:52 +04:00
} else {
Ui : : showPeerHistory ( peer , ShowAtUnreadMsgId ) ;
}
return true ;
}
bool MainWidget : : onInlineSwitchChosen ( const PeerId & peer , const QString & botAndQuery ) {
PeerData * p = App : : peer ( peer ) ;
2017-01-16 16:27:11 +03:00
if ( ! peer | | ( p - > isChannel ( ) & & ! p - > asChannel ( ) - > canPublish ( ) & & p - > asChannel ( ) - > isBroadcast ( ) ) | | ( p - > isChat ( ) & & ! p - > asChat ( ) - > canWrite ( ) ) | | ( p - > isUser ( ) & & p - > asUser ( ) - > isInaccessible ( ) ) ) {
2016-12-13 20:07:56 +03:00
Ui : : show ( Box < InformBox > ( lang ( lng_inline_switch_cant ) ) ) ;
2016-04-08 18:16:52 +04:00
return false ;
}
History * h = App : : history ( peer ) ;
2016-05-05 19:04:17 +03:00
TextWithTags textWithTags = { botAndQuery , TextWithTags : : Tags ( ) } ;
MessageCursor cursor = { botAndQuery . size ( ) , botAndQuery . size ( ) , QFIXED_MAX } ;
2016-06-09 17:31:10 +03:00
h - > setLocalDraft ( std_ : : make_unique < Data : : Draft > ( textWithTags , 0 , cursor , false ) ) ;
2016-04-08 18:16:52 +04:00
h - > clearEditDraft ( ) ;
2016-04-13 00:31:28 +03:00
bool opened = _history - > peer ( ) & & ( _history - > peer ( ) - > id = = peer ) ;
2015-10-18 14:49:34 +02:00
if ( opened ) {
2016-04-13 00:31:28 +03:00
_history - > applyDraft ( ) ;
2015-10-18 14:49:34 +02:00
} else {
2015-12-13 14:36:08 +03:00
Ui : : showPeerHistory ( peer , ShowAtUnreadMsgId ) ;
2015-10-18 14:49:34 +02:00
}
return true ;
}
2015-03-24 13:00:27 +03:00
bool MainWidget : : hasForwardingItems ( ) {
return ! _toForward . isEmpty ( ) ;
}
void MainWidget : : fillForwardingInfo ( Text * & from , Text * & text , bool & serviceColor , ImagePtr & preview ) {
if ( _toForward . isEmpty ( ) ) return ;
int32 version = 0 ;
for ( SelectedItemSet : : const_iterator i = _toForward . cbegin ( ) , e = _toForward . cend ( ) ; i ! = e ; + + i ) {
2016-02-18 22:12:50 +03:00
version + = i . value ( ) - > authorOriginal ( ) - > nameVersion ;
2015-03-24 13:00:27 +03:00
}
if ( version ! = _toForwardNameVersion ) {
updateForwardingTexts ( ) ;
}
from = & _toForwardFrom ;
text = & _toForwardText ;
serviceColor = ( _toForward . size ( ) > 1 ) | | _toForward . cbegin ( ) . value ( ) - > getMedia ( ) | | _toForward . cbegin ( ) . value ( ) - > serviceMsg ( ) ;
if ( _toForward . size ( ) < 2 & & _toForward . cbegin ( ) . value ( ) - > getMedia ( ) & & _toForward . cbegin ( ) . value ( ) - > getMedia ( ) - > hasReplyPreview ( ) ) {
preview = _toForward . cbegin ( ) . value ( ) - > getMedia ( ) - > replyPreview ( ) ;
}
}
void MainWidget : : updateForwardingTexts ( ) {
int32 version = 0 ;
QString from , text ;
if ( ! _toForward . isEmpty ( ) ) {
2015-09-04 16:01:31 +03:00
QMap < PeerData * , bool > fromUsersMap ;
QVector < PeerData * > fromUsers ;
2015-03-24 13:00:27 +03:00
fromUsers . reserve ( _toForward . size ( ) ) ;
for ( SelectedItemSet : : const_iterator i = _toForward . cbegin ( ) , e = _toForward . cend ( ) ; i ! = e ; + + i ) {
2016-02-18 22:12:50 +03:00
PeerData * from = i . value ( ) - > authorOriginal ( ) ;
2015-10-29 11:27:34 -04:00
if ( ! fromUsersMap . contains ( from ) ) {
fromUsersMap . insert ( from , true ) ;
fromUsers . push_back ( from ) ;
2015-03-24 13:00:27 +03:00
}
2016-02-17 19:37:21 +03:00
version + = from - > nameVersion ;
2015-03-24 13:00:27 +03:00
}
if ( fromUsers . size ( ) > 2 ) {
2015-09-04 16:01:31 +03:00
from = lng_forwarding_from ( lt_user , fromUsers . at ( 0 ) - > shortName ( ) , lt_count , fromUsers . size ( ) - 1 ) ;
2015-03-24 13:00:27 +03:00
} else if ( fromUsers . size ( ) < 2 ) {
from = fromUsers . at ( 0 ) - > name ;
} else {
2015-09-04 16:01:31 +03:00
from = lng_forwarding_from_two ( lt_user , fromUsers . at ( 0 ) - > shortName ( ) , lt_second_user , fromUsers . at ( 1 ) - > shortName ( ) ) ;
2015-03-24 13:00:27 +03:00
}
if ( _toForward . size ( ) < 2 ) {
text = _toForward . cbegin ( ) . value ( ) - > inReplyText ( ) ;
} else {
text = lng_forward_messages ( lt_count , _toForward . size ( ) ) ;
}
}
2016-12-23 16:21:01 +03:00
_toForwardFrom . setText ( st : : msgNameStyle , from , _textNameOptions ) ;
_toForwardText . setText ( st : : messageTextStyle , textClean ( text ) , _textDlgOptions ) ;
2015-03-24 13:00:27 +03:00
_toForwardNameVersion = version ;
}
2016-10-14 20:10:15 +03:00
void MainWidget : : updateForwardingItemRemovedSubscription ( ) {
if ( _toForward . isEmpty ( ) ) {
unsubscribe ( _forwardingItemRemovedSubscription ) ;
_forwardingItemRemovedSubscription = 0 ;
} else if ( ! _forwardingItemRemovedSubscription ) {
_forwardingItemRemovedSubscription = subscribe ( Global : : RefItemRemoved ( ) , [ this ] ( HistoryItem * item ) {
auto i = _toForward . find ( item - > id ) ;
if ( i = = _toForward . cend ( ) | | i . value ( ) ! = item ) {
i = _toForward . find ( item - > id - ServerMaxMsgId ) ;
}
if ( i ! = _toForward . cend ( ) & & i . value ( ) = = item ) {
_toForward . erase ( i ) ;
updateForwardingItemRemovedSubscription ( ) ;
updateForwardingTexts ( ) ;
}
} ) ;
}
}
2015-03-24 13:00:27 +03:00
void MainWidget : : cancelForwarding ( ) {
if ( _toForward . isEmpty ( ) ) return ;
_toForward . clear ( ) ;
2016-04-13 00:31:28 +03:00
_history - > cancelForwarding ( ) ;
2016-10-14 20:10:15 +03:00
updateForwardingItemRemovedSubscription ( ) ;
2015-03-24 13:00:27 +03:00
}
2016-06-03 15:45:33 +03:00
void MainWidget : : finishForwarding ( History * history , bool silent ) {
if ( ! history ) return ;
2015-12-31 23:27:21 +08:00
2015-04-04 23:01:34 +03:00
if ( ! _toForward . isEmpty ( ) ) {
2015-09-12 14:59:50 +03:00
bool genClientSideMessage = ( _toForward . size ( ) < 2 ) ;
2015-11-13 18:14:33 +03:00
PeerData * forwardFrom = 0 ;
2016-06-03 15:45:33 +03:00
App : : main ( ) - > readServerHistory ( history ) ;
2015-09-12 14:59:50 +03:00
2016-03-19 19:55:15 +03:00
MTPDmessage : : Flags flags = 0 ;
MTPmessages_ForwardMessages : : Flags sendFlags = 0 ;
2016-06-03 15:45:33 +03:00
bool channelPost = history - > peer - > isChannel ( ) & & ! history - > peer - > isMegagroup ( ) ;
bool showFromName = ! channelPost | | history - > peer - > asChannel ( ) - > addsSignature ( ) ;
2016-02-25 19:19:54 +03:00
bool silentPost = channelPost & & silent ;
2016-02-17 19:37:21 +03:00
if ( channelPost ) {
2016-03-19 19:55:15 +03:00
flags | = MTPDmessage : : Flag : : f_views ;
flags | = MTPDmessage : : Flag : : f_post ;
2016-02-17 19:37:21 +03:00
}
if ( showFromName ) {
2016-03-19 19:55:15 +03:00
flags | = MTPDmessage : : Flag : : f_from_id ;
2016-02-17 19:37:21 +03:00
}
2016-02-25 19:19:54 +03:00
if ( silentPost ) {
2016-03-19 19:55:15 +03:00
sendFlags | = MTPmessages_ForwardMessages : : Flag : : f_silent ;
2016-02-25 19:19:54 +03:00
}
2015-11-13 18:14:33 +03:00
2015-09-12 14:59:50 +03:00
QVector < MTPint > ids ;
QVector < MTPlong > randomIds ;
ids . reserve ( _toForward . size ( ) ) ;
randomIds . reserve ( _toForward . size ( ) ) ;
for ( SelectedItemSet : : const_iterator i = _toForward . cbegin ( ) , e = _toForward . cend ( ) ; i ! = e ; + + i ) {
2016-03-24 13:12:18 +03:00
uint64 randomId = rand_value < uint64 > ( ) ;
2015-09-12 14:59:50 +03:00
if ( genClientSideMessage ) {
2016-06-03 15:45:33 +03:00
FullMsgId newId ( peerToChannel ( history - > peer - > id ) , clientMsgId ( ) ) ;
2015-09-12 14:59:50 +03:00
HistoryMessage * msg = static_cast < HistoryMessage * > ( _toForward . cbegin ( ) . value ( ) ) ;
2016-06-03 15:45:33 +03:00
history - > addNewForwarded ( newId . msg , flags , date ( MTP_int ( unixtime ( ) ) ) , showFromName ? MTP : : authedId ( ) : 0 , msg ) ;
2015-09-12 14:59:50 +03:00
App : : historyRegRandom ( randomId , newId ) ;
2015-04-04 23:01:34 +03:00
}
2015-11-13 18:14:33 +03:00
if ( forwardFrom ! = i . value ( ) - > history ( ) - > peer ) {
if ( forwardFrom ) {
2016-06-03 15:45:33 +03:00
history - > sendRequestId = MTP : : send ( MTPmessages_ForwardMessages ( MTP_flags ( sendFlags ) , forwardFrom - > input , MTP_vector < MTPint > ( ids ) , MTP_vector < MTPlong > ( randomIds ) , history - > peer - > input ) , rpcDone ( & MainWidget : : sentUpdatesReceived ) , RPCFailHandlerPtr ( ) , 0 , 0 , history - > sendRequestId ) ;
2015-11-13 18:14:33 +03:00
ids . resize ( 0 ) ;
randomIds . resize ( 0 ) ;
}
forwardFrom = i . value ( ) - > history ( ) - > peer ;
}
ids . push_back ( MTP_int ( i . value ( ) - > id ) ) ;
2015-09-12 14:59:50 +03:00
randomIds . push_back ( MTP_long ( randomId ) ) ;
2014-08-20 09:32:50 +04:00
}
2016-06-03 15:45:33 +03:00
history - > sendRequestId = MTP : : send ( MTPmessages_ForwardMessages ( MTP_flags ( sendFlags ) , forwardFrom - > input , MTP_vector < MTPint > ( ids ) , MTP_vector < MTPlong > ( randomIds ) , history - > peer - > input ) , rpcDone ( & MainWidget : : sentUpdatesReceived ) , RPCFailHandlerPtr ( ) , 0 , 0 , history - > sendRequestId ) ;
2015-09-12 14:59:50 +03:00
2016-06-03 15:45:33 +03:00
if ( _history - > peer ( ) = = history - > peer ) {
2016-04-13 00:31:28 +03:00
_history - > peerMessagesUpdated ( ) ;
2015-11-13 18:14:33 +03:00
}
2015-09-12 14:59:50 +03:00
2015-04-04 23:01:34 +03:00
cancelForwarding ( ) ;
2014-08-20 09:32:50 +04:00
}
2015-04-04 23:01:34 +03:00
2016-06-03 15:45:33 +03:00
historyToDown ( history ) ;
2015-04-04 23:01:34 +03:00
dialogsToUp ( ) ;
2016-06-03 15:45:33 +03:00
_history - > peerMessagesUpdated ( history - > peer - > id ) ;
2014-05-30 12:53:19 +04:00
}
2015-04-08 02:03:32 +03:00
void MainWidget : : webPageUpdated ( WebPageData * data ) {
2016-09-27 16:37:18 +03:00
_webPagesUpdated . insert ( data - > id ) ;
_webPageOrGameUpdater . start ( 0 ) ;
2015-04-08 02:03:32 +03:00
}
2016-09-27 16:37:18 +03:00
void MainWidget : : gameUpdated ( GameData * data ) {
_gamesUpdated . insert ( data - > id ) ;
_webPageOrGameUpdater . start ( 0 ) ;
}
2015-04-30 16:53:36 +03:00
2016-09-27 16:37:18 +03:00
void MainWidget : : webPagesOrGamesUpdate ( ) {
_webPageOrGameUpdater . stop ( ) ;
if ( ! _webPagesUpdated . isEmpty ( ) ) {
auto & items = App : : webPageItems ( ) ;
for_const ( auto webPageId , _webPagesUpdated ) {
auto j = items . constFind ( App : : webPage ( webPageId ) ) ;
if ( j ! = items . cend ( ) ) {
for_const ( auto item , j . value ( ) ) {
item - > setPendingInitDimensions ( ) ;
}
}
}
_webPagesUpdated . clear ( ) ;
}
if ( ! _gamesUpdated . isEmpty ( ) ) {
auto & items = App : : gameItems ( ) ;
for_const ( auto gameId , _gamesUpdated ) {
auto j = items . constFind ( App : : game ( gameId ) ) ;
if ( j ! = items . cend ( ) ) {
for_const ( auto item , j . value ( ) ) {
item - > setPendingInitDimensions ( ) ;
}
2015-04-08 02:03:32 +03:00
}
}
2016-09-27 16:37:18 +03:00
_gamesUpdated . clear ( ) ;
2015-04-08 02:03:32 +03:00
}
}
2015-04-30 16:53:36 +03:00
void MainWidget : : updateMutedIn ( int32 seconds ) {
if ( seconds > 86400 ) seconds = 86400 ;
int32 ms = seconds * 1000 ;
if ( _updateMutedTimer . isActive ( ) & & _updateMutedTimer . remainingTime ( ) < = ms ) return ;
_updateMutedTimer . start ( ms ) ;
}
2015-05-19 18:46:45 +03:00
void MainWidget : : updateStickers ( ) {
2016-04-13 00:31:28 +03:00
_history - > updateStickers ( ) ;
2015-05-19 18:46:45 +03:00
}
2015-04-30 16:53:36 +03:00
void MainWidget : : onUpdateMuted ( ) {
App : : updateMuted ( ) ;
}
2014-05-30 12:53:19 +04:00
void MainWidget : : onShareContact ( const PeerId & peer , UserData * contact ) {
2016-04-13 00:31:28 +03:00
_history - > onShareContact ( peer , contact ) ;
2014-05-30 12:53:19 +04:00
}
2016-11-28 18:45:07 +03:00
bool MainWidget : : onSendPaths ( const PeerId & peer ) {
Ui : : showPeerHistory ( peer , ShowAtTheEndMsgId ) ;
return _history - > confirmSendingFiles ( cSendPaths ( ) ) ;
2014-07-18 14:37:34 +04:00
}
2015-06-27 16:02:00 +03:00
void MainWidget : : onFilesOrForwardDrop ( const PeerId & peer , const QMimeData * data ) {
if ( data - > hasFormat ( qsl ( " application/x-td-forward-selected " ) ) ) {
onForward ( peer , ForwardSelectedMessages ) ;
} else if ( data - > hasFormat ( qsl ( " application/x-td-forward-pressed-link " ) ) ) {
onForward ( peer , ForwardPressedLinkMessage ) ;
} else if ( data - > hasFormat ( qsl ( " application/x-td-forward-pressed " ) ) ) {
onForward ( peer , ForwardPressedMessage ) ;
} else {
2015-12-13 14:36:08 +03:00
Ui : : showPeerHistory ( peer , ShowAtTheEndMsgId ) ;
2016-11-28 18:45:07 +03:00
_history - > confirmSendingFiles ( data ) ;
2015-06-27 16:02:00 +03:00
}
2015-06-26 12:07:59 +03:00
}
2016-04-09 15:02:50 +04:00
void MainWidget : : rpcClear ( ) {
2016-04-13 00:31:28 +03:00
_history - > rpcClear ( ) ;
_dialogs - > rpcClear ( ) ;
if ( _overview ) _overview - > rpcClear ( ) ;
2016-04-09 15:02:50 +04:00
if ( _api ) _api - > rpcClear ( ) ;
RPCSender : : rpcClear ( ) ;
}
2015-12-23 19:48:44 +03:00
bool MainWidget : : isItemVisible ( HistoryItem * item ) {
if ( isHidden ( ) | | _a_show . animating ( ) ) {
return false ;
}
2016-04-13 00:31:28 +03:00
return _history - > isItemVisible ( item ) ;
2015-12-23 19:48:44 +03:00
}
2015-12-11 21:11:38 +03:00
void MainWidget : : notify_botCommandsChanged ( UserData * bot ) {
2016-04-13 00:31:28 +03:00
_history - > notify_botCommandsChanged ( bot ) ;
2015-12-11 21:11:38 +03:00
}
2016-01-01 17:58:05 +08:00
void MainWidget : : notify_inlineBotRequesting ( bool requesting ) {
2016-04-13 00:31:28 +03:00
_history - > notify_inlineBotRequesting ( requesting ) ;
2016-01-01 17:58:05 +08:00
}
2016-04-01 19:32:26 +04:00
void MainWidget : : notify_replyMarkupUpdated ( const HistoryItem * item ) {
2016-04-13 00:31:28 +03:00
_history - > notify_replyMarkupUpdated ( item ) ;
2016-04-01 19:32:26 +04:00
}
2016-04-08 13:20:10 +04:00
void MainWidget : : notify_inlineKeyboardMoved ( const HistoryItem * item , int oldKeyboardTop , int newKeyboardTop ) {
2016-04-13 00:31:28 +03:00
_history - > notify_inlineKeyboardMoved ( item , oldKeyboardTop , newKeyboardTop ) ;
2016-04-08 13:20:10 +04:00
}
2016-08-12 19:28:10 +03:00
bool MainWidget : : notify_switchInlineBotButtonReceived ( const QString & query , UserData * samePeerBot , MsgId samePeerReplyTo ) {
return _history - > notify_switchInlineBotButtonReceived ( query , samePeerBot , samePeerReplyTo ) ;
2016-04-08 18:16:52 +04:00
}
2015-12-11 21:11:38 +03:00
void MainWidget : : notify_userIsBotChanged ( UserData * bot ) {
2016-04-13 00:31:28 +03:00
_history - > notify_userIsBotChanged ( bot ) ;
2015-12-11 21:11:38 +03:00
}
2015-12-13 14:17:15 +03:00
void MainWidget : : notify_userIsContactChanged ( UserData * user , bool fromThisApp ) {
if ( ! user ) return ;
2016-04-13 00:31:28 +03:00
_dialogs - > notify_userIsContactChanged ( user , fromThisApp ) ;
2015-12-13 14:17:15 +03:00
const SharedContactItems & items ( App : : sharedContactItems ( ) ) ;
SharedContactItems : : const_iterator i = items . constFind ( peerToUser ( user - > id ) ) ;
if ( i ! = items . cend ( ) ) {
2016-09-27 16:37:18 +03:00
for_const ( auto item , i . value ( ) ) {
item - > setPendingInitDimensions ( ) ;
2015-12-13 14:17:15 +03:00
}
}
if ( user - > contact > 0 & & fromThisApp ) {
Ui : : showPeerHistory ( user - > id , ShowAtTheEndMsgId ) ;
}
}
2015-12-11 21:11:38 +03:00
void MainWidget : : notify_migrateUpdated ( PeerData * peer ) {
2016-04-13 00:31:28 +03:00
_history - > notify_migrateUpdated ( peer ) ;
2015-12-11 21:11:38 +03:00
}
2015-12-28 00:37:48 +03:00
void MainWidget : : notify_clipStopperHidden ( ClipStopperType type ) {
2016-04-13 00:31:28 +03:00
_history - > notify_clipStopperHidden ( type ) ;
2015-12-25 16:09:14 +03:00
}
2015-12-28 00:37:48 +03:00
void MainWidget : : ui_repaintHistoryItem ( const HistoryItem * item ) {
2016-04-13 00:31:28 +03:00
_history - > ui_repaintHistoryItem ( item ) ;
2016-02-28 14:58:30 +03:00
if ( item - > history ( ) - > lastMsg = = item ) {
item - > history ( ) - > updateChatListEntry ( ) ;
2015-12-11 21:11:38 +03:00
}
2016-10-14 20:10:15 +03:00
_playerPlaylist - > ui_repaintHistoryItem ( item ) ;
_playerPanel - > ui_repaintHistoryItem ( item ) ;
2016-04-13 00:31:28 +03:00
if ( _overview ) _overview - > ui_repaintHistoryItem ( item ) ;
2015-12-28 00:37:48 +03:00
}
2016-04-05 01:09:46 +04:00
void MainWidget : : ui_repaintInlineItem ( const InlineBots : : Layout : : ItemBase * layout ) {
2016-04-13 00:31:28 +03:00
_history - > ui_repaintInlineItem ( layout ) ;
2015-12-28 00:37:48 +03:00
}
2016-04-05 01:09:46 +04:00
bool MainWidget : : ui_isInlineItemVisible ( const InlineBots : : Layout : : ItemBase * layout ) {
2016-04-13 00:31:28 +03:00
return _history - > ui_isInlineItemVisible ( layout ) ;
2015-12-28 00:37:48 +03:00
}
2015-12-31 03:09:20 +08:00
bool MainWidget : : ui_isInlineItemBeingChosen ( ) {
2016-04-13 00:31:28 +03:00
return _history - > ui_isInlineItemBeingChosen ( ) ;
2015-12-13 01:29:33 +03:00
}
void MainWidget : : notify_historyItemLayoutChanged ( const HistoryItem * item ) {
2016-04-13 00:31:28 +03:00
_history - > notify_historyItemLayoutChanged ( item ) ;
if ( _overview ) _overview - > notify_historyItemLayoutChanged ( item ) ;
2015-12-11 21:11:38 +03:00
}
2016-04-10 22:18:26 +04:00
void MainWidget : : notify_inlineItemLayoutChanged ( const InlineBots : : Layout : : ItemBase * layout ) {
2016-04-13 00:31:28 +03:00
_history - > notify_inlineItemLayoutChanged ( layout ) ;
2016-04-10 22:18:26 +04:00
}
2016-04-11 14:59:01 +04:00
void MainWidget : : notify_historyMuteUpdated ( History * history ) {
2016-04-13 00:31:28 +03:00
_dialogs - > notify_historyMuteUpdated ( history ) ;
2016-04-11 14:59:01 +04:00
}
2016-03-19 19:55:15 +03:00
void MainWidget : : notify_handlePendingHistoryUpdate ( ) {
2016-04-13 00:31:28 +03:00
_history - > notify_handlePendingHistoryUpdate ( ) ;
2016-03-19 19:55:15 +03:00
}
2016-07-14 14:20:46 +03:00
bool MainWidget : : cmd_search ( ) {
if ( Ui : : isLayerShown ( ) | | Ui : : isMediaViewShown ( ) ) return false ;
return _history - > cmd_search ( ) ;
2016-02-27 22:39:51 +03:00
}
2016-07-14 14:20:46 +03:00
bool MainWidget : : cmd_next_chat ( ) {
if ( Ui : : isLayerShown ( ) | | Ui : : isMediaViewShown ( ) ) return false ;
return _history - > cmd_next_chat ( ) ;
2016-02-27 22:39:51 +03:00
}
2016-07-14 14:20:46 +03:00
bool MainWidget : : cmd_previous_chat ( ) {
if ( Ui : : isLayerShown ( ) | | Ui : : isMediaViewShown ( ) ) return false ;
return _history - > cmd_previous_chat ( ) ;
2016-02-27 22:39:51 +03:00
}
2014-05-30 12:53:19 +04:00
void MainWidget : : noHider ( HistoryHider * destroyed ) {
2015-07-17 22:17:37 +03:00
if ( _hider = = destroyed ) {
2016-04-13 00:31:28 +03:00
_hider = nullptr ;
2016-02-08 17:54:55 +03:00
if ( Adaptive : : OneColumn ( ) ) {
2014-12-12 19:27:03 +03:00
if ( _forwardConfirm ) {
2016-12-13 20:07:56 +03:00
_forwardConfirm - > closeBox ( ) ;
_forwardConfirm = nullptr ;
2014-12-12 19:27:03 +03:00
}
2016-04-13 00:31:28 +03:00
onHistoryShown ( _history - > history ( ) , _history - > msgId ( ) ) ;
2016-05-19 15:03:51 +03:00
if ( _wideSection | | _overview | | ( _history - > peer ( ) & & _history - > peer ( ) - > id ) ) {
2017-01-14 21:50:16 +03:00
auto animationParams = ( [ this ] {
if ( _overview ) {
return prepareOverviewAnimation ( ) ;
} else if ( _wideSection ) {
return prepareWideSectionAnimation ( _wideSection ) ;
}
return prepareHistoryAnimation ( _history - > peer ( ) ? _history - > peer ( ) - > id : 0 ) ;
} ) ( ) ;
2016-04-13 00:31:28 +03:00
_dialogs - > hide ( ) ;
if ( _overview ) {
2016-05-19 15:03:51 +03:00
_overview - > showAnimated ( Window : : SlideDirection : : FromRight , animationParams ) ;
} else if ( _wideSection ) {
_wideSection - > showAnimated ( Window : : SlideDirection : : FromRight , animationParams ) ;
2014-12-12 19:27:03 +03:00
} else {
2016-05-19 15:03:51 +03:00
_history - > showAnimated ( Window : : SlideDirection : : FromRight , animationParams ) ;
2014-12-12 19:27:03 +03:00
}
}
2016-02-08 17:54:55 +03:00
} else {
if ( _forwardConfirm ) {
_forwardConfirm - > deleteLater ( ) ;
2016-12-13 20:07:56 +03:00
_forwardConfirm = nullptr ;
2016-02-08 17:54:55 +03:00
}
2014-12-12 19:27:03 +03:00
}
2014-05-30 12:53:19 +04:00
}
}
2016-12-13 20:07:56 +03:00
void MainWidget : : hiderLayer ( object_ptr < HistoryHider > h ) {
2015-04-04 23:01:34 +03:00
if ( App : : passcoded ( ) ) {
return ;
}
2015-03-02 15:34:16 +03:00
2016-12-13 20:07:56 +03:00
_hider = std_ : : move ( h ) ;
2016-04-13 00:31:28 +03:00
connect ( _hider , SIGNAL ( forwarded ( ) ) , _dialogs , SLOT ( onCancelSearch ( ) ) ) ;
2016-02-08 17:54:55 +03:00
if ( Adaptive : : OneColumn ( ) ) {
2015-06-26 12:07:59 +03:00
dialogsToUp ( ) ;
2015-07-17 22:17:37 +03:00
_hider - > hide ( ) ;
2016-05-19 15:03:51 +03:00
auto animationParams = prepareDialogsAnimation ( ) ;
2014-12-12 19:27:03 +03:00
2015-10-03 13:09:09 +03:00
onHistoryShown ( 0 , 0 ) ;
2016-04-13 00:31:28 +03:00
if ( _overview ) {
_overview - > hide ( ) ;
2016-05-19 15:03:51 +03:00
} else if ( _wideSection ) {
_wideSection - > hide ( ) ;
2014-12-12 19:27:03 +03:00
} else {
2016-04-13 00:31:28 +03:00
_history - > hide ( ) ;
2014-12-12 19:27:03 +03:00
}
2016-08-16 19:53:10 +03:00
if ( _dialogs - > isHidden ( ) ) {
_dialogs - > show ( ) ;
2017-01-30 18:27:13 +03:00
updateControlsGeometry ( ) ;
2016-08-16 19:53:10 +03:00
_dialogs - > showAnimated ( Window : : SlideDirection : : FromLeft , animationParams ) ;
}
2016-02-08 17:54:55 +03:00
} else {
_hider - > show ( ) ;
2017-01-30 18:27:13 +03:00
updateControlsGeometry ( ) ;
2016-04-13 00:31:28 +03:00
_dialogs - > activate ( ) ;
2014-12-12 19:27:03 +03:00
}
}
2016-12-31 17:34:41 +04:00
void MainWidget : : forwardLayer ( int forwardSelected ) {
2016-12-13 20:07:56 +03:00
hiderLayer ( ( forwardSelected < 0 ) ? object_ptr < HistoryHider > ( this ) : object_ptr < HistoryHider > ( this , forwardSelected > 0 ) ) ;
2014-05-30 12:53:19 +04:00
}
2016-12-31 17:34:41 +04:00
void MainWidget : : deleteLayer ( int selectedCount ) {
2016-12-31 19:19:22 +04:00
if ( selectedCount ) {
auto forDelete = true ;
SelectedItemSet selected ;
if ( _overview ) {
_overview - > fillSelectedItems ( selected , forDelete ) ;
} else {
_history - > fillSelectedItems ( selected , forDelete ) ;
2016-03-10 18:42:01 +03:00
}
2016-12-31 19:19:22 +04:00
if ( ! selected . isEmpty ( ) ) {
Ui : : show ( Box < DeleteMessagesBox > ( selected ) ) ;
2015-12-24 22:26:28 +03:00
}
2016-12-31 19:19:22 +04:00
} else if ( auto item = App : : contextItem ( ) ) {
auto suggestModerateActions = ! _overview ;
Ui : : show ( Box < DeleteMessagesBox > ( item , suggestModerateActions ) ) ;
2014-05-30 12:53:19 +04:00
}
2016-12-31 19:19:22 +04:00
}
void MainWidget : : cancelUploadLayer ( ) {
auto item = App : : contextItem ( ) ;
if ( ! item ) {
return ;
}
App : : uploader ( ) - > pause ( item - > fullId ( ) ) ;
Ui : : show ( Box < ConfirmBox > ( lang ( lng_selected_cancel_sure_this ) , lang ( lng_selected_upload_stop ) , lang ( lng_continue ) , base : : lambda_guarded ( this , [ this ] {
if ( _overview ) {
_overview - > deleteContextItem ( false ) ;
2016-12-13 20:07:56 +03:00
} else {
2016-12-31 19:19:22 +04:00
_history - > deleteContextItem ( false ) ;
2016-12-13 20:07:56 +03:00
}
2016-12-31 19:19:22 +04:00
App : : uploader ( ) - > unpause ( ) ;
} ) , base : : lambda_guarded ( this , [ ] {
App : : uploader ( ) - > unpause ( ) ;
2016-12-13 20:07:56 +03:00
} ) ) ) ;
2014-05-30 12:53:19 +04:00
}
2016-06-14 19:26:41 +03:00
void MainWidget : : deletePhotoLayer ( PhotoData * photo ) {
2016-12-13 20:07:56 +03:00
if ( ! photo ) return ;
Ui : : show ( Box < ConfirmBox > ( lang ( lng_delete_photo_sure ) , lang ( lng_box_delete ) , base : : lambda_guarded ( this , [ this , photo ] {
Ui : : hideLayer ( ) ;
2016-06-14 19:26:41 +03:00
2016-12-13 20:07:56 +03:00
auto me = App : : self ( ) ;
if ( ! me ) return ;
2016-06-14 19:26:41 +03:00
2016-12-13 20:07:56 +03:00
if ( me - > photoId = = photo - > id ) {
App : : app ( ) - > peerClearPhoto ( me - > id ) ;
} else if ( photo - > peer & & ! photo - > peer - > isUser ( ) & & photo - > peer - > photoId = = photo - > id ) {
App : : app ( ) - > peerClearPhoto ( photo - > peer - > id ) ;
} else {
for ( int i = 0 , l = me - > photos . size ( ) ; i ! = l ; + + i ) {
if ( me - > photos . at ( i ) = = photo ) {
me - > photos . removeAt ( i ) ;
MTP : : send ( MTPphotos_DeletePhotos ( MTP_vector < MTPInputPhoto > ( 1 , MTP_inputPhoto ( MTP_long ( photo - > id ) , MTP_long ( photo - > access ) ) ) ) ) ;
break ;
}
2016-06-14 19:26:41 +03:00
}
}
2016-12-13 20:07:56 +03:00
} ) ) ) ;
2016-06-14 19:26:41 +03:00
}
2014-05-30 12:53:19 +04:00
void MainWidget : : shareContactLayer ( UserData * contact ) {
2016-12-13 20:07:56 +03:00
hiderLayer ( object_ptr < HistoryHider > ( this , contact ) ) ;
2014-05-30 12:53:19 +04:00
}
2015-10-18 14:49:34 +02:00
void MainWidget : : shareUrlLayer ( const QString & url , const QString & text ) {
2016-12-18 19:12:49 +03:00
// Don't allow to insert an inline bot query by share url link.
if ( url . trimmed ( ) . startsWith ( ' @ ' ) ) {
return ;
}
2016-12-13 20:07:56 +03:00
hiderLayer ( object_ptr < HistoryHider > ( this , url , text ) ) ;
2015-10-18 14:49:34 +02:00
}
2016-04-08 18:16:52 +04:00
void MainWidget : : inlineSwitchLayer ( const QString & botAndQuery ) {
2016-12-13 20:07:56 +03:00
hiderLayer ( object_ptr < HistoryHider > ( this , botAndQuery ) ) ;
2016-04-08 18:16:52 +04:00
}
2015-04-04 23:01:34 +03:00
bool MainWidget : : selectingPeer ( bool withConfirm ) {
2015-07-17 22:17:37 +03:00
return _hider ? ( withConfirm ? _hider - > withConfirm ( ) : true ) : false ;
2014-05-30 12:53:19 +04:00
}
2016-04-08 18:16:52 +04:00
bool MainWidget : : selectingPeerForInlineSwitch ( ) {
return selectingPeer ( ) ? ! _hider - > botAndQuery ( ) . isEmpty ( ) : false ;
}
2014-05-30 12:53:19 +04:00
void MainWidget : : offerPeer ( PeerId peer ) {
2015-12-07 21:09:05 +03:00
Ui : : hideLayer ( ) ;
2016-02-08 17:54:55 +03:00
if ( _hider - > offerPeer ( peer ) & & Adaptive : : OneColumn ( ) ) {
2016-12-13 20:07:56 +03:00
_forwardConfirm = Ui : : show ( Box < ConfirmBox > ( _hider - > offeredText ( ) , lang ( lng_forward_send ) , base : : lambda_guarded ( this , [ this ] {
_hider - > forward ( ) ;
if ( _forwardConfirm ) _forwardConfirm - > closeBox ( ) ;
if ( _hider ) _hider - > offerPeer ( 0 ) ;
} ) , base : : lambda_guarded ( this , [ this ] {
if ( _hider & & _forwardConfirm ) _hider - > offerPeer ( 0 ) ;
} ) ) ) ;
2014-12-12 19:27:03 +03:00
}
2014-05-30 12:53:19 +04:00
}
void MainWidget : : dialogsActivate ( ) {
2016-04-13 00:31:28 +03:00
_dialogs - > activate ( ) ;
2014-05-30 12:53:19 +04:00
}
2015-06-24 20:24:48 +03:00
DragState MainWidget : : getDragState ( const QMimeData * mime ) {
2016-04-13 00:31:28 +03:00
return _history - > getDragState ( mime ) ;
2015-06-24 20:24:48 +03:00
}
2015-04-04 23:01:34 +03:00
bool MainWidget : : leaveChatFailed ( PeerData * peer , const RPCError & error ) {
2016-04-08 14:44:35 +04:00
if ( MTP : : isDefaultHandledError ( error ) ) return false ;
2015-04-04 23:01:34 +03:00
2015-11-19 14:28:17 +03:00
if ( error . type ( ) = = qstr ( " USER_NOT_PARTICIPANT " ) | | error . type ( ) = = qstr ( " CHAT_ID_INVALID " ) | | error . type ( ) = = qstr ( " PEER_ID_INVALID " ) ) { // left this chat already
2015-09-24 11:58:10 +03:00
deleteConversation ( peer ) ;
2014-05-30 12:53:19 +04:00
return true ;
}
return false ;
}
2015-08-04 18:01:47 +03:00
void MainWidget : : deleteHistoryAfterLeave ( PeerData * peer , const MTPUpdates & updates ) {
2015-04-02 13:33:19 +03:00
sentUpdatesReceived ( updates ) ;
2015-09-24 11:58:10 +03:00
deleteConversation ( peer ) ;
2014-05-30 12:53:19 +04:00
}
2016-06-03 15:45:33 +03:00
void MainWidget : : deleteHistoryPart ( DeleteHistoryRequest request , const MTPmessages_AffectedHistory & result ) {
auto peer = request . peer ;
2016-04-08 14:44:35 +04:00
const auto & d ( result . c_messages_affectedHistory ( ) ) ;
2016-03-13 18:45:00 +03:00
if ( peer & & peer - > isChannel ( ) ) {
if ( peer - > asChannel ( ) - > ptsUpdated ( d . vpts . v , d . vpts_count . v ) ) {
peer - > asChannel ( ) - > ptsApplySkippedUpdates ( ) ;
}
} else {
if ( ptsUpdated ( d . vpts . v , d . vpts_count . v ) ) {
ptsApplySkippedUpdates ( ) ;
}
2015-09-20 12:54:22 +03:00
}
2014-05-30 12:53:19 +04:00
int32 offset = d . voffset . v ;
2015-09-08 20:22:29 +03:00
if ( ! MTP : : authedId ( ) ) return ;
if ( offset < = 0 ) {
cRefReportSpamStatuses ( ) . remove ( peer - > id ) ;
Local : : writeReportSpamStatuses ( ) ;
return ;
}
2014-05-30 12:53:19 +04:00
2016-06-03 15:45:33 +03:00
MTPmessages_DeleteHistory : : Flags flags = 0 ;
if ( request . justClearHistory ) {
flags | = MTPmessages_DeleteHistory : : Flag : : f_just_clear ;
}
MTP : : send ( MTPmessages_DeleteHistory ( MTP_flags ( flags ) , peer - > input , MTP_int ( 0 ) ) , rpcDone ( & MainWidget : : deleteHistoryPart , request ) ) ;
2014-05-30 12:53:19 +04:00
}
2016-12-31 17:34:41 +04:00
void MainWidget : : deleteMessages ( PeerData * peer , const QVector < MTPint > & ids , bool forEveryone ) {
2015-09-07 10:52:37 +03:00
if ( peer - > isChannel ( ) ) {
2015-09-17 00:15:13 +03:00
MTP : : send ( MTPchannels_DeleteMessages ( peer - > asChannel ( ) - > inputChannel , MTP_vector < MTPint > ( ids ) ) , rpcDone ( & MainWidget : : messagesAffected , peer ) ) ;
2015-09-07 10:52:37 +03:00
} else {
2016-12-31 17:34:41 +04:00
auto flags = MTPmessages_DeleteMessages : : Flags ( 0 ) ;
if ( forEveryone ) {
flags | = MTPmessages_DeleteMessages : : Flag : : f_revoke ;
}
MTP : : send ( MTPmessages_DeleteMessages ( MTP_flags ( flags ) , MTP_vector < MTPint > ( ids ) ) , rpcDone ( & MainWidget : : messagesAffected , peer ) ) ;
2015-09-07 10:52:37 +03:00
}
2015-03-19 12:18:19 +03:00
}
2014-05-30 12:53:19 +04:00
void MainWidget : : deletedContact ( UserData * user , const MTPcontacts_Link & result ) {
2016-05-25 15:09:05 +03:00
auto & d ( result . c_contacts_link ( ) ) ;
2016-06-02 16:57:49 +03:00
App : : feedUsers ( MTP_vector < MTPUser > ( 1 , d . vuser ) ) ;
App : : feedUserLink ( MTP_int ( peerToUser ( user - > id ) ) , d . vmy_link , d . vforeign_link ) ;
2014-05-30 12:53:19 +04:00
}
2015-11-13 18:14:33 +03:00
void MainWidget : : removeDialog ( History * history ) {
2016-04-13 00:31:28 +03:00
_dialogs - > removeDialog ( history ) ;
2015-11-13 18:14:33 +03:00
}
2015-09-24 11:58:10 +03:00
void MainWidget : : deleteConversation ( PeerData * peer , bool deleteHistory ) {
if ( activePeer ( ) = = peer ) {
2015-12-13 14:36:08 +03:00
Ui : : showChatsList ( ) ;
2015-09-24 11:58:10 +03:00
}
2016-12-13 10:59:57 +03:00
if ( auto history = App : : historyLoaded ( peer - > id ) ) {
history - > setPinnedDialog ( false ) ;
removeDialog ( history ) ;
2015-11-20 21:24:44 +03:00
if ( peer - > isMegagroup ( ) & & peer - > asChannel ( ) - > mgInfo - > migrateFromPtr ) {
2016-12-13 10:59:57 +03:00
if ( auto migrated = App : : historyLoaded ( peer - > asChannel ( ) - > mgInfo - > migrateFromPtr - > id ) ) {
2015-11-20 21:24:44 +03:00
if ( migrated - > lastMsg ) { // return initial dialog
migrated - > setLastMessage ( migrated - > lastMsg ) ;
} else {
checkPeerHistory ( migrated - > peer ) ;
}
}
}
2016-12-13 10:59:57 +03:00
history - > clear ( ) ;
history - > newLoaded = true ;
history - > oldLoaded = deleteHistory ;
2015-09-24 11:58:10 +03:00
}
if ( peer - > isChannel ( ) ) {
peer - > asChannel ( ) - > ptsWaitingForShortPoll ( - 1 ) ;
}
if ( deleteHistory ) {
2016-06-03 15:45:33 +03:00
DeleteHistoryRequest request = { peer , false } ;
MTPmessages_DeleteHistory : : Flags flags = 0 ;
MTP : : send ( MTPmessages_DeleteHistory ( MTP_flags ( flags ) , peer - > input , MTP_int ( 0 ) ) , rpcDone ( & MainWidget : : deleteHistoryPart , request ) ) ;
2015-09-19 12:13:21 +03:00
}
2014-05-30 12:53:19 +04:00
}
2016-06-01 23:05:37 +03:00
void MainWidget : : deleteAndExit ( ChatData * chat ) {
PeerData * peer = chat ;
MTP : : send ( MTPmessages_DeleteChatUser ( chat - > inputChat , App : : self ( ) - > inputUser ) , rpcDone ( & MainWidget : : deleteHistoryAfterLeave , peer ) , rpcFail ( & MainWidget : : leaveChatFailed , peer ) ) ;
}
2016-03-13 18:45:00 +03:00
void MainWidget : : deleteAllFromUser ( ChannelData * channel , UserData * from ) {
t_assert ( channel ! = nullptr & & from ! = nullptr ) ;
QVector < MsgId > toDestroy ;
2016-03-14 19:59:18 +03:00
if ( History * history = App : : historyLoaded ( channel - > id ) ) {
for ( HistoryBlock * block : history - > blocks ) {
for ( HistoryItem * item : block - > items ) {
if ( item - > from ( ) = = from & & item - > type ( ) = = HistoryItemMsg & & item - > canDelete ( ) ) {
toDestroy . push_back ( item - > id ) ;
2016-03-13 18:45:00 +03:00
}
}
}
2016-03-14 19:59:18 +03:00
for ( const MsgId & msgId : toDestroy ) {
if ( HistoryItem * item = App : : histItemById ( peerToChannel ( channel - > id ) , msgId ) ) {
2016-03-13 18:45:00 +03:00
item - > destroy ( ) ;
}
}
}
MTP : : send ( MTPchannels_DeleteUserHistory ( channel - > inputChannel , from - > inputUser ) , rpcDone ( & MainWidget : : deleteAllFromUserPart , { channel , from } ) ) ;
}
void MainWidget : : deleteAllFromUserPart ( DeleteAllFromUserParams params , const MTPmessages_AffectedHistory & result ) {
2016-04-08 14:44:35 +04:00
const auto & d ( result . c_messages_affectedHistory ( ) ) ;
2016-03-13 18:45:00 +03:00
if ( params . channel - > ptsUpdated ( d . vpts . v , d . vpts_count . v ) ) {
params . channel - > ptsApplySkippedUpdates ( ) ;
}
int32 offset = d . voffset . v ;
if ( ! MTP : : authedId ( ) ) return ;
if ( offset > 0 ) {
MTP : : send ( MTPchannels_DeleteUserHistory ( params . channel - > inputChannel , params . from - > inputUser ) , rpcDone ( & MainWidget : : deleteAllFromUserPart , params ) ) ;
2016-03-14 19:59:18 +03:00
} else if ( History * h = App : : historyLoaded ( params . channel ) ) {
2016-03-13 18:45:00 +03:00
if ( ! h - > lastMsg ) {
checkPeerHistory ( params . channel ) ;
}
}
}
2014-05-30 12:53:19 +04:00
void MainWidget : : clearHistory ( PeerData * peer ) {
2015-09-19 12:13:21 +03:00
if ( History * h = App : : historyLoaded ( peer - > id ) ) {
if ( h - > lastMsg ) {
Local : : addSavedPeer ( h - > peer , h - > lastMsg - > date ) ;
}
h - > clear ( ) ;
h - > newLoaded = h - > oldLoaded = true ;
2014-05-30 12:53:19 +04:00
}
2016-06-03 15:45:33 +03:00
MTPmessages_DeleteHistory : : Flags flags = MTPmessages_DeleteHistory : : Flag : : f_just_clear ;
DeleteHistoryRequest request = { peer , true } ;
MTP : : send ( MTPmessages_DeleteHistory ( MTP_flags ( flags ) , peer - > input , MTP_int ( 0 ) ) , rpcDone ( & MainWidget : : deleteHistoryPart , request ) ) ;
2014-05-30 12:53:19 +04:00
}
2015-09-16 16:04:08 +03:00
void MainWidget : : addParticipants ( PeerData * chatOrChannel , const QVector < UserData * > & users ) {
2015-09-17 00:15:13 +03:00
if ( chatOrChannel - > isChat ( ) ) {
2017-01-01 20:45:20 +04:00
auto chat = chatOrChannel - > asChat ( ) ;
for_const ( auto user , users ) {
MTP : : send ( MTPmessages_AddChatUser ( chat - > inputChat , user - > inputUser , MTP_int ( ForwardOnAdd ) ) , rpcDone ( & MainWidget : : sentUpdatesReceived ) , rpcFail ( & MainWidget : : addParticipantFail , { user , chat } ) , 0 , 5 ) ;
2015-09-16 16:04:08 +03:00
}
2015-09-17 00:15:13 +03:00
} else if ( chatOrChannel - > isChannel ( ) ) {
QVector < MTPInputUser > inputUsers ;
2015-12-06 18:50:02 +03:00
inputUsers . reserve ( qMin ( users . size ( ) , int ( MaxUsersPerInvite ) ) ) ;
2015-09-17 00:15:13 +03:00
for ( QVector < UserData * > : : const_iterator i = users . cbegin ( ) , e = users . cend ( ) ; i ! = e ; + + i ) {
inputUsers . push_back ( ( * i ) - > inputUser ) ;
2015-12-06 18:50:02 +03:00
if ( inputUsers . size ( ) = = MaxUsersPerInvite ) {
MTP : : send ( MTPchannels_InviteToChannel ( chatOrChannel - > asChannel ( ) - > inputChannel , MTP_vector < MTPInputUser > ( inputUsers ) ) , rpcDone ( & MainWidget : : inviteToChannelDone , chatOrChannel - > asChannel ( ) ) , rpcFail ( & MainWidget : : addParticipantsFail , chatOrChannel - > asChannel ( ) ) , 0 , 5 ) ;
inputUsers . clear ( ) ;
}
}
if ( ! inputUsers . isEmpty ( ) ) {
MTP : : send ( MTPchannels_InviteToChannel ( chatOrChannel - > asChannel ( ) - > inputChannel , MTP_vector < MTPInputUser > ( inputUsers ) ) , rpcDone ( & MainWidget : : inviteToChannelDone , chatOrChannel - > asChannel ( ) ) , rpcFail ( & MainWidget : : addParticipantsFail , chatOrChannel - > asChannel ( ) ) , 0 , 5 ) ;
2015-09-17 00:15:13 +03:00
}
2014-05-30 12:53:19 +04:00
}
}
2017-01-01 20:45:20 +04:00
bool MainWidget : : addParticipantFail ( UserAndPeer data , const RPCError & error ) {
2016-04-08 14:44:35 +04:00
if ( MTP : : isDefaultHandledError ( error ) ) return false ;
2015-04-04 23:01:34 +03:00
2015-06-15 20:19:24 +03:00
QString text = lang ( lng_failed_add_participant ) ;
2016-04-08 14:44:35 +04:00
if ( error . type ( ) = = qstr ( " USER_LEFT_CHAT " ) ) { // trying to return a user who has left
} else if ( error . type ( ) = = qstr ( " USER_KICKED " ) ) { // trying to return a user who was kicked by admin
2016-03-23 19:50:40 +03:00
text = lang ( lng_cant_invite_banned ) ;
2016-04-08 14:44:35 +04:00
} else if ( error . type ( ) = = qstr ( " USER_PRIVACY_RESTRICTED " ) ) {
2016-02-14 21:29:17 +03:00
text = lang ( lng_cant_invite_privacy ) ;
2016-04-08 14:44:35 +04:00
} else if ( error . type ( ) = = qstr ( " USER_NOT_MUTUAL_CONTACT " ) ) { // trying to return user who does not have me in contacts
2015-08-07 15:11:50 +03:00
text = lang ( lng_failed_add_not_mutual ) ;
2017-01-01 20:45:20 +04:00
} else if ( error . type ( ) = = qstr ( " USER_ALREADY_PARTICIPANT " ) & & data . user - > botInfo ) {
2015-06-15 20:19:24 +03:00
text = lang ( lng_bot_already_in_group ) ;
2016-04-08 14:44:35 +04:00
} else if ( error . type ( ) = = qstr ( " PEER_FLOOD " ) ) {
2017-01-01 20:45:20 +04:00
text = PeerFloodErrorText ( ( data . peer - > isChat ( ) | | data . peer - > isMegagroup ( ) ) ? PeerFloodType : : InviteGroup : PeerFloodType : : InviteChannel ) ;
2014-05-30 12:53:19 +04:00
}
2016-12-13 20:07:56 +03:00
Ui : : show ( Box < InformBox > ( text ) ) ;
2014-05-30 12:53:19 +04:00
return false ;
}
2015-11-02 17:33:57 -05:00
bool MainWidget : : addParticipantsFail ( ChannelData * channel , const RPCError & error ) {
2016-04-08 14:44:35 +04:00
if ( MTP : : isDefaultHandledError ( error ) ) return false ;
2015-09-17 00:15:13 +03:00
QString text = lang ( lng_failed_add_participant ) ;
2016-04-08 14:44:35 +04:00
if ( error . type ( ) = = qstr ( " USER_LEFT_CHAT " ) ) { // trying to return banned user to his group
} else if ( error . type ( ) = = qstr ( " USER_KICKED " ) ) { // trying to return a user who was kicked by admin
2016-03-23 19:50:40 +03:00
text = lang ( lng_cant_invite_banned ) ;
2016-04-08 14:44:35 +04:00
} else if ( error . type ( ) = = qstr ( " USER_PRIVACY_RESTRICTED " ) ) {
2016-03-23 19:50:40 +03:00
text = lang ( channel - > isMegagroup ( ) ? lng_cant_invite_privacy : lng_cant_invite_privacy_channel ) ;
2016-04-08 14:44:35 +04:00
} else if ( error . type ( ) = = qstr ( " USER_NOT_MUTUAL_CONTACT " ) ) { // trying to return user who does not have me in contacts
2015-11-02 17:33:57 -05:00
text = lang ( channel - > isMegagroup ( ) ? lng_failed_add_not_mutual : lng_failed_add_not_mutual_channel ) ;
2016-04-08 14:44:35 +04:00
} else if ( error . type ( ) = = qstr ( " PEER_FLOOD " ) ) {
2017-01-01 20:45:20 +04:00
text = PeerFloodErrorText ( PeerFloodType : : InviteGroup ) ;
2015-09-17 00:15:13 +03:00
}
2016-12-13 20:07:56 +03:00
Ui : : show ( Box < InformBox > ( text ) ) ;
2015-09-17 00:15:13 +03:00
return false ;
}
2014-05-30 12:53:19 +04:00
void MainWidget : : kickParticipant ( ChatData * chat , UserData * user ) {
2015-09-03 13:48:40 +03:00
MTP : : send ( MTPmessages_DeleteChatUser ( chat - > inputChat , user - > inputUser ) , rpcDone ( & MainWidget : : sentUpdatesReceived ) , rpcFail ( & MainWidget : : kickParticipantFail , chat ) ) ;
2015-12-13 14:36:08 +03:00
Ui : : showPeerHistory ( chat - > id , ShowAtTheEndMsgId ) ;
2014-05-30 12:53:19 +04:00
}
2015-04-04 23:01:34 +03:00
bool MainWidget : : kickParticipantFail ( ChatData * chat , const RPCError & error ) {
2016-04-08 14:44:35 +04:00
if ( MTP : : isDefaultHandledError ( error ) ) return false ;
2015-04-04 23:01:34 +03:00
error . type ( ) ;
2014-05-30 12:53:19 +04:00
return false ;
}
void MainWidget : : checkPeerHistory ( PeerData * peer ) {
2016-05-27 19:47:46 +03:00
MTP : : send ( MTPmessages_GetHistory ( peer - > input , MTP_int ( 0 ) , MTP_int ( 0 ) , MTP_int ( 0 ) , MTP_int ( 1 ) , MTP_int ( 0 ) , MTP_int ( 0 ) ) , rpcDone ( & MainWidget : : checkedHistory , peer ) ) ;
2014-05-30 12:53:19 +04:00
}
void MainWidget : : checkedHistory ( PeerData * peer , const MTPmessages_Messages & result ) {
const QVector < MTPMessage > * v = 0 ;
2015-09-04 16:01:31 +03:00
switch ( result . type ( ) ) {
case mtpc_messages_messages : {
2016-05-27 19:47:46 +03:00
auto & d ( result . c_messages_messages ( ) ) ;
2014-05-30 12:53:19 +04:00
App : : feedUsers ( d . vusers ) ;
2015-06-30 01:09:23 +03:00
App : : feedChats ( d . vchats ) ;
2014-05-30 12:53:19 +04:00
v = & d . vmessages . c_vector ( ) . v ;
2015-09-04 16:01:31 +03:00
} break ;
case mtpc_messages_messagesSlice : {
2016-05-27 19:47:46 +03:00
auto & d ( result . c_messages_messagesSlice ( ) ) ;
2014-05-30 12:53:19 +04:00
App : : feedUsers ( d . vusers ) ;
2015-06-30 01:09:23 +03:00
App : : feedChats ( d . vchats ) ;
2014-05-30 12:53:19 +04:00
v = & d . vmessages . c_vector ( ) . v ;
2015-09-04 16:01:31 +03:00
} break ;
2015-09-13 11:41:27 +03:00
case mtpc_messages_channelMessages : {
2016-05-27 19:47:46 +03:00
auto & d ( result . c_messages_channelMessages ( ) ) ;
2015-09-13 11:41:27 +03:00
if ( peer & & peer - > isChannel ( ) ) {
peer - > asChannel ( ) - > ptsReceived ( d . vpts . v ) ;
} else {
2015-09-19 12:13:21 +03:00
LOG ( ( " API Error: received messages.channelMessages when no channel was passed! (MainWidget::checkedHistory) " ) ) ;
2015-09-13 11:41:27 +03:00
}
2015-09-04 16:01:31 +03:00
App : : feedUsers ( d . vusers ) ;
App : : feedChats ( d . vchats ) ;
v = & d . vmessages . c_vector ( ) . v ;
} break ;
2014-05-30 12:53:19 +04:00
}
if ( ! v ) return ;
if ( v - > isEmpty ( ) ) {
2016-06-03 21:24:27 +03:00
if ( peer - > isChat ( ) & & ! peer - > asChat ( ) - > haveLeft ( ) ) {
History * h = App : : historyLoaded ( peer - > id ) ;
if ( h ) Local : : addSavedPeer ( peer , h - > lastMsgDate ) ;
2015-09-21 23:57:42 +03:00
} else if ( peer - > isChannel ( ) ) {
2015-09-23 20:43:08 +03:00
if ( peer - > asChannel ( ) - > inviter > 0 & & peer - > asChannel ( ) - > amIn ( ) ) {
if ( UserData * from = App : : userLoaded ( peer - > asChannel ( ) - > inviter ) ) {
History * h = App : : history ( peer - > id ) ;
h - > clear ( true ) ;
2016-05-27 19:47:46 +03:00
h - > addNewerSlice ( QVector < MTPMessage > ( ) ) ;
2015-09-23 20:43:08 +03:00
h - > asChannelHistory ( ) - > insertJoinedMessage ( true ) ;
2016-04-13 00:31:28 +03:00
_history - > peerMessagesUpdated ( h - > peer - > id ) ;
2015-09-21 23:57:42 +03:00
}
}
} else {
2016-06-03 21:24:27 +03:00
deleteConversation ( peer , false ) ;
2015-08-07 15:11:50 +03:00
}
2014-05-30 12:53:19 +04:00
} else {
2015-09-21 23:57:42 +03:00
History * h = App : : history ( peer - > id ) ;
2015-06-15 20:19:24 +03:00
if ( ! h - > lastMsg ) {
2016-05-27 19:47:46 +03:00
h - > addNewMessage ( ( * v ) [ 0 ] , NewMessageLast ) ;
2015-09-21 23:57:42 +03:00
}
if ( ! h - > lastMsgDate . isNull ( ) & & h - > loadedAtBottom ( ) ) {
2015-09-23 20:43:08 +03:00
if ( peer - > isChannel ( ) & & peer - > asChannel ( ) - > inviter > 0 & & h - > lastMsgDate < = peer - > asChannel ( ) - > inviteDate & & peer - > asChannel ( ) - > amIn ( ) ) {
if ( UserData * from = App : : userLoaded ( peer - > asChannel ( ) - > inviter ) ) {
h - > asChannelHistory ( ) - > insertJoinedMessage ( true ) ;
2016-04-13 00:31:28 +03:00
_history - > peerMessagesUpdated ( h - > peer - > id ) ;
2015-09-21 23:57:42 +03:00
}
}
2014-05-30 12:53:19 +04:00
}
}
}
2015-09-09 10:46:31 +03:00
bool MainWidget : : sendMessageFail ( const RPCError & error ) {
2016-04-08 14:44:35 +04:00
if ( MTP : : isDefaultHandledError ( error ) ) return false ;
2015-09-09 10:46:31 +03:00
2016-04-08 14:44:35 +04:00
if ( error . type ( ) = = qstr ( " PEER_FLOOD " ) ) {
2017-01-01 20:45:20 +04:00
Ui : : show ( Box < InformBox > ( PeerFloodErrorText ( PeerFloodType : : Send ) ) ) ;
2015-09-09 10:46:31 +03:00
return true ;
}
2015-01-05 23:17:33 +03:00
return false ;
}
2015-02-03 18:02:46 +03:00
void MainWidget : : onCacheBackground ( ) {
2016-10-28 15:44:28 +03:00
if ( Window : : Theme : : Background ( ) - > tile ( ) ) {
2017-01-01 20:45:20 +04:00
auto & bg = Window : : Theme : : Background ( ) - > pixmapForTiled ( ) ;
auto result = QImage ( _willCacheFor . width ( ) * cIntRetinaFactor ( ) , _willCacheFor . height ( ) * cIntRetinaFactor ( ) , QImage : : Format_RGB32 ) ;
2015-02-04 10:59:20 +03:00
result . setDevicePixelRatio ( cRetinaFactor ( ) ) ;
2015-02-03 19:44:54 +03:00
{
QPainter p ( & result ) ;
2017-01-01 20:45:20 +04:00
auto left = 0 ;
auto top = 0 ;
auto right = _willCacheFor . width ( ) ;
auto bottom = _willCacheFor . height ( ) ;
auto w = bg . width ( ) / cRetinaFactor ( ) ;
auto h = bg . height ( ) / cRetinaFactor ( ) ;
auto sx = 0 ;
auto sy = 0 ;
auto cx = qCeil ( _willCacheFor . width ( ) / w ) ;
auto cy = qCeil ( _willCacheFor . height ( ) / h ) ;
2015-02-03 19:44:54 +03:00
for ( int i = sx ; i < cx ; + + i ) {
for ( int j = sy ; j < cy ; + + j ) {
p . drawPixmap ( QPointF ( i * w , j * h ) , bg ) ;
}
}
}
_cachedX = 0 ;
_cachedY = 0 ;
2016-07-13 20:34:57 +03:00
_cachedBackground = App : : pixmapFromImageInPlace ( std_ : : move ( result ) ) ;
2015-02-03 19:44:54 +03:00
} else {
2017-01-01 20:45:20 +04:00
auto & bg = Window : : Theme : : Background ( ) - > pixmap ( ) ;
2015-02-03 19:44:54 +03:00
QRect to , from ;
2016-12-23 16:21:01 +03:00
Window : : Theme : : ComputeBackgroundRects ( _willCacheFor , bg . size ( ) , to , from ) ;
2015-02-03 19:44:54 +03:00
_cachedX = to . x ( ) ;
_cachedY = to . y ( ) ;
2016-07-13 20:34:57 +03:00
_cachedBackground = App : : pixmapFromImageInPlace ( bg . toImage ( ) . copy ( from ) . scaled ( to . width ( ) * cIntRetinaFactor ( ) , to . height ( ) * cIntRetinaFactor ( ) , Qt : : IgnoreAspectRatio , Qt : : SmoothTransformation ) ) ;
2015-02-03 19:44:54 +03:00
_cachedBackground . setDevicePixelRatio ( cRetinaFactor ( ) ) ;
}
2015-02-03 18:02:46 +03:00
_cachedFor = _willCacheFor ;
}
2014-05-30 12:53:19 +04:00
void MainWidget : : forwardSelectedItems ( ) {
2016-04-13 00:31:28 +03:00
if ( _overview ) {
_overview - > onForwardSelected ( ) ;
2014-08-20 09:32:50 +04:00
} else {
2016-04-13 00:31:28 +03:00
_history - > onForwardSelected ( ) ;
2014-08-20 09:32:50 +04:00
}
2014-05-30 12:53:19 +04:00
}
2016-12-31 17:34:41 +04:00
void MainWidget : : confirmDeleteSelectedItems ( ) {
2016-04-13 00:31:28 +03:00
if ( _overview ) {
2016-12-31 17:34:41 +04:00
_overview - > confirmDeleteSelectedItems ( ) ;
2014-08-20 09:32:50 +04:00
} else {
2016-12-31 17:34:41 +04:00
_history - > confirmDeleteSelectedItems ( ) ;
2014-08-20 09:32:50 +04:00
}
2014-05-30 12:53:19 +04:00
}
void MainWidget : : clearSelectedItems ( ) {
2016-04-13 00:31:28 +03:00
if ( _overview ) {
_overview - > onClearSelected ( ) ;
2014-08-20 09:32:50 +04:00
} else {
2016-04-13 00:31:28 +03:00
_history - > onClearSelected ( ) ;
2014-08-20 09:32:50 +04:00
}
2014-05-30 12:53:19 +04:00
}
2016-04-09 22:45:55 +04:00
Dialogs : : IndexedList * MainWidget : : contactsList ( ) {
2016-04-13 00:31:28 +03:00
return _dialogs - > contactsList ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-04-09 22:45:55 +04:00
Dialogs : : IndexedList * MainWidget : : dialogsList ( ) {
2016-04-13 00:31:28 +03:00
return _dialogs - > dialogsList ( ) ;
2015-06-15 20:19:24 +03:00
}
2016-04-05 11:45:53 +04:00
namespace {
QString parseCommandFromMessage ( History * history , const QString & message ) {
if ( history - > peer - > id ! = peerFromUser ( ServiceUserId ) ) {
return QString ( ) ;
}
if ( message . size ( ) < 3 | | message . at ( 0 ) ! = ' * ' | | message . at ( message . size ( ) - 1 ) ! = ' * ' ) {
return QString ( ) ;
}
QString command = message . mid ( 1 , message . size ( ) - 2 ) ;
QStringList commands ;
commands . push_back ( qsl ( " new_version_text " ) ) ;
commands . push_back ( qsl ( " all_new_version_texts " ) ) ;
if ( commands . indexOf ( command ) < 0 ) {
return QString ( ) ;
}
return command ;
}
void executeParsedCommand ( const QString & command ) {
if ( command . isEmpty ( ) | | ! App : : wnd ( ) ) {
return ;
}
if ( command = = qsl ( " new_version_text " ) ) {
2016-12-13 10:59:57 +03:00
App : : wnd ( ) - > serviceNotificationLocal ( langNewVersionText ( ) ) ;
2016-04-05 11:45:53 +04:00
} else if ( command = = qsl ( " all_new_version_texts " ) ) {
for ( int i = 0 ; i < languageCount ; + + i ) {
2016-12-13 10:59:57 +03:00
App : : wnd ( ) - > serviceNotificationLocal ( langNewVersionTextForLang ( i ) ) ;
2016-04-05 11:45:53 +04:00
}
}
}
} // namespace
2016-04-30 20:04:14 +03:00
void MainWidget : : sendMessage ( const MessageToSend & message ) {
auto history = message . history ;
2016-05-05 19:04:17 +03:00
const auto & textWithTags = message . textWithTags ;
2015-08-30 17:57:21 +03:00
2016-06-03 15:45:33 +03:00
readServerHistory ( history ) ;
2016-04-30 20:04:14 +03:00
_history - > fastShowAtEnd ( history ) ;
if ( ! history | | ! _history - > canSendMessages ( history - > peer ) ) {
2015-10-23 18:06:56 +02:00
return ;
2015-08-30 17:57:21 +03:00
}
2015-08-24 13:53:04 +03:00
2016-05-05 19:04:17 +03:00
saveRecentHashtags ( textWithTags . text ) ;
2015-10-23 18:06:56 +02:00
2016-05-05 19:04:17 +03:00
EntitiesInText sendingEntities , leftEntities = entitiesFromTextTags ( textWithTags . tags ) ;
2016-04-30 20:04:14 +03:00
auto prepareFlags = itemTextOptions ( history , App : : self ( ) ) . flags ;
2016-05-05 19:04:17 +03:00
QString sendingText , leftText = prepareTextWithEntities ( textWithTags . text , prepareFlags , & leftEntities ) ;
2015-10-23 18:06:56 +02:00
2016-05-05 19:04:17 +03:00
QString command = parseCommandFromMessage ( history , textWithTags . text ) ;
2016-04-23 14:40:42 +03:00
HistoryItem * lastMessage = nullptr ;
2016-04-05 11:45:53 +04:00
2016-05-23 16:14:54 +03:00
MsgId replyTo = ( message . replyTo < 0 ) ? _history - > replyToId ( ) : message . replyTo ;
2016-04-05 11:45:53 +04:00
while ( command . isEmpty ( ) & & textSplit ( sendingText , sendingEntities , leftText , leftEntities , MaxMessageSize ) ) {
2016-04-30 20:04:14 +03:00
FullMsgId newId ( peerToChannel ( history - > peer - > id ) , clientMsgId ( ) ) ;
2016-03-24 13:12:18 +03:00
uint64 randomId = rand_value < uint64 > ( ) ;
2014-11-05 20:43:32 +03:00
2016-04-30 20:04:14 +03:00
trimTextWithEntities ( sendingText , & sendingEntities ) ;
2015-08-24 13:53:04 +03:00
2014-06-15 16:31:03 +04:00
App : : historyRegRandom ( randomId , newId ) ;
2016-04-30 20:04:14 +03:00
App : : historyRegSentData ( randomId , history - > peer - > id , sendingText ) ;
2014-07-04 15:12:54 +04:00
2014-11-05 20:43:32 +03:00
MTPstring msgText ( MTP_string ( sendingText ) ) ;
2016-04-30 20:04:14 +03:00
MTPDmessage : : Flags flags = newMessageFlags ( history - > peer ) | MTPDmessage : : Flag : : f_entities ; // unread, out
2016-03-19 19:55:15 +03:00
MTPmessages_SendMessage : : Flags sendFlags = 0 ;
2015-04-07 01:15:29 +03:00
if ( replyTo ) {
2016-03-19 19:55:15 +03:00
flags | = MTPDmessage : : Flag : : f_reply_to_msg_id ;
sendFlags | = MTPmessages_SendMessage : : Flag : : f_reply_to_msg_id ;
2015-04-07 01:15:29 +03:00
}
2015-04-08 02:03:32 +03:00
MTPMessageMedia media = MTP_messageMediaEmpty ( ) ;
2016-04-30 20:04:14 +03:00
if ( message . webPageId = = CancelledWebPageId ) {
2016-03-19 19:55:15 +03:00
sendFlags | = MTPmessages_SendMessage : : Flag : : f_no_webpage ;
2016-04-30 20:04:14 +03:00
} else if ( message . webPageId ) {
2016-09-27 16:37:18 +03:00
auto page = App : : webPage ( message . webPageId ) ;
2015-04-08 02:03:32 +03:00
media = MTP_messageMediaWebPage ( MTP_webPagePending ( MTP_long ( page - > id ) , MTP_int ( page - > pendingTill ) ) ) ;
2016-03-19 19:55:15 +03:00
flags | = MTPDmessage : : Flag : : f_media ;
2015-04-08 02:03:32 +03:00
}
2016-05-27 19:47:46 +03:00
bool channelPost = history - > peer - > isChannel ( ) & & ! history - > peer - > isMegagroup ( ) ;
2016-04-30 20:04:14 +03:00
bool showFromName = ! channelPost | | history - > peer - > asChannel ( ) - > addsSignature ( ) ;
bool silentPost = channelPost & & message . silent ;
2016-02-17 19:37:21 +03:00
if ( channelPost ) {
2016-03-19 19:55:15 +03:00
flags | = MTPDmessage : : Flag : : f_views ;
flags | = MTPDmessage : : Flag : : f_post ;
2016-02-17 19:37:21 +03:00
}
if ( showFromName ) {
2016-03-19 19:55:15 +03:00
flags | = MTPDmessage : : Flag : : f_from_id ;
2015-09-06 13:17:09 +03:00
}
2016-02-25 19:19:54 +03:00
if ( silentPost ) {
2016-03-19 19:55:15 +03:00
sendFlags | = MTPmessages_SendMessage : : Flag : : f_silent ;
2016-02-25 19:19:54 +03:00
}
2015-10-23 18:06:56 +02:00
MTPVector < MTPMessageEntity > localEntities = linksToMTP ( sendingEntities ) , sentEntities = linksToMTP ( sendingEntities , true ) ;
if ( ! sentEntities . c_vector ( ) . v . isEmpty ( ) ) {
2016-03-19 19:55:15 +03:00
sendFlags | = MTPmessages_SendMessage : : Flag : : f_entities ;
2015-10-23 18:06:56 +02:00
}
2016-06-03 21:24:27 +03:00
if ( message . clearDraft ) {
sendFlags | = MTPmessages_SendMessage : : Flag : : f_clear_draft ;
history - > clearCloudDraft ( ) ;
}
2016-04-30 20:04:14 +03:00
lastMessage = history - > addNewMessage ( MTP_message ( MTP_flags ( flags ) , MTP_int ( newId . msg ) , MTP_int ( showFromName ? MTP : : authedId ( ) : 0 ) , peerToMTP ( history - > peer - > id ) , MTPnullFwdHeader , MTPint ( ) , MTP_int ( replyTo ) , MTP_int ( unixtime ( ) ) , msgText , media , MTPnullMarkup , localEntities , MTP_int ( 1 ) , MTPint ( ) ) , NewMessageUnread ) ;
history - > sendRequestId = MTP : : send ( MTPmessages_SendMessage ( MTP_flags ( sendFlags ) , history - > peer - > input , MTP_int ( replyTo ) , msgText , MTP_long ( randomId ) , MTPnullMarkup , sentEntities ) , rpcDone ( & MainWidget : : sentUpdatesReceived , randomId ) , rpcFail ( & MainWidget : : sendMessageFail ) , 0 , 0 , history - > sendRequestId ) ;
2014-11-05 20:43:32 +03:00
}
2016-04-30 20:04:14 +03:00
history - > lastSentMsg = lastMessage ;
2016-04-23 14:40:42 +03:00
2016-05-27 19:47:46 +03:00
finishForwarding ( history , message . silent ) ;
2016-04-05 11:45:53 +04:00
executeParsedCommand ( command ) ;
2014-11-05 20:43:32 +03:00
}
2015-03-24 13:00:27 +03:00
void MainWidget : : saveRecentHashtags ( const QString & text ) {
bool found = false ;
QRegularExpressionMatch m ;
RecentHashtagPack recent ( cRecentWriteHashtags ( ) ) ;
for ( int32 i = 0 , next = 0 ; ( m = reHashtag ( ) . match ( text , i ) ) . hasMatch ( ) ; i = next ) {
i = m . capturedStart ( ) ;
next = m . capturedEnd ( ) ;
if ( m . hasMatch ( ) ) {
if ( ! m . capturedRef ( 1 ) . isEmpty ( ) ) {
+ + i ;
}
if ( ! m . capturedRef ( 2 ) . isEmpty ( ) ) {
- - next ;
}
}
if ( ! found & & cRecentWriteHashtags ( ) . isEmpty ( ) & & cRecentSearchHashtags ( ) . isEmpty ( ) ) {
2016-01-01 22:48:32 +08:00
Local : : readRecentHashtagsAndBots ( ) ;
2015-03-24 13:00:27 +03:00
recent = cRecentWriteHashtags ( ) ;
}
found = true ;
incrementRecentHashtag ( recent , text . mid ( i + 1 , next - i - 1 ) ) ;
}
if ( found ) {
cSetRecentWriteHashtags ( recent ) ;
2016-01-01 22:48:32 +08:00
Local : : writeRecentHashtagsAndBots ( ) ;
2015-03-24 13:00:27 +03:00
}
}
2016-06-03 15:45:33 +03:00
void MainWidget : : readServerHistory ( History * history , ReadServerHistoryChecks checks ) {
if ( ! history ) return ;
if ( checks = = ReadServerHistoryChecks : : OnlyIfUnread & & ! history - > unreadCount ( ) ) return ;
2015-12-31 23:27:21 +08:00
2016-06-03 15:45:33 +03:00
auto peer = history - > peer ;
MsgId upTo = history - > inboxRead ( 0 ) ;
if ( auto channel = peer - > asChannel ( ) ) {
if ( ! channel - > amIn ( ) ) {
return ; // no read request for channels that I didn't koin
}
2015-09-23 20:43:08 +03:00
}
2016-06-03 15:45:33 +03:00
if ( _readRequests . contains ( peer ) ) {
auto i = _readRequestsPending . find ( peer ) ;
2015-09-06 13:17:09 +03:00
if ( i = = _readRequestsPending . cend ( ) ) {
2016-06-03 15:45:33 +03:00
_readRequestsPending . insert ( peer , upTo ) ;
2015-09-06 13:17:09 +03:00
} else if ( i . value ( ) < upTo ) {
i . value ( ) = upTo ;
}
2016-06-03 15:45:33 +03:00
} else {
sendReadRequest ( peer , upTo ) ;
2015-09-06 13:17:09 +03:00
}
2014-06-15 16:31:03 +04:00
}
2016-06-03 15:45:33 +03:00
void MainWidget : : unreadCountChanged ( History * history ) {
_history - > unreadCountChanged ( history ) ;
}
2016-12-01 22:20:33 +03:00
TimeMs MainWidget : : animActiveTimeStart ( const HistoryItem * msg ) const {
2016-04-13 00:31:28 +03:00
return _history - > animActiveTimeStart ( msg ) ;
2014-07-04 15:12:54 +04:00
}
void MainWidget : : stopAnimActive ( ) {
2016-04-13 00:31:28 +03:00
_history - > stopAnimActive ( ) ;
2014-07-04 15:12:54 +04:00
}
2016-04-14 22:24:42 +03:00
void MainWidget : : sendBotCommand ( PeerData * peer , UserData * bot , const QString & cmd , MsgId replyTo ) {
_history - > sendBotCommand ( peer , bot , cmd , replyTo ) ;
2016-03-29 20:17:00 +03:00
}
2016-11-20 15:54:07 +03:00
void MainWidget : : hideSingleUseKeyboard ( PeerData * peer , MsgId replyTo ) {
_history - > hideSingleUseKeyboard ( peer , replyTo ) ;
}
2016-04-06 21:02:22 +04:00
void MainWidget : : app_sendBotCallback ( const HistoryMessageReplyMarkup : : Button * button , const HistoryItem * msg , int row , int col ) {
2016-04-13 00:31:28 +03:00
_history - > app_sendBotCallback ( button , msg , row , col ) ;
2015-06-10 18:54:24 +03:00
}
2016-01-01 02:34:56 +08:00
bool MainWidget : : insertBotCommand ( const QString & cmd , bool specialGif ) {
2016-04-13 00:31:28 +03:00
return _history - > insertBotCommand ( cmd , specialGif ) ;
2015-06-17 22:43:03 +03:00
}
2015-09-21 23:57:42 +03:00
void MainWidget : : searchMessages ( const QString & query , PeerData * inPeer ) {
2015-05-20 22:28:24 +03:00
App : : wnd ( ) - > hideMediaview ( ) ;
2016-04-13 00:31:28 +03:00
_dialogs - > searchMessages ( query , inPeer ) ;
2016-02-08 17:54:55 +03:00
if ( Adaptive : : OneColumn ( ) ) {
2015-12-13 14:36:08 +03:00
Ui : : showChatsList ( ) ;
2015-09-21 23:57:42 +03:00
} else {
2016-04-13 00:31:28 +03:00
_dialogs - > activate ( ) ;
2015-09-21 23:57:42 +03:00
}
2014-07-16 10:58:36 +04:00
}
2015-11-16 19:04:37 +03:00
bool MainWidget : : preloadOverview ( PeerData * peer , MediaOverviewType type ) {
MTPMessagesFilter filter = typeToMediaFilter ( type ) ;
if ( type = = OverviewCount ) return false ;
History * h = App : : history ( peer - > id ) ;
2016-06-02 16:02:55 +03:00
if ( h - > overviewCountLoaded ( type ) | | _overviewPreload [ type ] . contains ( peer ) ) {
2015-11-16 19:04:37 +03:00
return false ;
}
2016-03-19 19:55:15 +03:00
MTPmessages_Search : : Flags flags = 0 ;
_overviewPreload [ type ] . insert ( peer , MTP : : send ( MTPmessages_Search ( MTP_flags ( flags ) , peer - > input , MTP_string ( " " ) , filter , MTP_int ( 0 ) , MTP_int ( 0 ) , MTP_int ( 0 ) , MTP_int ( 0 ) , MTP_int ( 0 ) ) , rpcDone ( & MainWidget : : overviewPreloaded , peer ) , rpcFail ( & MainWidget : : overviewFailed , peer ) , 0 , 10 ) ) ;
2015-11-16 19:04:37 +03:00
return true ;
}
2014-08-15 15:19:32 +04:00
void MainWidget : : preloadOverviews ( PeerData * peer ) {
History * h = App : : history ( peer - > id ) ;
2015-11-16 19:04:37 +03:00
bool sending = false ;
2014-08-15 15:19:32 +04:00
for ( int32 i = 0 ; i < OverviewCount ; + + i ) {
2016-06-21 17:19:24 +03:00
auto type = MediaOverviewType ( i ) ;
if ( type ! = OverviewChatPhotos & & preloadOverview ( peer , type ) ) {
2015-11-16 19:04:37 +03:00
sending = true ;
2014-08-15 15:19:32 +04:00
}
}
2015-11-16 19:04:37 +03:00
if ( sending ) {
MTP : : sendAnything ( ) ;
2014-08-15 15:19:32 +04:00
}
}
void MainWidget : : overviewPreloaded ( PeerData * peer , const MTPmessages_Messages & result , mtpRequestId req ) {
MediaOverviewType type = OverviewCount ;
for ( int32 i = 0 ; i < OverviewCount ; + + i ) {
OverviewsPreload : : iterator j = _overviewPreload [ i ] . find ( peer ) ;
if ( j ! = _overviewPreload [ i ] . end ( ) & & j . value ( ) = = req ) {
type = MediaOverviewType ( i ) ;
_overviewPreload [ i ] . erase ( j ) ;
break ;
}
}
if ( type = = OverviewCount ) return ;
2015-11-18 16:11:56 +03:00
App : : history ( peer - > id ) - > overviewSliceDone ( type , result , true ) ;
2014-08-15 15:19:32 +04:00
2017-01-01 20:45:20 +04:00
Notify : : mediaOverviewUpdated ( peer , type ) ;
2014-08-15 15:19:32 +04:00
}
2017-01-01 20:45:20 +04:00
void MainWidget : : mediaOverviewUpdated ( const Notify : : PeerUpdate & update ) {
auto peer = update . peer ;
2016-04-13 00:31:28 +03:00
if ( _overview & & ( _overview - > peer ( ) = = peer | | _overview - > peer ( ) - > migrateFrom ( ) = = peer ) ) {
2017-01-01 20:45:20 +04:00
_overview - > mediaOverviewUpdated ( update ) ;
2014-08-21 16:18:56 +04:00
int32 mask = 0 ;
2015-11-16 19:04:37 +03:00
History * h = peer ? App : : historyLoaded ( ( peer - > migrateTo ( ) ? peer - > migrateTo ( ) : peer ) - > id ) : 0 ;
History * m = ( peer & & peer - > migrateFrom ( ) ) ? App : : historyLoaded ( peer - > migrateFrom ( ) - > id ) : 0 ;
2014-08-21 16:18:56 +04:00
if ( h ) {
for ( int32 i = 0 ; i < OverviewCount ; + + i ) {
2016-04-13 00:31:28 +03:00
if ( ! h - > overview [ i ] . isEmpty ( ) | | h - > overviewCount ( i ) > 0 | | i = = _overview - > type ( ) ) {
2014-08-21 16:18:56 +04:00
mask | = ( 1 < < i ) ;
2015-11-18 16:11:56 +03:00
} else if ( m & & ( ! m - > overview [ i ] . isEmpty ( ) | | m - > overviewCount ( i ) > 0 ) ) {
2015-11-16 19:04:37 +03:00
mask | = ( 1 < < i ) ;
2014-08-21 16:18:56 +04:00
}
}
}
if ( mask ! = _mediaTypeMask ) {
2016-10-26 19:43:13 +03:00
_mediaType - > clearActions ( ) ;
2014-08-21 16:18:56 +04:00
for ( int32 i = 0 ; i < OverviewCount ; + + i ) {
if ( mask & ( 1 < < i ) ) {
switch ( i ) {
2016-11-07 19:08:24 +03:00
case OverviewPhotos : _mediaType - > addAction ( lang ( lng_media_type_photos ) , this , SLOT ( onPhotosSelect ( ) ) ) ; break ;
case OverviewVideos : _mediaType - > addAction ( lang ( lng_media_type_videos ) , this , SLOT ( onVideosSelect ( ) ) ) ; break ;
case OverviewMusicFiles : _mediaType - > addAction ( lang ( lng_media_type_songs ) , this , SLOT ( onSongsSelect ( ) ) ) ; break ;
case OverviewFiles : _mediaType - > addAction ( lang ( lng_media_type_files ) , this , SLOT ( onDocumentsSelect ( ) ) ) ; break ;
case OverviewVoiceFiles : _mediaType - > addAction ( lang ( lng_media_type_audios ) , this , SLOT ( onAudiosSelect ( ) ) ) ; break ;
case OverviewLinks : _mediaType - > addAction ( lang ( lng_media_type_links ) , this , SLOT ( onLinksSelect ( ) ) ) ; break ;
2014-08-21 16:18:56 +04:00
}
}
}
_mediaTypeMask = mask ;
2016-04-13 00:31:28 +03:00
_mediaType - > move ( width ( ) - _mediaType - > width ( ) , st : : topBarHeight ) ;
_overview - > updateTopBarSelection ( ) ;
2014-08-21 16:18:56 +04:00
}
}
2014-08-15 15:19:32 +04:00
}
2014-08-20 23:13:00 +04:00
void MainWidget : : changingMsgId ( HistoryItem * row , MsgId newId ) {
2016-04-13 00:31:28 +03:00
if ( _overview ) _overview - > changingMsgId ( row , newId ) ;
2014-08-20 23:13:00 +04:00
}
2016-03-11 15:20:58 +03:00
void MainWidget : : itemEdited ( HistoryItem * item ) {
2016-04-13 00:31:28 +03:00
if ( _history - > peer ( ) = = item - > history ( ) - > peer | | ( _history - > peer ( ) & & _history - > peer ( ) = = item - > history ( ) - > peer - > migrateTo ( ) ) ) {
_history - > itemEdited ( item ) ;
2016-03-11 15:20:58 +03:00
}
}
2014-08-15 15:19:32 +04:00
bool MainWidget : : overviewFailed ( PeerData * peer , const RPCError & error , mtpRequestId req ) {
2016-04-08 14:44:35 +04:00
if ( MTP : : isDefaultHandledError ( error ) ) return false ;
2015-04-04 23:01:34 +03:00
2014-08-15 15:19:32 +04:00
MediaOverviewType type = OverviewCount ;
for ( int32 i = 0 ; i < OverviewCount ; + + i ) {
OverviewsPreload : : iterator j = _overviewPreload [ i ] . find ( peer ) ;
if ( j ! = _overviewPreload [ i ] . end ( ) & & j . value ( ) = = req ) {
_overviewPreload [ i ] . erase ( j ) ;
break ;
}
}
return true ;
}
void MainWidget : : loadMediaBack ( PeerData * peer , MediaOverviewType type , bool many ) {
if ( _overviewLoad [ type ] . constFind ( peer ) ! = _overviewLoad [ type ] . cend ( ) ) return ;
2015-11-18 16:11:56 +03:00
History * history = App : : history ( peer - > id ) ;
if ( history - > overviewLoaded ( type ) ) return ;
2014-08-15 15:19:32 +04:00
2015-11-18 16:11:56 +03:00
MsgId minId = history - > overviewMinId ( type ) ;
2015-12-23 14:13:08 +03:00
int32 limit = ( many | | history - > overview [ type ] . size ( ) > MediaOverviewStartPerPage ) ? SearchPerPage : MediaOverviewStartPerPage ;
2014-08-15 15:19:32 +04:00
MTPMessagesFilter filter = typeToMediaFilter ( type ) ;
if ( type = = OverviewCount ) return ;
2016-03-19 19:55:15 +03:00
MTPmessages_Search : : Flags flags = 0 ;
_overviewLoad [ type ] . insert ( peer , MTP : : send ( MTPmessages_Search ( MTP_flags ( flags ) , peer - > input , MTPstring ( ) , filter , MTP_int ( 0 ) , MTP_int ( 0 ) , MTP_int ( 0 ) , MTP_int ( minId ) , MTP_int ( limit ) ) , rpcDone ( & MainWidget : : overviewLoaded , history ) ) ) ;
2014-08-15 15:19:32 +04:00
}
2014-11-12 23:30:26 +03:00
void MainWidget : : checkLastUpdate ( bool afterSleep ) {
2016-12-01 22:20:33 +03:00
auto n = getms ( true ) ;
2014-11-12 23:30:26 +03:00
if ( _lastUpdateTime & & n > _lastUpdateTime + ( afterSleep ? NoUpdatesAfterSleepTimeout : NoUpdatesTimeout ) ) {
2015-04-16 17:59:42 +03:00
_lastUpdateTime = n ;
MTP : : ping ( ) ;
2014-11-12 23:30:26 +03:00
}
}
2015-11-18 16:11:56 +03:00
void MainWidget : : overviewLoaded ( History * history , const MTPmessages_Messages & result , mtpRequestId req ) {
2014-08-15 15:19:32 +04:00
OverviewsPreload : : iterator it ;
MediaOverviewType type = OverviewCount ;
for ( int32 i = 0 ; i < OverviewCount ; + + i ) {
2015-11-18 16:11:56 +03:00
it = _overviewLoad [ i ] . find ( history - > peer ) ;
2014-08-15 15:19:32 +04:00
if ( it ! = _overviewLoad [ i ] . cend ( ) ) {
type = MediaOverviewType ( i ) ;
_overviewLoad [ i ] . erase ( it ) ;
break ;
}
}
if ( type = = OverviewCount ) return ;
2015-11-18 16:11:56 +03:00
history - > overviewSliceDone ( type , result ) ;
2014-08-15 15:19:32 +04:00
2017-01-01 20:45:20 +04:00
Notify : : mediaOverviewUpdated ( history - > peer , type ) ;
2014-08-15 15:19:32 +04:00
}
2015-09-06 13:17:09 +03:00
void MainWidget : : sendReadRequest ( PeerData * peer , MsgId upTo ) {
if ( ! MTP : : authedId ( ) ) return ;
if ( peer - > isChannel ( ) ) {
2016-06-03 15:45:33 +03:00
_readRequests . insert ( peer , qMakePair ( MTP : : send ( MTPchannels_ReadHistory ( peer - > asChannel ( ) - > inputChannel , MTP_int ( upTo ) ) , rpcDone ( & MainWidget : : channelReadDone , peer ) , rpcFail ( & MainWidget : : readRequestFail , peer ) ) , upTo ) ) ;
2015-09-06 13:17:09 +03:00
} else {
2016-06-03 15:45:33 +03:00
_readRequests . insert ( peer , qMakePair ( MTP : : send ( MTPmessages_ReadHistory ( peer - > input , MTP_int ( upTo ) ) , rpcDone ( & MainWidget : : historyReadDone , peer ) , rpcFail ( & MainWidget : : readRequestFail , peer ) ) , upTo ) ) ;
2015-09-06 13:17:09 +03:00
}
}
2016-06-03 15:45:33 +03:00
void MainWidget : : channelReadDone ( PeerData * peer , const MTPBool & result ) {
2015-09-06 13:17:09 +03:00
readRequestDone ( peer ) ;
}
2016-06-03 15:45:33 +03:00
void MainWidget : : historyReadDone ( PeerData * peer , const MTPmessages_AffectedMessages & result ) {
2015-10-29 15:10:49 -04:00
messagesAffected ( peer , result ) ;
readRequestDone ( peer ) ;
2014-06-15 16:31:03 +04:00
}
2015-09-06 13:17:09 +03:00
bool MainWidget : : readRequestFail ( PeerData * peer , const RPCError & error ) {
2016-04-08 14:44:35 +04:00
if ( MTP : : isDefaultHandledError ( error ) ) return false ;
2015-09-06 13:17:09 +03:00
readRequestDone ( peer ) ;
return false ;
}
void MainWidget : : readRequestDone ( PeerData * peer ) {
_readRequests . remove ( peer ) ;
ReadRequestsPending : : iterator i = _readRequestsPending . find ( peer ) ;
if ( i ! = _readRequestsPending . cend ( ) ) {
sendReadRequest ( peer , i . value ( ) ) ;
_readRequestsPending . erase ( i ) ;
}
}
2015-09-07 10:52:37 +03:00
void MainWidget : : messagesAffected ( PeerData * peer , const MTPmessages_AffectedMessages & result ) {
2016-04-08 14:44:35 +04:00
const auto & d ( result . c_messages_affectedMessages ( ) ) ;
2015-09-07 10:52:37 +03:00
if ( peer & & peer - > isChannel ( ) ) {
2015-09-20 12:54:22 +03:00
if ( peer - > asChannel ( ) - > ptsUpdated ( d . vpts . v , d . vpts_count . v ) ) {
peer - > asChannel ( ) - > ptsApplySkippedUpdates ( ) ;
}
2015-09-07 10:52:37 +03:00
} else {
2015-09-20 12:54:22 +03:00
if ( ptsUpdated ( d . vpts . v , d . vpts_count . v ) ) {
ptsApplySkippedUpdates ( ) ;
}
2015-09-07 10:52:37 +03:00
}
2015-09-23 20:43:08 +03:00
if ( History * h = App : : historyLoaded ( peer ? peer - > id : 0 ) ) {
2015-09-19 12:13:21 +03:00
if ( ! h - > lastMsg ) {
checkPeerHistory ( peer ) ;
}
}
2015-03-19 12:18:19 +03:00
}
2016-07-05 17:48:36 +03:00
void MainWidget : : ui_showPeerHistoryAsync ( quint64 peerId , qint32 showAtMsgId , Ui : : ShowWay way ) {
Ui : : showPeerHistory ( peerId , showAtMsgId , way ) ;
2015-12-13 14:17:15 +03:00
}
2016-03-19 19:55:15 +03:00
void MainWidget : : ui_autoplayMediaInlineAsync ( qint32 channelId , qint32 msgId ) {
if ( HistoryItem * item = App : : histItemById ( channelId , msgId ) ) {
if ( HistoryMedia * media = item - > getMedia ( ) ) {
2016-04-10 18:53:01 +04:00
media - > playInline ( true ) ;
2016-03-19 19:55:15 +03:00
}
}
}
2016-09-23 19:04:26 +03:00
void MainWidget : : handleAudioUpdate ( const AudioMsgId & audioId ) {
2017-01-25 00:24:39 +03:00
using State = Media : : Player : : State ;
auto state = Media : : Player : : mixer ( ) - > currentState ( audioId . type ( ) ) ;
if ( state . id = = audioId & & state . state = = State : : StoppedAtStart ) {
state . state = State : : Stopped ;
2017-01-19 11:24:43 +03:00
Media : : Player : : mixer ( ) - > clearStoppedAtStart ( audioId ) ;
2015-07-01 00:07:05 +03:00
2016-09-21 14:44:20 +03:00
auto document = audioId . audio ( ) ;
auto filepath = document - > filepath ( DocumentData : : FilePathResolveSaveFromData ) ;
2016-03-16 14:54:37 +03:00
if ( ! filepath . isEmpty ( ) ) {
2016-06-29 18:21:21 +03:00
if ( documentIsValidMediaFile ( filepath ) ) {
psOpenFile ( filepath ) ;
}
2015-07-01 00:07:05 +03:00
}
}
2017-01-25 00:24:39 +03:00
if ( state . id = = audioId & & audioId . type ( ) = = AudioMsgId : : Type : : Song ) {
if ( ! Media : : Player : : IsStopped ( state . state ) & & state . state ! = State : : Finishing ) {
2017-01-19 11:24:43 +03:00
if ( ! _playerUsingPanel & & ! _player ) {
2016-10-18 18:19:13 +03:00
createPlayer ( ) ;
}
2016-11-04 11:23:50 +03:00
} else if ( _player & & _player - > isHidden ( ) & & ! _playerUsingPanel ) {
_player . destroyDelayed ( ) ;
_playerVolume . destroyDelayed ( ) ;
2015-07-03 11:47:16 +03:00
}
}
2016-09-21 14:44:20 +03:00
if ( auto item = App : : histItemById ( audioId . contextId ( ) ) ) {
Ui : : repaintHistoryItem ( item ) ;
}
if ( auto items = InlineBots : : Layout : : documentItems ( ) ) {
for ( auto item : items - > value ( audioId . audio ( ) ) ) {
Ui : : repaintInlineItem ( item ) ;
2016-04-10 22:18:26 +04:00
}
}
2014-09-04 11:33:44 +04:00
}
2016-10-12 22:34:25 +03:00
void MainWidget : : switchToPanelPlayer ( ) {
2016-10-14 20:10:15 +03:00
if ( _playerUsingPanel ) return ;
_playerUsingPanel = true ;
2016-10-12 22:34:25 +03:00
_player - > slideUp ( ) ;
_playerVolume . destroyDelayed ( ) ;
2016-10-14 20:10:15 +03:00
_playerPlaylist - > hideIgnoringEnterEvents ( ) ;
Media : : Player : : instance ( ) - > usePanelPlayer ( ) . notify ( true , true ) ;
2016-10-12 22:34:25 +03:00
}
void MainWidget : : switchToFixedPlayer ( ) {
2016-10-14 20:10:15 +03:00
if ( ! _playerUsingPanel ) return ;
_playerUsingPanel = false ;
2016-10-12 22:34:25 +03:00
if ( ! _player ) {
createPlayer ( ) ;
} else {
_player - > slideDown ( ) ;
if ( ! _playerVolume ) {
_playerVolume . create ( this ) ;
_player - > entity ( ) - > volumeWidgetCreated ( _playerVolume ) ;
updateMediaPlayerPosition ( ) ;
2016-04-14 19:08:36 +03:00
}
2015-07-03 11:47:16 +03:00
}
2016-10-14 20:10:15 +03:00
Media : : Player : : instance ( ) - > usePanelPlayer ( ) . notify ( false , true ) ;
_playerPanel - > hideIgnoringEnterEvents ( ) ;
2015-07-03 11:47:16 +03:00
}
2016-10-18 18:19:13 +03:00
void MainWidget : : closeBothPlayers ( ) {
2016-11-04 11:23:50 +03:00
if ( _playerUsingPanel ) {
_playerUsingPanel = false ;
_player . destroyDelayed ( ) ;
} else {
_player - > slideUp ( ) ;
}
2016-10-18 18:19:13 +03:00
_playerVolume . destroyDelayed ( ) ;
2017-01-19 11:24:43 +03:00
Media : : Player : : instance ( ) - > usePanelPlayer ( ) . notify ( false , true ) ;
2016-10-18 18:19:13 +03:00
_playerPanel - > hideIgnoringEnterEvents ( ) ;
_playerPlaylist - > hideIgnoringEnterEvents ( ) ;
2017-01-19 11:24:43 +03:00
Media : : Player : : instance ( ) - > stop ( ) ;
2016-10-22 17:35:37 +03:00
Shortcuts : : disableMediaShortcuts ( ) ;
2016-10-18 18:19:13 +03:00
}
2016-10-12 22:34:25 +03:00
void MainWidget : : createPlayer ( ) {
_player . create ( this , [ this ] { playerHeightUpdated ( ) ; } ) ;
2016-11-04 11:23:50 +03:00
_player - > entity ( ) - > setCloseCallback ( [ this ] { closeBothPlayers ( ) ; } ) ;
2016-10-12 22:34:25 +03:00
_playerVolume . create ( this ) ;
_player - > entity ( ) - > volumeWidgetCreated ( _playerVolume ) ;
orderWidgets ( ) ;
if ( _a_show . animating ( ) ) {
_player - > showFast ( ) ;
_player - > hide ( ) ;
} else {
_player - > hideFast ( ) ;
2016-11-04 11:23:50 +03:00
if ( _player ) {
_player - > slideDown ( ) ;
_playerHeight = _contentScrollAddToY = _player - > contentHeight ( ) ;
updateControlsGeometry ( ) ;
}
2016-10-12 22:34:25 +03:00
}
2016-10-22 17:35:37 +03:00
Shortcuts : : enableMediaShortcuts ( ) ;
2016-10-12 22:34:25 +03:00
}
void MainWidget : : playerHeightUpdated ( ) {
auto playerHeight = _player - > contentHeight ( ) ;
if ( playerHeight ! = _playerHeight ) {
_contentScrollAddToY + = playerHeight - _playerHeight ;
_playerHeight = playerHeight ;
updateControlsGeometry ( ) ;
}
2016-11-04 11:23:50 +03:00
if ( ! _playerHeight & & _player - > isHidden ( ) ) {
2017-01-25 00:24:39 +03:00
auto state = Media : : Player : : mixer ( ) - > currentState ( AudioMsgId : : Type : : Song ) ;
if ( state . id & & Media : : Player : : IsStopped ( state . state ) ) {
2016-11-04 11:23:50 +03:00
_playerVolume . destroyDelayed ( ) ;
_player . destroyDelayed ( ) ;
}
2016-10-12 22:34:25 +03:00
}
}
2015-12-31 03:09:20 +08:00
void MainWidget : : documentLoadProgress ( FileLoader * loader ) {
2016-09-23 19:04:26 +03:00
if ( auto mtpLoader = loader ? loader - > mtpLoader ( ) : nullptr ) {
documentLoadProgress ( App : : document ( mtpLoader - > objId ( ) ) ) ;
}
}
2015-12-31 03:09:20 +08:00
2016-09-23 19:04:26 +03:00
void MainWidget : : documentLoadProgress ( DocumentData * document ) {
2015-12-24 22:26:28 +03:00
if ( document - > loaded ( ) ) {
document - > performActionOnLoad ( ) ;
2014-05-30 12:53:19 +04:00
}
2015-12-24 22:26:28 +03:00
2016-09-23 19:04:26 +03:00
auto & items = App : : documentItems ( ) ;
auto i = items . constFind ( document ) ;
2014-05-30 12:53:19 +04:00
if ( i ! = items . cend ( ) ) {
2016-09-27 16:37:18 +03:00
for_const ( auto item , i . value ( ) ) {
Ui : : repaintHistoryItem ( item ) ;
2014-05-30 12:53:19 +04:00
}
}
2015-04-19 13:29:19 +03:00
App : : wnd ( ) - > documentUpdated ( document ) ;
2015-07-03 11:47:16 +03:00
2016-09-23 19:04:26 +03:00
if ( ! document - > loaded ( ) & & document - > song ( ) ) {
2017-01-19 11:24:43 +03:00
Media : : Player : : instance ( ) - > documentLoadProgress ( document ) ;
2015-07-03 11:47:16 +03:00
}
2014-05-30 12:53:19 +04:00
}
2015-12-31 03:09:20 +08:00
void MainWidget : : documentLoadFailed ( FileLoader * loader , bool started ) {
mtpFileLoader * l = loader ? loader - > mtpLoader ( ) : 0 ;
if ( ! l ) return ;
2016-12-13 20:07:56 +03:00
auto document = App : : document ( l - > objId ( ) ) ;
if ( started ) {
auto failedFileName = l - > fileName ( ) ;
Ui : : show ( Box < ConfirmBox > ( lang ( lng_download_finish_failed ) , base : : lambda_guarded ( this , [ this , document , failedFileName ] {
Ui : : hideLayer ( ) ;
if ( document ) document - > save ( failedFileName ) ;
} ) ) ) ;
} else {
Ui : : show ( Box < ConfirmBox > ( lang ( lng_download_path_failed ) , lang ( lng_download_path_settings ) , base : : lambda_guarded ( this , [ this ] {
Global : : SetDownloadPath ( QString ( ) ) ;
Global : : SetDownloadPathBookmark ( QByteArray ( ) ) ;
Ui : : show ( Box < DownloadPathBox > ( ) ) ;
Global : : RefDownloadPathChanged ( ) . notify ( ) ;
} ) ) ) ;
}
2015-03-19 12:18:19 +03:00
if ( document ) {
2015-12-24 22:26:28 +03:00
if ( document - > loading ( ) ) document - > cancel ( ) ;
2015-12-08 22:07:50 +03:00
document - > status = FileDownloadFailed ;
2015-03-19 12:18:19 +03:00
}
2014-05-30 12:53:19 +04:00
}
2015-12-31 13:34:43 +08:00
void MainWidget : : inlineResultLoadProgress ( FileLoader * loader ) {
2016-04-05 01:09:46 +04:00
//InlineBots::Result *result = InlineBots::resultFromLoader(loader);
2015-12-31 13:34:43 +08:00
//if (!result) return;
//result->loaded();
//Ui::repaintInlineItem();
}
void MainWidget : : inlineResultLoadFailed ( FileLoader * loader , bool started ) {
2016-04-05 01:09:46 +04:00
//InlineBots::Result *result = InlineBots::resultFromLoader(loader);
2015-12-31 13:34:43 +08:00
//if (!result) return;
//result->loaded();
//Ui::repaintInlineItem();
}
2016-02-12 21:18:32 +03:00
void MainWidget : : mediaMarkRead ( DocumentData * data ) {
2016-02-12 19:35:06 +03:00
const DocumentItems & items ( App : : documentItems ( ) ) ;
DocumentItems : : const_iterator i = items . constFind ( data ) ;
2015-04-30 16:53:36 +03:00
if ( i ! = items . cend ( ) ) {
mediaMarkRead ( i . value ( ) ) ;
}
}
void MainWidget : : mediaMarkRead ( const HistoryItemsMap & items ) {
QVector < MTPint > markedIds ;
markedIds . reserve ( items . size ( ) ) ;
2016-09-27 16:37:18 +03:00
for_const ( auto item , items ) {
if ( ! item - > out ( ) & & item - > isMediaUnread ( ) ) {
item - > markMediaRead ( ) ;
if ( item - > id > 0 ) {
markedIds . push_back ( MTP_int ( item - > id ) ) ;
2015-04-30 16:53:36 +03:00
}
}
}
if ( ! markedIds . isEmpty ( ) ) {
2015-09-07 10:52:37 +03:00
MTP : : send ( MTPmessages_ReadMessageContents ( MTP_vector < MTPint > ( markedIds ) ) , rpcDone ( & MainWidget : : messagesAffected , ( PeerData * ) 0 ) ) ;
2015-04-30 16:53:36 +03:00
}
}
2014-05-30 12:53:19 +04:00
void MainWidget : : updateOnlineDisplay ( ) {
2015-03-02 15:34:16 +03:00
if ( this ! = App : : main ( ) ) return ;
2016-08-17 18:14:08 +03:00
_history - > updateOnlineDisplay ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-11-28 18:45:07 +03:00
void MainWidget : : onSendFileConfirm ( const FileLoadResultPtr & file ) {
_history - > sendFileConfirmed ( file ) ;
2016-09-11 11:38:14 +03:00
}
bool MainWidget : : onSendSticker ( DocumentData * document ) {
return _history - > onStickerSend ( document ) ;
2014-05-30 12:53:19 +04:00
}
void MainWidget : : dialogsCancelled ( ) {
2015-07-17 22:17:37 +03:00
if ( _hider ) {
_hider - > startHide ( ) ;
noHider ( _hider ) ;
2014-05-30 12:53:19 +04:00
}
2016-04-13 00:31:28 +03:00
_history - > activate ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-12-13 10:59:57 +03:00
void MainWidget : : serviceNotification ( const TextWithEntities & message , const MTPMessageMedia & media , int32 date ) {
2016-05-20 19:01:06 +03:00
MTPDmessage : : Flags flags = MTPDmessage : : Flag : : f_entities | MTPDmessage : : Flag : : f_from_id | MTPDmessage_ClientFlag : : f_clientside_unread ;
2016-12-13 10:59:57 +03:00
QString sendingText , leftText = message . text ;
EntitiesInText sendingEntities , leftEntities = message . entities ;
HistoryItem * item = nullptr ;
2015-10-23 18:06:56 +02:00
while ( textSplit ( sendingText , sendingEntities , leftText , leftEntities , MaxMessageSize ) ) {
MTPVector < MTPMessageEntity > localEntities = linksToMTP ( sendingEntities ) ;
2016-12-13 10:59:57 +03:00
item = App : : histories ( ) . addNewMessage ( MTP_message ( MTP_flags ( flags ) , MTP_int ( clientMsgId ( ) ) , MTP_int ( ServiceUserId ) , MTP_peerUser ( MTP_int ( MTP : : authedId ( ) ) ) , MTPnullFwdHeader , MTPint ( ) , MTPint ( ) , MTP_int ( date ) , MTP_string ( sendingText ) , media , MTPnullMarkup , localEntities , MTPint ( ) , MTPint ( ) ) , NewMessageUnread ) ;
2015-02-20 18:41:54 +03:00
}
2014-12-12 19:27:03 +03:00
if ( item ) {
2016-04-13 00:31:28 +03:00
_history - > peerMessagesUpdated ( item - > history ( ) - > peer - > id ) ;
2014-12-12 19:27:03 +03:00
}
}
void MainWidget : : serviceHistoryDone ( const MTPmessages_Messages & msgs ) {
switch ( msgs . type ( ) ) {
2015-09-04 16:01:31 +03:00
case mtpc_messages_messages : {
2016-05-27 19:47:46 +03:00
auto & d ( msgs . c_messages_messages ( ) ) ;
2015-09-04 16:01:31 +03:00
App : : feedUsers ( d . vusers ) ;
App : : feedChats ( d . vchats ) ;
2015-09-20 11:55:41 +03:00
App : : feedMsgs ( d . vmessages , NewMessageLast ) ;
2015-09-04 16:01:31 +03:00
} break ;
case mtpc_messages_messagesSlice : {
2016-05-27 19:47:46 +03:00
auto & d ( msgs . c_messages_messagesSlice ( ) ) ;
2015-09-04 16:01:31 +03:00
App : : feedUsers ( d . vusers ) ;
App : : feedChats ( d . vchats ) ;
2015-09-20 11:55:41 +03:00
App : : feedMsgs ( d . vmessages , NewMessageLast ) ;
2015-09-04 16:01:31 +03:00
} break ;
2014-12-12 19:27:03 +03:00
2015-09-04 16:01:31 +03:00
case mtpc_messages_channelMessages : {
2016-05-27 19:47:46 +03:00
auto & d ( msgs . c_messages_channelMessages ( ) ) ;
2015-09-19 12:13:21 +03:00
LOG ( ( " API Error: received messages.channelMessages! (MainWidget::serviceHistoryDone) " ) ) ;
2015-09-04 16:01:31 +03:00
App : : feedUsers ( d . vusers ) ;
App : : feedChats ( d . vchats ) ;
2015-09-20 11:55:41 +03:00
App : : feedMsgs ( d . vmessages , NewMessageLast ) ;
2015-09-04 16:01:31 +03:00
} break ;
2014-12-12 19:27:03 +03:00
}
App : : wnd ( ) - > showDelayedServiceMsgs ( ) ;
}
bool MainWidget : : serviceHistoryFail ( const RPCError & error ) {
2016-04-08 14:44:35 +04:00
if ( MTP : : isDefaultHandledError ( error ) ) return false ;
2015-04-04 23:01:34 +03:00
2014-12-12 19:27:03 +03:00
App : : wnd ( ) - > showDelayedServiceMsgs ( ) ;
return false ;
}
2015-01-26 16:04:41 +03:00
bool MainWidget : : isIdle ( ) const {
return _isIdle ;
}
2015-02-03 18:02:46 +03:00
void MainWidget : : clearCachedBackground ( ) {
_cachedBackground = QPixmap ( ) ;
_cacheBackgroundTimer . stop ( ) ;
2016-08-26 22:49:18 -06:00
update ( ) ;
2015-02-03 18:02:46 +03:00
}
QPixmap MainWidget : : cachedBackground ( const QRect & forRect , int & x , int & y ) {
if ( ! _cachedBackground . isNull ( ) & & forRect = = _cachedFor ) {
x = _cachedX ;
y = _cachedY ;
return _cachedBackground ;
}
if ( _willCacheFor ! = forRect | | ! _cacheBackgroundTimer . isActive ( ) ) {
_willCacheFor = forRect ;
_cacheBackgroundTimer . start ( CacheBackgroundTimeout ) ;
}
return QPixmap ( ) ;
}
void MainWidget : : updateScrollColors ( ) {
2016-04-13 00:31:28 +03:00
_history - > updateScrollColors ( ) ;
2015-02-03 18:02:46 +03:00
}
void MainWidget : : setChatBackground ( const App : : WallPaper & wp ) {
2016-04-13 00:31:28 +03:00
_background = std_ : : make_unique < App : : WallPaper > ( wp ) ;
2015-12-24 22:26:28 +03:00
_background - > full - > loadEvenCancelled ( ) ;
2015-02-03 18:02:46 +03:00
checkChatBackground ( ) ;
}
bool MainWidget : : chatBackgroundLoading ( ) {
2016-06-22 16:39:54 +03:00
return ( _background ! = nullptr ) ;
}
float64 MainWidget : : chatBackgroundProgress ( ) const {
if ( _background ) {
return _background - > full - > progress ( ) ;
}
return 1. ;
2015-02-03 18:02:46 +03:00
}
void MainWidget : : checkChatBackground ( ) {
if ( _background ) {
if ( _background - > full - > loaded ( ) ) {
if ( _background - > full - > isNull ( ) ) {
2016-10-28 15:44:28 +03:00
Window : : Theme : : Background ( ) - > setImage ( Window : : Theme : : kDefaultBackground ) ;
2016-11-07 18:24:28 +03:00
} else if ( false
| | _background - > id = = Window : : Theme : : kInitialBackground
| | _background - > id = = Window : : Theme : : kDefaultBackground ) {
2016-10-28 15:44:28 +03:00
Window : : Theme : : Background ( ) - > setImage ( _background - > id ) ;
2015-02-03 18:02:46 +03:00
} else {
2016-10-28 15:44:28 +03:00
Window : : Theme : : Background ( ) - > setImage ( _background - > id , _background - > full - > pix ( ) . toImage ( ) ) ;
2015-02-03 18:02:46 +03:00
}
2016-04-13 00:31:28 +03:00
_background = nullptr ;
2015-02-03 18:02:46 +03:00
QTimer : : singleShot ( 0 , this , SLOT ( update ( ) ) ) ;
}
}
}
ImagePtr MainWidget : : newBackgroundThumb ( ) {
return _background ? _background - > thumb : ImagePtr ( ) ;
}
2015-03-19 12:18:19 +03:00
ApiWrap * MainWidget : : api ( ) {
2016-04-13 00:31:28 +03:00
return _api . get ( ) ;
2015-03-19 12:18:19 +03:00
}
2016-03-10 13:15:21 +03:00
void MainWidget : : messageDataReceived ( ChannelData * channel , MsgId msgId ) {
2016-04-13 00:31:28 +03:00
_history - > messageDataReceived ( channel , msgId ) ;
2015-03-19 12:18:19 +03:00
}
2015-11-24 19:19:18 +03:00
void MainWidget : : updateBotKeyboard ( History * h ) {
2016-04-13 00:31:28 +03:00
_history - > updateBotKeyboard ( h ) ;
2015-06-18 20:24:54 +03:00
}
2015-03-24 13:00:27 +03:00
void MainWidget : : pushReplyReturn ( HistoryItem * item ) {
2016-04-13 00:31:28 +03:00
_history - > pushReplyReturn ( item ) ;
2015-03-24 13:00:27 +03:00
}
2014-05-30 12:53:19 +04:00
void MainWidget : : setInnerFocus ( ) {
2016-04-13 00:31:28 +03:00
if ( _hider | | ! _history - > peer ( ) ) {
2015-07-17 22:17:37 +03:00
if ( _hider & & _hider - > wasOffered ( ) ) {
_hider - > setFocus ( ) ;
2016-12-13 20:07:56 +03:00
} else if ( ! _hider & & _overview ) {
2016-04-13 00:31:28 +03:00
_overview - > activate ( ) ;
2016-12-13 20:07:56 +03:00
} else if ( ! _hider & & _wideSection ) {
2016-05-19 15:03:51 +03:00
_wideSection - > setInnerFocus ( ) ;
2014-05-30 12:53:19 +04:00
} else {
2015-07-17 22:17:37 +03:00
dialogsActivate ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-04-13 00:31:28 +03:00
} else if ( _overview ) {
_overview - > activate ( ) ;
2016-05-19 15:03:51 +03:00
} else if ( _wideSection ) {
_wideSection - > setInnerFocus ( ) ;
2014-05-30 12:53:19 +04:00
} else {
2016-04-13 00:31:28 +03:00
_history - > setInnerFocus ( ) ;
2014-05-30 12:53:19 +04:00
}
}
2015-09-21 23:57:42 +03:00
void MainWidget : : scheduleViewIncrement ( HistoryItem * item ) {
PeerData * peer = item - > history ( ) - > peer ;
ViewsIncrement : : iterator i = _viewsIncremented . find ( peer ) ;
if ( i ! = _viewsIncremented . cend ( ) ) {
if ( i . value ( ) . contains ( item - > id ) ) return ;
} else {
i = _viewsIncremented . insert ( peer , ViewsIncrementMap ( ) ) ;
}
i . value ( ) . insert ( item - > id , true ) ;
ViewsIncrement : : iterator j = _viewsToIncrement . find ( peer ) ;
if ( j = = _viewsToIncrement . cend ( ) ) {
j = _viewsToIncrement . insert ( peer , ViewsIncrementMap ( ) ) ;
_viewsIncrementTimer . start ( SendViewsTimeout ) ;
}
j . value ( ) . insert ( item - > id , true ) ;
}
2016-12-20 16:03:51 +03:00
void MainWidget : : fillPeerMenu ( PeerData * peer , base : : lambda < QAction * ( const QString & text , base : : lambda < void ( ) > & & handler ) > & & callback , bool pinToggle ) {
if ( pinToggle ) {
auto isPinned = false ;
if ( auto history = App : : historyLoaded ( peer ) ) {
isPinned = history - > isPinnedDialog ( ) ;
}
auto pinSubscription = MakeShared < base : : Subscription > ( ) ;
auto pinAction = callback ( lang ( isPinned ? lng_context_unpin_from_top : lng_context_pin_to_top ) , [ peer , pinSubscription ] {
auto history = App : : history ( peer ) ;
auto isPinned = ! history - > isPinnedDialog ( ) ;
2017-01-02 21:11:49 +04:00
if ( isPinned & & App : : histories ( ) . pinnedCount ( ) > = Global : : PinnedDialogsCountMax ( ) ) {
Ui : : show ( Box < InformBox > ( lng_error_pinned_max ( lt_count , Global : : PinnedDialogsCountMax ( ) ) ) ) ;
return ;
}
2016-12-20 16:03:51 +03:00
history - > setPinnedDialog ( isPinned ) ;
auto flags = MTPmessages_ToggleDialogPin : : Flags ( 0 ) ;
if ( isPinned ) {
flags | = MTPmessages_ToggleDialogPin : : Flag : : f_pinned ;
2016-12-13 10:59:57 +03:00
}
2016-12-20 16:03:51 +03:00
MTP : : send ( MTPmessages_ToggleDialogPin ( MTP_flags ( flags ) , peer - > input ) ) ;
if ( isPinned ) {
if ( auto main = App : : main ( ) ) {
main - > dialogsToUp ( ) ;
}
}
} ) ;
auto pinChangedHandler = Notify : : PeerUpdatedHandler ( Notify : : PeerUpdate : : Flag : : PinnedChanged , [ pinAction , peer ] ( const Notify : : PeerUpdate & update ) {
if ( update . peer ! = peer ) return ;
pinAction - > setText ( lang ( App : : history ( peer ) - > isPinnedDialog ( ) ? lng_context_unpin_from_top : lng_context_pin_to_top ) ) ;
} ) ;
* pinSubscription = Notify : : PeerUpdated ( ) . add_subscription ( std_ : : move ( pinChangedHandler ) ) ;
}
2016-11-05 11:36:24 +03:00
callback ( lang ( ( peer - > isChat ( ) | | peer - > isMegagroup ( ) ) ? lng_context_view_group : ( peer - > isUser ( ) ? lng_context_view_profile : lng_context_view_channel ) ) , [ peer ] {
Ui : : showPeerProfile ( peer ) ;
} ) ;
auto muteSubscription = MakeShared < base : : Subscription > ( ) ;
auto muteAction = callback ( lang ( peer - > isMuted ( ) ? lng_enable_notifications_from_tray : lng_disable_notifications_from_tray ) , [ peer , muteSubscription ] {
App : : main ( ) - > updateNotifySetting ( peer , peer - > isMuted ( ) ? NotifySettingSetNotify : NotifySettingSetMuted ) ;
} ) ;
auto muteChangedHandler = Notify : : PeerUpdatedHandler ( Notify : : PeerUpdate : : Flag : : NotificationsEnabled , [ muteAction , peer ] ( const Notify : : PeerUpdate & update ) {
if ( update . peer ! = peer ) return ;
muteAction - > setText ( lang ( peer - > isMuted ( ) ? lng_enable_notifications_from_tray : lng_disable_notifications_from_tray ) ) ;
} ) ;
* muteSubscription = Notify : : PeerUpdated ( ) . add_subscription ( std_ : : move ( muteChangedHandler ) ) ;
callback ( lang ( lng_profile_search_messages ) , [ peer ] {
App : : main ( ) - > searchInPeer ( peer ) ;
} ) ;
auto clearHistoryHandler = [ peer ] {
2016-12-13 20:07:56 +03:00
auto text = peer - > isUser ( ) ? lng_sure_delete_history ( lt_contact , peer - > name ) : lng_sure_delete_group_history ( lt_group , peer - > name ) ;
Ui : : show ( Box < ConfirmBox > ( text , lang ( lng_box_delete ) , st : : attentionBoxButton , [ peer ] {
2016-11-05 11:36:24 +03:00
if ( ! App : : main ( ) ) return ;
Ui : : hideLayer ( ) ;
App : : main ( ) - > clearHistory ( peer ) ;
2016-12-13 20:07:56 +03:00
} ) ) ;
2016-11-05 11:36:24 +03:00
} ;
auto deleteAndLeaveHandler = [ peer ] {
auto warningText = peer - > isUser ( ) ? lng_sure_delete_history ( lt_contact , peer - > name ) :
peer - > isChat ( ) ? lng_sure_delete_and_exit ( lt_group , peer - > name ) :
lang ( peer - > isMegagroup ( ) ? lng_sure_leave_group : lng_sure_leave_channel ) ;
auto confirmText = lang ( peer - > isUser ( ) ? lng_box_delete : lng_box_leave ) ;
auto & confirmStyle = peer - > isChannel ( ) ? st : : defaultBoxButton : st : : attentionBoxButton ;
2016-12-13 20:07:56 +03:00
Ui : : show ( Box < ConfirmBox > ( warningText , confirmText , confirmStyle , [ peer ] {
2016-11-05 11:36:24 +03:00
if ( ! App : : main ( ) ) return ;
Ui : : hideLayer ( ) ;
Ui : : showChatsList ( ) ;
if ( peer - > isUser ( ) ) {
App : : main ( ) - > deleteConversation ( peer ) ;
} else if ( peer - > isChat ( ) ) {
MTP : : send ( MTPmessages_DeleteChatUser ( peer - > asChat ( ) - > inputChat , App : : self ( ) - > inputUser ) , App : : main ( ) - > rpcDone ( & MainWidget : : deleteHistoryAfterLeave , peer ) , App : : main ( ) - > rpcFail ( & MainWidget : : leaveChatFailed , peer ) ) ;
} else if ( peer - > isChannel ( ) ) {
if ( peer - > migrateFrom ( ) ) {
App : : main ( ) - > deleteConversation ( peer - > migrateFrom ( ) ) ;
}
MTP : : send ( MTPchannels_LeaveChannel ( peer - > asChannel ( ) - > inputChannel ) , App : : main ( ) - > rpcDone ( & MainWidget : : sentUpdatesReceived ) ) ;
}
2016-12-13 20:07:56 +03:00
} ) ) ;
2016-11-05 11:36:24 +03:00
} ;
if ( auto user = peer - > asUser ( ) ) {
callback ( lang ( lng_profile_delete_conversation ) , std_ : : move ( deleteAndLeaveHandler ) ) ;
2016-11-20 15:54:07 +03:00
callback ( lang ( lng_profile_clear_history ) , std_ : : move ( clearHistoryHandler ) ) ;
2017-01-16 16:27:11 +03:00
if ( ! user - > isInaccessible ( ) & & user ! = App : : self ( ) ) {
2016-11-05 11:36:24 +03:00
auto blockSubscription = MakeShared < base : : Subscription > ( ) ;
auto blockAction = callback ( lang ( user - > isBlocked ( ) ? ( user - > botInfo ? lng_profile_unblock_bot : lng_profile_unblock_user ) : ( user - > botInfo ? lng_profile_block_bot : lng_profile_block_user ) ) , [ user , blockSubscription ] {
auto willBeBlocked = ! user - > isBlocked ( ) ;
auto handler = : : rpcDone ( [ user , willBeBlocked ] ( const MTPBool & result ) {
user - > setBlockStatus ( willBeBlocked ? UserData : : BlockStatus : : Blocked : UserData : : BlockStatus : : NotBlocked ) ;
emit App : : main ( ) - > peerUpdated ( user ) ;
} ) ;
if ( willBeBlocked ) {
MTP : : send ( MTPcontacts_Block ( user - > inputUser ) , std_ : : move ( handler ) ) ;
} else {
MTP : : send ( MTPcontacts_Unblock ( user - > inputUser ) , std_ : : move ( handler ) ) ;
}
} ) ;
auto blockChangedHandler = Notify : : PeerUpdatedHandler ( Notify : : PeerUpdate : : Flag : : UserIsBlocked , [ blockAction , peer ] ( const Notify : : PeerUpdate & update ) {
if ( update . peer ! = peer ) return ;
blockAction - > setText ( lang ( peer - > asUser ( ) - > isBlocked ( ) ? ( peer - > asUser ( ) - > botInfo ? lng_profile_unblock_bot : lng_profile_unblock_user ) : ( peer - > asUser ( ) - > botInfo ? lng_profile_block_bot : lng_profile_block_user ) ) ) ;
} ) ;
* blockSubscription = Notify : : PeerUpdated ( ) . add_subscription ( std_ : : move ( blockChangedHandler ) ) ;
if ( user - > blockStatus ( ) = = UserData : : BlockStatus : : Unknown ) {
App : : api ( ) - > requestFullPeer ( user ) ;
}
}
} else if ( peer - > isChat ( ) ) {
callback ( lang ( lng_profile_clear_and_exit ) , std_ : : move ( deleteAndLeaveHandler ) ) ;
2016-11-21 19:24:23 +03:00
callback ( lang ( lng_profile_clear_history ) , std_ : : move ( clearHistoryHandler ) ) ;
2016-11-05 11:36:24 +03:00
} else if ( peer - > isChannel ( ) & & peer - > asChannel ( ) - > amIn ( ) & & ! peer - > asChannel ( ) - > amCreator ( ) ) {
callback ( lang ( peer - > isMegagroup ( ) ? lng_profile_leave_group : lng_profile_leave_channel ) , std_ : : move ( deleteAndLeaveHandler ) ) ;
}
}
2015-09-21 23:57:42 +03:00
void MainWidget : : onViewsIncrement ( ) {
2016-03-15 21:08:17 +03:00
if ( ! App : : main ( ) | | ! MTP : : authedId ( ) ) return ;
2015-09-21 23:57:42 +03:00
for ( ViewsIncrement : : iterator i = _viewsToIncrement . begin ( ) ; i ! = _viewsToIncrement . cend ( ) ; ) {
if ( _viewsIncrementRequests . contains ( i . key ( ) ) ) {
+ + i ;
continue ;
}
QVector < MTPint > ids ;
ids . reserve ( i . value ( ) . size ( ) ) ;
for ( ViewsIncrementMap : : const_iterator j = i . value ( ) . cbegin ( ) , end = i . value ( ) . cend ( ) ; j ! = end ; + + j ) {
ids . push_back ( MTP_int ( j . key ( ) ) ) ;
}
mtpRequestId req = MTP : : send ( MTPmessages_GetMessagesViews ( i . key ( ) - > input , MTP_vector < MTPint > ( ids ) , MTP_bool ( true ) ) , rpcDone ( & MainWidget : : viewsIncrementDone , ids ) , rpcFail ( & MainWidget : : viewsIncrementFail ) , 0 , 5 ) ;
_viewsIncrementRequests . insert ( i . key ( ) , req ) ;
i = _viewsToIncrement . erase ( i ) ;
}
}
void MainWidget : : viewsIncrementDone ( QVector < MTPint > ids , const MTPVector < MTPint > & result , mtpRequestId req ) {
2016-04-08 14:44:35 +04:00
const auto & v ( result . c_vector ( ) . v ) ;
2015-09-21 23:57:42 +03:00
if ( ids . size ( ) = = v . size ( ) ) {
for ( ViewsIncrementRequests : : iterator i = _viewsIncrementRequests . begin ( ) ; i ! = _viewsIncrementRequests . cend ( ) ; + + i ) {
if ( i . value ( ) = = req ) {
PeerData * peer = i . key ( ) ;
ChannelId channel = peerToChannel ( peer - > id ) ;
for ( int32 j = 0 , l = ids . size ( ) ; j < l ; + + j ) {
if ( HistoryItem * item = App : : histItemById ( channel , ids . at ( j ) . v ) ) {
item - > setViewsCount ( v . at ( j ) . v ) ;
}
}
_viewsIncrementRequests . erase ( i ) ;
break ;
}
}
}
if ( ! _viewsToIncrement . isEmpty ( ) & & ! _viewsIncrementTimer . isActive ( ) ) {
_viewsIncrementTimer . start ( SendViewsTimeout ) ;
}
}
bool MainWidget : : viewsIncrementFail ( const RPCError & error , mtpRequestId req ) {
2016-04-08 14:44:35 +04:00
if ( MTP : : isDefaultHandledError ( error ) ) return false ;
2015-09-21 23:57:42 +03:00
for ( ViewsIncrementRequests : : iterator i = _viewsIncrementRequests . begin ( ) ; i ! = _viewsIncrementRequests . cend ( ) ; + + i ) {
if ( i . value ( ) = = req ) {
_viewsIncrementRequests . erase ( i ) ;
break ;
}
}
if ( ! _viewsToIncrement . isEmpty ( ) & & ! _viewsIncrementTimer . isActive ( ) ) {
_viewsIncrementTimer . start ( SendViewsTimeout ) ;
}
return false ;
}
void MainWidget : : createDialog ( History * history ) {
2016-04-13 00:31:28 +03:00
_dialogs - > createDialog ( history ) ;
2014-05-30 12:53:19 +04:00
}
2015-07-17 22:17:37 +03:00
void MainWidget : : choosePeer ( PeerId peerId , MsgId showAtMsgId ) {
if ( selectingPeer ( ) ) {
offerPeer ( peerId ) ;
} else {
2015-12-13 14:36:08 +03:00
Ui : : showPeerHistory ( peerId , showAtMsgId ) ;
2015-07-17 22:17:37 +03:00
}
}
void MainWidget : : clearBotStartToken ( PeerData * peer ) {
2015-09-03 13:48:40 +03:00
if ( peer & & peer - > isUser ( ) & & peer - > asUser ( ) - > botInfo ) {
2015-07-17 22:17:37 +03:00
peer - > asUser ( ) - > botInfo - > startToken = QString ( ) ;
2014-05-30 12:53:19 +04:00
}
2015-07-17 22:17:37 +03:00
}
2015-09-07 18:53:46 +03:00
void MainWidget : : contactsReceived ( ) {
2016-04-13 00:31:28 +03:00
_history - > contactsReceived ( ) ;
2015-09-07 18:53:46 +03:00
}
2015-09-12 22:00:56 +03:00
void MainWidget : : updateAfterDrag ( ) {
2016-04-13 00:31:28 +03:00
if ( _overview ) {
_overview - > updateAfterDrag ( ) ;
2015-09-12 22:00:56 +03:00
} else {
2016-04-13 00:31:28 +03:00
_history - > updateAfterDrag ( ) ;
2015-09-12 22:00:56 +03:00
}
}
2015-09-16 16:04:08 +03:00
void MainWidget : : ctrlEnterSubmitUpdated ( ) {
2016-04-13 00:31:28 +03:00
_history - > updateFieldSubmitSettings ( ) ;
2015-09-16 16:04:08 +03:00
}
2016-07-05 17:48:36 +03:00
void MainWidget : : ui_showPeerHistory ( quint64 peerId , qint32 showAtMsgId , Ui : : ShowWay way ) {
2017-01-14 21:50:16 +03:00
if ( auto peer = App : : peerLoaded ( peerId ) ) {
2015-11-13 18:14:33 +03:00
if ( peer - > migrateTo ( ) ) {
2016-03-23 16:21:26 +03:00
peer = peer - > migrateTo ( ) ;
peerId = peer - > id ;
2015-11-13 18:14:33 +03:00
if ( showAtMsgId > 0 ) showAtMsgId = - showAtMsgId ;
}
2016-03-23 16:21:26 +03:00
QString restriction = peer - > restrictionReason ( ) ;
if ( ! restriction . isEmpty ( ) ) {
Ui : : showChatsList ( ) ;
2016-12-13 20:07:56 +03:00
Ui : : show ( Box < InformBox > ( restriction ) ) ;
2016-03-23 16:21:26 +03:00
return ;
}
2015-11-13 18:14:33 +03:00
}
2016-07-05 17:48:36 +03:00
2017-01-14 21:50:16 +03:00
Global : : RefDialogsListFocused ( ) . set ( false , true ) ;
_a_dialogsWidth . finish ( ) ;
2016-07-05 17:48:36 +03:00
bool back = ( way = = Ui : : ShowWay : : Backward | | ! peerId ) ;
bool foundInStack = ! peerId ;
if ( foundInStack | | ( way = = Ui : : ShowWay : : ClearStack ) ) {
for_const ( auto & item , _stack ) {
clearBotStartToken ( item - > peer ) ;
}
_stack . clear ( ) ;
} else {
for ( int i = 0 , s = _stack . size ( ) ; i < s ; + + i ) {
if ( _stack . at ( i ) - > type ( ) = = HistoryStackItem & & _stack . at ( i ) - > peer - > id = = peerId ) {
foundInStack = true ;
2016-10-20 12:46:16 +03:00
while ( _stack . size ( ) > i + 1 ) {
2016-07-05 17:48:36 +03:00
clearBotStartToken ( _stack . back ( ) - > peer ) ;
_stack . pop_back ( ) ;
}
2016-10-20 12:46:16 +03:00
_stack . pop_back ( ) ;
2016-07-05 17:48:36 +03:00
if ( ! back ) {
back = true ;
}
break ;
}
}
2016-09-03 12:35:12 -04:00
if ( auto historyPeer = _history - > peer ( ) ) {
if ( way = = Ui : : ShowWay : : Forward & & historyPeer - > id = = peerId ) {
way = Ui : : ShowWay : : ClearStack ;
}
}
2016-07-05 17:48:36 +03:00
}
2016-09-13 13:03:21 +03:00
dlgUpdated ( ) ;
2016-07-05 17:48:36 +03:00
if ( back | | ( way = = Ui : : ShowWay : : ClearStack ) ) {
_peerInStack = nullptr ;
_msgIdInStack = 0 ;
} else {
saveSectionInStack ( ) ;
2015-07-17 22:17:37 +03:00
}
2016-09-13 13:03:21 +03:00
dlgUpdated ( ) ;
2015-07-17 22:17:37 +03:00
2017-01-14 21:50:16 +03:00
auto wasActivePeer = activePeer ( ) ;
2015-09-20 11:55:41 +03:00
2016-08-17 18:14:08 +03:00
Ui : : hideSettingsAndLayer ( ) ;
2015-07-17 22:17:37 +03:00
if ( _hider ) {
_hider - > startHide ( ) ;
2016-04-13 00:31:28 +03:00
_hider = nullptr ;
2015-07-17 22:17:37 +03:00
}
2017-01-14 21:50:16 +03:00
auto animatedShow = [ this , peerId , back , way ] {
if ( _a_show . animating ( ) | | App : : passcoded ( ) ) {
return false ;
}
if ( ! peerId ) {
if ( Adaptive : : OneColumn ( ) ) {
return true ;
} else {
return false ;
}
}
if ( back | | way = = Ui : : ShowWay : : Forward ) {
return true ;
}
if ( _history - > isHidden ( ) & & ( _wideSection | | _overview | | Adaptive : : OneColumn ( ) ) ) {
return true ;
}
return false ;
} ;
auto animationParams = animatedShow ( ) ? prepareHistoryAnimation ( peerId ) : Window : : SectionSlideParams ( ) ;
2016-10-20 12:46:16 +03:00
if ( _history - > peer ( ) & & _history - > peer ( ) - > id ! = peerId & & way ! = Ui : : ShowWay : : Forward ) {
2016-07-05 17:48:36 +03:00
clearBotStartToken ( _history - > peer ( ) ) ;
}
2016-04-13 00:31:28 +03:00
_history - > showHistory ( peerId , showAtMsgId ) ;
2015-07-17 22:17:37 +03:00
2017-01-14 21:50:16 +03:00
auto noPeer = ! _history - > peer ( ) ;
auto onlyDialogs = noPeer & & Adaptive : : OneColumn ( ) ;
2016-05-19 15:03:51 +03:00
if ( _wideSection | | _overview ) {
if ( _wideSection ) {
_wideSection - > hide ( ) ;
_wideSection - > deleteLater ( ) ;
_wideSection = nullptr ;
2015-07-17 22:17:37 +03:00
}
2016-04-13 00:31:28 +03:00
if ( _overview ) {
_overview - > hide ( ) ;
_overview - > clear ( ) ;
_overview - > deleteLater ( ) ;
_overview - > rpcClear ( ) ;
_overview = nullptr ;
2015-07-17 22:17:37 +03:00
}
}
if ( onlyDialogs ) {
2016-04-13 00:31:28 +03:00
_topBar - > hide ( ) ;
_history - > hide ( ) ;
2015-10-17 16:52:26 +02:00
if ( ! _a_show . animating ( ) ) {
2017-01-14 21:50:16 +03:00
if ( animationParams ) {
auto direction = back ? Window : : SlideDirection : : FromLeft : Window : : SlideDirection : : FromRight ;
_dialogs - > showAnimated ( direction , animationParams ) ;
2016-05-19 15:03:51 +03:00
} else {
2016-11-06 20:23:13 +03:00
_dialogs - > showFast ( ) ;
2014-08-15 15:19:32 +04:00
}
2014-12-12 19:27:03 +03:00
}
2015-07-17 22:17:37 +03:00
} else {
if ( noPeer ) {
2016-04-13 00:31:28 +03:00
_topBar - > hide ( ) ;
2017-01-30 18:27:13 +03:00
updateControlsGeometry ( ) ;
2015-09-21 23:57:42 +03:00
} else if ( wasActivePeer ! = activePeer ( ) ) {
if ( activePeer ( ) - > isChannel ( ) ) {
activePeer ( ) - > asChannel ( ) - > ptsWaitingForShortPoll ( WaitForChannelGetDifference ) ;
}
_viewsIncremented . remove ( activePeer ( ) ) ;
2015-07-17 22:17:37 +03:00
}
2016-04-13 00:31:28 +03:00
if ( Adaptive : : OneColumn ( ) & & ! _dialogs - > isHidden ( ) ) _dialogs - > hide ( ) ;
2015-10-17 16:52:26 +02:00
if ( ! _a_show . animating ( ) ) {
2016-05-19 15:03:51 +03:00
if ( ! animationParams . oldContentCache . isNull ( ) ) {
_history - > showAnimated ( back ? Window : : SlideDirection : : FromLeft : Window : : SlideDirection : : FromRight , animationParams ) ;
} else {
_history - > show ( ) ;
if ( App : : wnd ( ) ) {
QTimer : : singleShot ( 0 , App : : wnd ( ) , SLOT ( setInnerFocus ( ) ) ) ;
}
2014-05-30 12:53:19 +04:00
}
}
}
2015-09-20 11:55:41 +03:00
//if (wasActivePeer && wasActivePeer->isChannel() && activePeer() != wasActivePeer) {
2015-09-20 12:54:22 +03:00
// wasActivePeer->asChannel()->ptsWaitingForShortPoll(false);
2015-09-20 11:55:41 +03:00
//}
2015-07-17 22:17:37 +03:00
2016-04-13 00:31:28 +03:00
if ( ! _dialogs - > isHidden ( ) ) {
2015-12-07 13:06:59 +03:00
if ( ! back ) {
2016-04-13 00:31:28 +03:00
_dialogs - > scrollToPeer ( peerId , showAtMsgId ) ;
2015-12-07 13:06:59 +03:00
}
2016-04-13 00:31:28 +03:00
_dialogs - > update ( ) ;
2014-12-12 19:27:03 +03:00
}
2016-07-05 17:48:36 +03:00
topBar ( ) - > showAll ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-03-29 20:17:00 +03:00
PeerData * MainWidget : : ui_getPeerForMouseAction ( ) {
2016-04-13 00:31:28 +03:00
return _history - > ui_getPeerForMouseAction ( ) ;
2016-03-29 20:17:00 +03:00
}
2014-08-22 11:41:39 +04:00
void MainWidget : : peerBefore ( const PeerData * inPeer , MsgId inMsg , PeerData * & outPeer , MsgId & outMsg ) {
if ( selectingPeer ( ) ) {
outPeer = 0 ;
outMsg = 0 ;
return ;
}
2016-04-13 00:31:28 +03:00
_dialogs - > peerBefore ( inPeer , inMsg , outPeer , outMsg ) ;
2014-05-30 12:53:19 +04:00
}
2014-08-22 11:41:39 +04:00
void MainWidget : : peerAfter ( const PeerData * inPeer , MsgId inMsg , PeerData * & outPeer , MsgId & outMsg ) {
if ( selectingPeer ( ) ) {
outPeer = 0 ;
outMsg = 0 ;
return ;
}
2016-04-13 00:31:28 +03:00
_dialogs - > peerAfter ( inPeer , inMsg , outPeer , outMsg ) ;
2014-05-30 12:53:19 +04:00
}
2014-12-15 18:55:45 +03:00
PeerData * MainWidget : : historyPeer ( ) {
2016-04-13 00:31:28 +03:00
return _history - > peer ( ) ;
2014-12-15 18:55:45 +03:00
}
2014-05-30 12:53:19 +04:00
PeerData * MainWidget : : peer ( ) {
2016-04-13 00:31:28 +03:00
return _overview ? _overview - > peer ( ) : _history - > peer ( ) ;
2014-05-30 12:53:19 +04:00
}
PeerData * MainWidget : : activePeer ( ) {
2016-04-13 00:31:28 +03:00
return _history - > peer ( ) ? _history - > peer ( ) : _peerInStack ;
2014-05-30 12:53:19 +04:00
}
2014-07-04 15:12:54 +04:00
MsgId MainWidget : : activeMsgId ( ) {
2016-04-13 00:31:28 +03:00
return _history - > peer ( ) ? _history - > msgId ( ) : _msgIdInStack ;
2014-07-04 15:12:54 +04:00
}
2015-07-03 11:47:16 +03:00
PeerData * MainWidget : : overviewPeer ( ) {
2016-04-13 00:31:28 +03:00
return _overview ? _overview - > peer ( ) : 0 ;
2015-07-03 11:47:16 +03:00
}
2014-08-21 16:18:56 +04:00
bool MainWidget : : mediaTypeSwitch ( ) {
2016-04-13 00:31:28 +03:00
if ( ! _overview ) return false ;
2014-08-21 16:18:56 +04:00
for ( int32 i = 0 ; i < OverviewCount ; + + i ) {
if ( ! ( _mediaTypeMask & ~ ( 1 < < i ) ) ) {
return false ;
}
}
return true ;
}
2016-07-05 17:48:36 +03:00
void MainWidget : : saveSectionInStack ( ) {
if ( _overview ) {
_stack . push_back ( std_ : : make_unique < StackItemOverview > ( _overview - > peer ( ) , _overview - > type ( ) , _overview - > lastWidth ( ) , _overview - > lastScrollTop ( ) ) ) ;
} else if ( _wideSection ) {
_stack . push_back ( std_ : : make_unique < StackItemSection > ( _wideSection - > createMemento ( ) ) ) ;
} else if ( _history - > peer ( ) ) {
_peerInStack = _history - > peer ( ) ;
_msgIdInStack = _history - > msgId ( ) ;
_stack . push_back ( std_ : : make_unique < StackItemHistory > ( _peerInStack , _msgIdInStack , _history - > replyReturns ( ) ) ) ;
}
}
2014-08-21 16:18:56 +04:00
void MainWidget : : showMediaOverview ( PeerData * peer , MediaOverviewType type , bool back , int32 lastScrollTop ) {
2015-11-13 18:14:33 +03:00
if ( peer - > migrateTo ( ) ) {
peer = peer - > migrateTo ( ) ;
}
2016-08-17 18:14:08 +03:00
Ui : : hideSettingsAndLayer ( ) ;
2016-04-13 00:31:28 +03:00
if ( _overview & & _overview - > peer ( ) = = peer ) {
if ( _overview - > type ( ) ! = type ) {
_overview - > switchType ( type ) ;
2016-02-12 19:35:06 +03:00
} else if ( type = = OverviewMusicFiles ) { // hack for player
2015-07-03 11:47:16 +03:00
showBackFromStack ( ) ;
2014-08-15 15:19:32 +04:00
}
return ;
}
2017-01-14 21:50:16 +03:00
Global : : RefDialogsListFocused ( ) . set ( false , true ) ;
_a_dialogsWidth . finish ( ) ;
auto animatedShow = [ this ] {
if ( _a_show . animating ( ) | | App : : passcoded ( ) ) {
return false ;
}
if ( Adaptive : : OneColumn ( ) | | isSectionShown ( ) ) {
return true ;
}
return false ;
} ;
auto animationParams = animatedShow ( ) ? prepareOverviewAnimation ( ) : Window : : SectionSlideParams ( ) ;
2014-08-15 15:19:32 +04:00
if ( ! back ) {
2016-07-05 17:48:36 +03:00
saveSectionInStack ( ) ;
2014-08-15 15:19:32 +04:00
}
2017-01-30 18:27:13 +03:00
setFocus ( ) ; // otherwise dialogs widget could be focused.
2016-04-13 00:31:28 +03:00
if ( _overview ) {
_overview - > hide ( ) ;
_overview - > clear ( ) ;
_overview - > deleteLater ( ) ;
_overview - > rpcClear ( ) ;
2014-08-15 15:19:32 +04:00
}
2016-05-19 15:03:51 +03:00
if ( _wideSection ) {
_wideSection - > hide ( ) ;
_wideSection - > deleteLater ( ) ;
_wideSection = nullptr ;
2014-08-15 15:19:32 +04:00
}
2016-12-13 20:07:56 +03:00
_overview . create ( this , peer , type ) ;
2014-08-21 16:18:56 +04:00
_mediaTypeMask = 0 ;
2016-04-13 00:31:28 +03:00
_topBar - > show ( ) ;
2017-01-30 18:27:13 +03:00
updateControlsGeometry ( ) ;
2017-01-01 20:45:20 +04:00
// Send a fake update.
Notify : : PeerUpdate update ( peer ) ;
update . flags | = Notify : : PeerUpdate : : Flag : : SharedMediaChanged ;
update . mediaTypesMask | = ( 1 < < type ) ;
mediaOverviewUpdated ( update ) ;
2016-05-19 15:03:51 +03:00
_overview - > setLastScrollTop ( lastScrollTop ) ;
if ( ! animationParams . oldContentCache . isNull ( ) ) {
_overview - > showAnimated ( back ? Window : : SlideDirection : : FromLeft : Window : : SlideDirection : : FromRight , animationParams ) ;
2015-07-03 11:47:16 +03:00
} else {
2016-04-13 00:31:28 +03:00
_overview - > fastShow ( ) ;
2015-07-03 11:47:16 +03:00
}
2016-12-05 14:01:08 +03:00
_history - > finishAnimation ( ) ;
2016-07-05 17:48:36 +03:00
if ( back ) {
clearBotStartToken ( _history - > peer ( ) ) ;
}
2016-04-13 00:31:28 +03:00
_history - > showHistory ( 0 , 0 ) ;
_history - > hide ( ) ;
if ( Adaptive : : OneColumn ( ) ) _dialogs - > hide ( ) ;
2015-07-17 22:17:37 +03:00
orderWidgets ( ) ;
2014-08-15 15:19:32 +04:00
}
2016-06-06 14:35:49 +03:00
void MainWidget : : showWideSection ( const Window : : SectionMemento & memento ) {
2016-08-17 18:14:08 +03:00
Ui : : hideSettingsAndLayer ( ) ;
2016-05-19 15:03:51 +03:00
if ( _wideSection & & _wideSection - > showInternal ( & memento ) ) {
return ;
2015-11-13 18:14:33 +03:00
}
2017-01-14 21:50:16 +03:00
showNewWideSection ( & memento , false , true ) ;
2016-05-19 15:03:51 +03:00
}
2014-08-11 13:03:45 +04:00
2016-05-19 15:03:51 +03:00
Window : : SectionSlideParams MainWidget : : prepareShowAnimation ( bool willHaveTopBarShadow ) {
Window : : SectionSlideParams result ;
result . withTopBarShadow = willHaveTopBarShadow ;
if ( selectingPeer ( ) & & Adaptive : : OneColumn ( ) ) {
result . withTopBarShadow = false ;
} else if ( _wideSection ) {
if ( ! _wideSection - > hasTopBarShadow ( ) ) {
result . withTopBarShadow = false ;
2014-05-30 12:53:19 +04:00
}
2016-05-19 15:03:51 +03:00
} else if ( ! _overview & & ! _history - > peer ( ) ) {
result . withTopBarShadow = false ;
2014-05-30 12:53:19 +04:00
}
2016-05-19 15:03:51 +03:00
2016-10-12 22:34:25 +03:00
if ( _player ) {
_player - > hideShadow ( ) ;
}
2016-10-13 11:33:12 +03:00
auto playerVolumeVisible = _playerVolume & & ! _playerVolume - > isHidden ( ) ;
if ( playerVolumeVisible ) {
_playerVolume - > hide ( ) ;
}
2016-10-14 20:10:15 +03:00
auto playerPanelVisible = ! _playerPanel - > isHidden ( ) ;
if ( playerPanelVisible ) {
_playerPanel - > hide ( ) ;
}
auto playerPlaylistVisible = ! _playerPlaylist - > isHidden ( ) ;
if ( playerPlaylistVisible ) {
_playerPlaylist - > hide ( ) ;
}
2016-05-19 15:03:51 +03:00
if ( selectingPeer ( ) & & Adaptive : : OneColumn ( ) ) {
result . oldContentCache = myGrab ( this , QRect ( 0 , _playerHeight , _dialogsWidth , height ( ) - _playerHeight ) ) ;
} else if ( _wideSection ) {
result . oldContentCache = _wideSection - > grabForShowAnimation ( result ) ;
} else {
if ( result . withTopBarShadow ) {
if ( _overview ) _overview - > grapWithoutTopBarShadow ( ) ;
_history - > grapWithoutTopBarShadow ( ) ;
} else {
if ( _overview ) _overview - > grabStart ( ) ;
_history - > grabStart ( ) ;
}
if ( Adaptive : : OneColumn ( ) ) {
result . oldContentCache = myGrab ( this , QRect ( 0 , _playerHeight , _dialogsWidth , height ( ) - _playerHeight ) ) ;
} else {
2016-10-12 22:34:25 +03:00
_sideShadow - > hide ( ) ;
2016-05-19 15:03:51 +03:00
result . oldContentCache = myGrab ( this , QRect ( _dialogsWidth , _playerHeight , width ( ) - _dialogsWidth , height ( ) - _playerHeight ) ) ;
2016-10-12 22:34:25 +03:00
_sideShadow - > show ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-05-19 15:03:51 +03:00
if ( _overview ) _overview - > grabFinish ( ) ;
_history - > grabFinish ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-10-14 20:10:15 +03:00
2016-10-13 11:33:12 +03:00
if ( playerVolumeVisible ) {
_playerVolume - > show ( ) ;
}
2016-10-14 20:10:15 +03:00
if ( playerPanelVisible ) {
_playerPanel - > show ( ) ;
}
if ( playerPlaylistVisible ) {
_playerPlaylist - > show ( ) ;
}
2016-10-12 22:34:25 +03:00
if ( _player ) {
_player - > showShadow ( ) ;
}
2016-05-19 15:03:51 +03:00
return result ;
}
Window : : SectionSlideParams MainWidget : : prepareWideSectionAnimation ( Window : : SectionWidget * section ) {
return prepareShowAnimation ( section - > hasTopBarShadow ( ) ) ;
}
Window : : SectionSlideParams MainWidget : : prepareHistoryAnimation ( PeerId historyPeerId ) {
return prepareShowAnimation ( historyPeerId ! = 0 ) ;
}
Window : : SectionSlideParams MainWidget : : prepareOverviewAnimation ( ) {
return prepareShowAnimation ( true ) ;
}
Window : : SectionSlideParams MainWidget : : prepareDialogsAnimation ( ) {
return prepareShowAnimation ( false ) ;
}
2017-01-14 21:50:16 +03:00
void MainWidget : : showNewWideSection ( const Window : : SectionMemento * memento , bool back , bool saveInStack ) {
2016-05-19 15:03:51 +03:00
QPixmap animCache ;
2017-01-14 21:50:16 +03:00
Global : : RefDialogsListFocused ( ) . set ( false , true ) ;
_a_dialogsWidth . finish ( ) ;
2016-05-19 15:03:51 +03:00
auto newWideGeometry = QRect ( _history - > x ( ) , _playerHeight , _history - > width ( ) , height ( ) - _playerHeight ) ;
auto newWideSection = memento - > createWidget ( this , newWideGeometry ) ;
2017-01-14 21:50:16 +03:00
auto animatedShow = [ this ] {
if ( _a_show . animating ( ) | | App : : passcoded ( ) ) {
return false ;
}
if ( Adaptive : : OneColumn ( ) | | isSectionShown ( ) ) {
return true ;
}
return false ;
} ;
auto animationParams = animatedShow ( ) ? prepareWideSectionAnimation ( newWideSection ) : Window : : SectionSlideParams ( ) ;
2016-05-19 15:03:51 +03:00
2016-12-13 20:07:56 +03:00
if ( saveInStack ) {
saveSectionInStack ( ) ;
}
2017-01-30 18:27:13 +03:00
setFocus ( ) ; // otherwise dialogs widget could be focused.
2016-04-13 00:31:28 +03:00
if ( _overview ) {
_overview - > hide ( ) ;
_overview - > clear ( ) ;
_overview - > deleteLater ( ) ;
_overview - > rpcClear ( ) ;
_overview = nullptr ;
2014-08-15 15:19:32 +04:00
}
2016-05-19 15:03:51 +03:00
if ( _wideSection ) {
_wideSection - > hide ( ) ;
_wideSection - > deleteLater ( ) ;
_wideSection = nullptr ;
2014-08-01 15:09:46 +04:00
}
2016-12-13 20:07:56 +03:00
_wideSection = std_ : : move ( newWideSection ) ;
2016-05-12 19:05:20 +03:00
_topBar - > hide ( ) ;
2017-01-30 18:27:13 +03:00
updateControlsGeometry ( ) ;
2016-12-05 14:01:08 +03:00
_history - > finishAnimation ( ) ;
2016-04-13 00:31:28 +03:00
_history - > showHistory ( 0 , 0 ) ;
_history - > hide ( ) ;
if ( Adaptive : : OneColumn ( ) ) _dialogs - > hide ( ) ;
2015-07-17 22:17:37 +03:00
2017-01-14 21:50:16 +03:00
if ( animationParams ) {
auto direction = back ? Window : : SlideDirection : : FromLeft : Window : : SlideDirection : : FromRight ;
_wideSection - > showAnimated ( direction , animationParams ) ;
} else {
_wideSection - > showFast ( ) ;
}
2017-01-07 15:55:05 +04:00
2015-07-17 22:17:37 +03:00
orderWidgets ( ) ;
2014-05-30 12:53:19 +04:00
}
2017-01-14 21:50:16 +03:00
bool MainWidget : : isSectionShown ( ) const {
return _wideSection | | _overview | | _history - > peer ( ) ;
}
2016-07-05 17:48:36 +03:00
bool MainWidget : : stackIsEmpty ( ) const {
return _stack . isEmpty ( ) ;
}
2014-08-15 15:19:32 +04:00
void MainWidget : : showBackFromStack ( ) {
2015-07-03 11:47:16 +03:00
if ( selectingPeer ( ) ) return ;
if ( _stack . isEmpty ( ) ) {
2015-12-13 14:36:08 +03:00
Ui : : showChatsList ( ) ;
2015-09-16 16:04:08 +03:00
if ( App : : wnd ( ) ) QTimer : : singleShot ( 0 , App : : wnd ( ) , SLOT ( setInnerFocus ( ) ) ) ;
2015-07-03 11:47:16 +03:00
return ;
}
2016-07-05 17:48:36 +03:00
auto item = std_ : : move ( _stack . back ( ) ) ;
2014-08-15 15:19:32 +04:00
_stack . pop_back ( ) ;
2016-05-19 15:03:51 +03:00
if ( auto currentHistoryPeer = _history - > peer ( ) ) {
clearBotStartToken ( currentHistoryPeer ) ;
}
2014-08-15 15:19:32 +04:00
if ( item - > type ( ) = = HistoryStackItem ) {
2015-10-14 13:51:37 +02:00
dlgUpdated ( ) ;
2016-07-05 17:48:36 +03:00
_peerInStack = nullptr ;
2015-07-17 22:17:37 +03:00
_msgIdInStack = 0 ;
2017-01-14 21:50:16 +03:00
for ( auto i = _stack . size ( ) ; i > 0 ; ) {
if ( _stack [ - - i ] - > type ( ) = = HistoryStackItem ) {
auto historyItem = static_cast < StackItemHistory * > ( _stack [ i ] . get ( ) ) ;
_peerInStack = historyItem - > peer ;
_msgIdInStack = historyItem - > msgId ;
2015-10-14 13:51:37 +02:00
dlgUpdated ( ) ;
2015-07-17 22:17:37 +03:00
break ;
}
}
2017-01-14 21:50:16 +03:00
auto historyItem = static_cast < StackItemHistory * > ( item . get ( ) ) ;
Ui : : showPeerHistory ( historyItem - > peer - > id , ShowAtUnreadMsgId , Ui : : ShowWay : : Backward ) ;
_history - > setReplyReturns ( historyItem - > peer - > id , historyItem - > replyReturns ) ;
2016-05-19 15:03:51 +03:00
} else if ( item - > type ( ) = = SectionStackItem ) {
2017-01-14 21:50:16 +03:00
auto sectionItem = static_cast < StackItemSection * > ( item . get ( ) ) ;
showNewWideSection ( sectionItem - > memento ( ) , true , false ) ;
2014-08-15 15:19:32 +04:00
} else if ( item - > type ( ) = = OverviewStackItem ) {
2017-01-14 21:50:16 +03:00
auto overviewItem = static_cast < StackItemOverview * > ( item . get ( ) ) ;
showMediaOverview ( overviewItem - > peer , overviewItem - > mediaType , true , overviewItem - > lastScrollTop ) ;
2014-05-30 12:53:19 +04:00
}
}
2015-07-17 22:17:37 +03:00
void MainWidget : : orderWidgets ( ) {
2016-04-13 00:31:28 +03:00
_topBar - > raise ( ) ;
_dialogs - > raise ( ) ;
2016-10-12 22:34:25 +03:00
if ( _player ) {
_player - > raise ( ) ;
}
if ( _playerVolume ) {
_playerVolume - > raise ( ) ;
}
2016-04-13 00:31:28 +03:00
_mediaType - > raise ( ) ;
2016-10-12 22:34:25 +03:00
_sideShadow - > raise ( ) ;
2017-01-14 21:50:16 +03:00
_sideResizeArea - > raise ( ) ;
2016-10-14 20:10:15 +03:00
_playerPlaylist - > raise ( ) ;
_playerPanel - > raise ( ) ;
2015-07-17 22:17:37 +03:00
if ( _hider ) _hider - > raise ( ) ;
}
2014-05-30 12:53:19 +04:00
QRect MainWidget : : historyRect ( ) const {
2016-04-13 00:31:28 +03:00
QRect r ( _history - > historyRect ( ) ) ;
r . moveLeft ( r . left ( ) + _history - > x ( ) ) ;
r . moveTop ( r . top ( ) + _history - > y ( ) ) ;
2014-05-30 12:53:19 +04:00
return r ;
}
2016-05-19 15:03:51 +03:00
QPixmap MainWidget : : grabForShowAnimation ( const Window : : SectionSlideParams & params ) {
_topBar - > stopAnim ( ) ;
QPixmap result ;
2016-10-12 22:34:25 +03:00
if ( _player ) {
_player - > hideShadow ( ) ;
}
2016-10-13 11:33:12 +03:00
auto playerVolumeVisible = _playerVolume & & ! _playerVolume - > isHidden ( ) ;
if ( playerVolumeVisible ) {
_playerVolume - > hide ( ) ;
}
2016-10-14 20:10:15 +03:00
auto playerPanelVisible = ! _playerPanel - > isHidden ( ) ;
if ( playerPanelVisible ) {
_playerPanel - > hide ( ) ;
}
auto playerPlaylistVisible = ! _playerPlaylist - > isHidden ( ) ;
if ( playerPlaylistVisible ) {
_playerPlaylist - > hide ( ) ;
}
2016-05-19 15:03:51 +03:00
if ( Adaptive : : OneColumn ( ) ) {
result = myGrab ( this , QRect ( 0 , _playerHeight , _dialogsWidth , height ( ) - _playerHeight ) ) ;
} else {
2016-10-12 22:34:25 +03:00
_sideShadow - > hide ( ) ;
2016-05-19 15:03:51 +03:00
result = myGrab ( this , QRect ( _dialogsWidth , _playerHeight , width ( ) - _dialogsWidth , height ( ) - _playerHeight ) ) ;
2016-10-12 22:34:25 +03:00
_sideShadow - > show ( ) ;
}
2016-10-13 11:33:12 +03:00
if ( playerVolumeVisible ) {
_playerVolume - > show ( ) ;
}
2016-10-14 20:10:15 +03:00
if ( playerPanelVisible ) {
_playerPanel - > show ( ) ;
}
if ( playerPlaylistVisible ) {
_playerPlaylist - > show ( ) ;
}
2016-10-12 22:34:25 +03:00
if ( _player ) {
_player - > showShadow ( ) ;
2016-05-19 15:03:51 +03:00
}
return result ;
}
2016-04-11 14:59:01 +04:00
void MainWidget : : dlgUpdated ( ) {
if ( _peerInStack ) {
2016-12-05 14:01:08 +03:00
_dialogs - > dlgUpdated ( _peerInStack , _msgIdInStack ) ;
2015-10-14 13:51:37 +02:00
}
2014-05-30 12:53:19 +04:00
}
2016-04-11 14:59:01 +04:00
void MainWidget : : dlgUpdated ( Dialogs : : Mode list , Dialogs : : Row * row ) {
if ( row ) {
2016-04-13 00:31:28 +03:00
_dialogs - > dlgUpdated ( list , row ) ;
2016-04-11 14:59:01 +04:00
}
}
2016-12-05 14:01:08 +03:00
void MainWidget : : dlgUpdated ( PeerData * peer , MsgId msgId ) {
if ( ! peer ) return ;
if ( msgId < 0 & & - msgId < ServerMaxMsgId & & peer - > migrateFrom ( ) ) {
_dialogs - > dlgUpdated ( peer - > migrateFrom ( ) , - msgId ) ;
2015-11-13 18:14:33 +03:00
} else {
2016-12-05 14:01:08 +03:00
_dialogs - > dlgUpdated ( peer , msgId ) ;
2015-11-13 18:14:33 +03:00
}
2014-05-30 12:53:19 +04:00
}
void MainWidget : : windowShown ( ) {
2016-04-13 00:31:28 +03:00
_history - > windowShown ( ) ;
2014-05-30 12:53:19 +04:00
}
2015-08-30 17:57:21 +03:00
void MainWidget : : sentUpdatesReceived ( uint64 randomId , const MTPUpdates & result ) {
2015-09-21 23:57:42 +03:00
feedUpdates ( result , randomId ) ;
2014-05-30 12:53:19 +04:00
}
2016-03-23 19:50:40 +03:00
bool MainWidget : : deleteChannelFailed ( const RPCError & error ) {
2016-04-08 14:44:35 +04:00
if ( MTP : : isDefaultHandledError ( error ) ) return false ;
2016-03-23 19:50:40 +03:00
//if (error.type() == qstr("CHANNEL_TOO_LARGE")) {
2016-12-13 20:07:56 +03:00
// Ui::show(Box<InformBox>(lang(lng_cant_delete_channel)));
2016-03-23 19:50:40 +03:00
//}
return true ;
}
2015-09-23 20:43:08 +03:00
void MainWidget : : inviteToChannelDone ( ChannelData * channel , const MTPUpdates & updates ) {
sentUpdatesReceived ( updates ) ;
2015-09-25 10:47:32 +03:00
QTimer : : singleShot ( ReloadChannelMembersTimeout , this , SLOT ( onActiveChannelUpdateFull ( ) ) ) ;
}
void MainWidget : : onActiveChannelUpdateFull ( ) {
if ( activePeer ( ) & & activePeer ( ) - > isChannel ( ) ) {
activePeer ( ) - > asChannel ( ) - > updateFull ( true ) ;
}
2015-09-23 20:43:08 +03:00
}
2016-06-03 15:45:33 +03:00
void MainWidget : : historyToDown ( History * history ) {
_history - > historyToDown ( history ) ;
2014-05-30 12:53:19 +04:00
}
void MainWidget : : dialogsToUp ( ) {
2016-04-13 00:31:28 +03:00
_dialogs - > dialogsToUp ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-06-03 15:45:33 +03:00
void MainWidget : : newUnreadMsg ( History * history , HistoryItem * item ) {
_history - > newUnreadMsg ( history , item ) ;
2014-05-30 12:53:19 +04:00
}
2016-06-03 15:45:33 +03:00
void MainWidget : : markActiveHistoryAsRead ( ) {
_history - > historyWasRead ( ReadServerHistoryChecks : : OnlyIfUnread ) ;
2014-05-30 12:53:19 +04:00
}
2016-06-03 15:45:33 +03:00
void MainWidget : : historyCleared ( History * history ) {
_history - > historyCleared ( history ) ;
2015-06-17 22:43:03 +03:00
}
2016-12-05 14:01:08 +03:00
void MainWidget : : showAnimated ( const QPixmap & bgAnimCache , bool back ) {
_showBack = back ;
( _showBack ? _cacheOver : _cacheUnder ) = bgAnimCache ;
2015-10-17 16:52:26 +02:00
2016-12-05 14:01:08 +03:00
_a_show . finish ( ) ;
2014-05-30 12:53:19 +04:00
showAll ( ) ;
2016-12-05 14:01:08 +03:00
( _showBack ? _cacheUnder : _cacheOver ) = myGrab ( this ) ;
2015-10-17 16:52:26 +02:00
hideAll ( ) ;
2014-05-30 12:53:19 +04:00
2016-12-05 14:01:08 +03:00
_a_show . start ( [ this ] { animationCallback ( ) ; } , 0. , 1. , st : : slideDuration , Window : : SlideAnimation : : transition ( ) ) ;
2014-05-30 12:53:19 +04:00
show ( ) ;
}
2016-12-05 14:01:08 +03:00
void MainWidget : : animationCallback ( ) {
update ( ) ;
if ( ! _a_show . animating ( ) ) {
2015-10-17 16:52:26 +02:00
_cacheUnder = _cacheOver = QPixmap ( ) ;
2014-05-30 12:53:19 +04:00
showAll ( ) ;
activate ( ) ;
}
2015-10-17 16:52:26 +02:00
}
2014-05-30 12:53:19 +04:00
void MainWidget : : paintEvent ( QPaintEvent * e ) {
2015-02-03 18:02:46 +03:00
if ( _background ) checkChatBackground ( ) ;
2015-10-17 16:52:26 +02:00
Painter p ( this ) ;
2016-12-05 14:01:08 +03:00
auto progress = _a_show . current ( getms ( ) , 1. ) ;
2015-10-17 16:52:26 +02:00
if ( _a_show . animating ( ) ) {
2016-12-05 14:01:08 +03:00
auto coordUnder = _showBack ? anim : : interpolate ( - st : : slideShift , 0 , progress ) : anim : : interpolate ( 0 , - st : : slideShift , progress ) ;
auto coordOver = _showBack ? anim : : interpolate ( 0 , width ( ) , progress ) : anim : : interpolate ( width ( ) , 0 , progress ) ;
auto shadow = _showBack ? ( 1. - progress ) : progress ;
if ( coordOver > 0 ) {
p . drawPixmap ( QRect ( 0 , 0 , coordOver , height ( ) ) , _cacheUnder , QRect ( - coordUnder * cRetinaFactor ( ) , 0 , coordOver * cRetinaFactor ( ) , height ( ) * cRetinaFactor ( ) ) ) ;
p . setOpacity ( shadow ) ;
p . fillRect ( 0 , 0 , coordOver , height ( ) , st : : slideFadeOutBg ) ;
2015-10-17 16:52:26 +02:00
p . setOpacity ( 1 ) ;
}
2016-12-05 14:01:08 +03:00
p . drawPixmap ( coordOver , 0 , _cacheOver ) ;
p . setOpacity ( shadow ) ;
st : : slideShadow . fill ( p , QRect ( coordOver - st : : slideShadow . width ( ) , 0 , st : : slideShadow . width ( ) , height ( ) ) ) ;
2014-05-30 12:53:19 +04:00
}
}
void MainWidget : : hideAll ( ) {
2016-04-13 00:31:28 +03:00
_dialogs - > hide ( ) ;
_history - > hide ( ) ;
2016-05-19 15:03:51 +03:00
if ( _wideSection ) {
_wideSection - > hide ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-04-13 00:31:28 +03:00
if ( _overview ) {
_overview - > hide ( ) ;
2014-08-15 15:19:32 +04:00
}
2016-10-12 22:34:25 +03:00
_sideShadow - > hide ( ) ;
2016-04-13 00:31:28 +03:00
_topBar - > hide ( ) ;
_mediaType - > hide ( ) ;
2016-10-12 22:34:25 +03:00
if ( _player ) {
_player - > hide ( ) ;
2016-04-14 19:08:36 +03:00
_playerHeight = 0 ;
}
2014-05-30 12:53:19 +04:00
}
void MainWidget : : showAll ( ) {
2015-04-02 13:33:19 +03:00
if ( cPasswordRecovered ( ) ) {
cSetPasswordRecovered ( false ) ;
2016-12-13 20:07:56 +03:00
Ui : : show ( Box < InformBox > ( lang ( lng_signin_password_removed ) ) ) ;
2015-04-02 13:33:19 +03:00
}
2016-02-08 17:54:55 +03:00
if ( Adaptive : : OneColumn ( ) ) {
2016-10-12 22:34:25 +03:00
_sideShadow - > hide ( ) ;
2015-07-17 22:17:37 +03:00
if ( _hider ) {
_hider - > hide ( ) ;
if ( ! _forwardConfirm & & _hider - > wasOffered ( ) ) {
2016-12-13 20:07:56 +03:00
_forwardConfirm = Ui : : show ( Box < ConfirmBox > ( _hider - > offeredText ( ) , lang ( lng_forward_send ) , base : : lambda_guarded ( this , [ this ] {
_hider - > forward ( ) ;
if ( _forwardConfirm ) _forwardConfirm - > closeBox ( ) ;
if ( _hider ) _hider - > offerPeer ( 0 ) ;
} ) , base : : lambda_guarded ( this , [ this ] {
if ( _hider & & _forwardConfirm ) _hider - > offerPeer ( 0 ) ;
} ) ) , ForceFastShowLayer ) ;
2014-12-12 19:27:03 +03:00
}
}
if ( selectingPeer ( ) ) {
2016-11-06 20:23:13 +03:00
_dialogs - > showFast ( ) ;
2016-04-13 00:31:28 +03:00
_history - > hide ( ) ;
if ( _overview ) _overview - > hide ( ) ;
2016-05-19 15:03:51 +03:00
if ( _wideSection ) _wideSection - > hide ( ) ;
2016-04-13 00:31:28 +03:00
_topBar - > hide ( ) ;
} else if ( _overview ) {
_overview - > show ( ) ;
2016-05-19 15:03:51 +03:00
} else if ( _wideSection ) {
_wideSection - > show ( ) ;
2016-04-13 00:31:28 +03:00
} else if ( _history - > peer ( ) ) {
_history - > show ( ) ;
2016-10-18 13:32:33 +03:00
_history - > updateControlsGeometry ( ) ;
2014-12-12 19:27:03 +03:00
} else {
2016-11-06 20:23:13 +03:00
_dialogs - > showFast ( ) ;
2016-04-13 00:31:28 +03:00
_history - > hide ( ) ;
2014-12-12 19:27:03 +03:00
}
2016-08-16 19:53:10 +03:00
if ( ! selectingPeer ( ) ) {
if ( _wideSection ) {
_topBar - > hide ( ) ;
_dialogs - > hide ( ) ;
2017-01-14 21:50:16 +03:00
} else if ( isSectionShown ( ) ) {
2016-08-16 19:53:10 +03:00
_topBar - > show ( ) ;
_dialogs - > hide ( ) ;
}
2014-12-12 19:27:03 +03:00
}
2016-02-08 17:54:55 +03:00
} else {
2016-10-12 22:34:25 +03:00
_sideShadow - > show ( ) ;
2016-02-08 17:54:55 +03:00
if ( _hider ) {
_hider - > show ( ) ;
if ( _forwardConfirm ) {
2016-12-13 20:07:56 +03:00
_forwardConfirm = nullptr ;
2016-02-08 17:54:55 +03:00
Ui : : hideLayer ( true ) ;
2016-12-13 20:07:56 +03:00
if ( _hider - > wasOffered ( ) ) {
_hider - > setFocus ( ) ;
}
2016-02-08 17:54:55 +03:00
}
}
2016-11-06 20:23:13 +03:00
_dialogs - > showFast ( ) ;
2016-04-13 00:31:28 +03:00
if ( _overview ) {
_overview - > show ( ) ;
2016-05-19 15:03:51 +03:00
} else if ( _wideSection ) {
_wideSection - > show ( ) ;
2016-02-08 17:54:55 +03:00
} else {
2016-04-13 00:31:28 +03:00
_history - > show ( ) ;
2016-10-18 13:32:33 +03:00
_history - > updateControlsGeometry ( ) ;
2016-02-08 17:54:55 +03:00
}
2016-05-19 15:03:51 +03:00
if ( _wideSection ) {
2016-05-12 19:05:20 +03:00
_topBar - > hide ( ) ;
2017-01-14 21:50:16 +03:00
} else if ( isSectionShown ( ) ) {
2016-04-13 00:31:28 +03:00
_topBar - > show ( ) ;
2016-02-08 17:54:55 +03:00
}
2014-05-30 12:53:19 +04:00
}
2016-10-12 22:34:25 +03:00
if ( _player ) {
_player - > show ( ) ;
_playerHeight = _player - > contentHeight ( ) ;
2015-10-17 10:31:48 +02:00
}
2017-01-30 18:27:13 +03:00
updateControlsGeometry ( ) ;
2015-10-17 10:31:48 +02:00
2014-05-30 12:53:19 +04:00
App : : wnd ( ) - > checkHistoryActivation ( ) ;
}
void MainWidget : : resizeEvent ( QResizeEvent * e ) {
2016-10-12 22:34:25 +03:00
updateControlsGeometry ( ) ;
}
void MainWidget : : updateControlsGeometry ( ) {
2017-01-14 21:50:16 +03:00
updateWindowAdaptiveLayout ( ) ;
auto topBarHeight = _topBar - > isHidden ( ) ? 0 : st : : topBarHeight ;
if ( ! Adaptive : : SmallColumn ( ) ) {
_a_dialogsWidth . finish ( ) ;
}
if ( ! _a_dialogsWidth . animating ( ) ) {
_dialogs - > stopWidthAnimation ( ) ;
}
auto dialogsWidth = qRound ( _a_dialogsWidth . current ( _dialogsWidth ) ) ;
2016-02-08 17:54:55 +03:00
if ( Adaptive : : OneColumn ( ) ) {
2016-10-12 22:34:25 +03:00
if ( _player ) {
2017-01-14 21:50:16 +03:00
_player - > resizeToWidth ( dialogsWidth ) ;
2016-10-12 22:34:25 +03:00
_player - > moveToLeft ( 0 , 0 ) ;
}
2017-01-14 21:50:16 +03:00
_dialogs - > setGeometry ( 0 , _playerHeight , dialogsWidth , height ( ) - _playerHeight ) ;
_topBar - > setGeometry ( 0 , _playerHeight , dialogsWidth , st : : topBarHeight ) ;
_history - > setGeometry ( 0 , _playerHeight + topBarHeight , dialogsWidth , height ( ) - _playerHeight - topBarHeight ) ;
if ( _hider ) _hider - > setGeometry ( 0 , 0 , dialogsWidth , height ( ) ) ;
2016-02-08 17:54:55 +03:00
} else {
2017-01-14 21:50:16 +03:00
accumulate_min ( dialogsWidth , width ( ) - st : : windowMinWidth ) ;
auto sectionWidth = width ( ) - dialogsWidth ;
2016-10-12 22:34:25 +03:00
2017-01-14 21:50:16 +03:00
_dialogs - > setGeometryToLeft ( 0 , 0 , dialogsWidth , height ( ) ) ;
_sideShadow - > setGeometryToLeft ( dialogsWidth , 0 , st : : lineWidth , height ( ) ) ;
2016-10-12 22:34:25 +03:00
if ( _player ) {
_player - > resizeToWidth ( sectionWidth ) ;
2017-01-14 21:50:16 +03:00
_player - > moveToLeft ( dialogsWidth , 0 ) ;
2016-10-12 22:34:25 +03:00
}
2017-01-14 21:50:16 +03:00
_topBar - > setGeometryToLeft ( dialogsWidth , _playerHeight , sectionWidth , st : : topBarHeight ) ;
_history - > setGeometryToLeft ( dialogsWidth , _playerHeight + topBarHeight , sectionWidth , height ( ) - _playerHeight - topBarHeight ) ;
2015-10-17 10:31:48 +02:00
if ( _hider ) {
2017-01-14 21:50:16 +03:00
_hider - > setGeometryToLeft ( dialogsWidth , 0 , sectionWidth , height ( ) ) ;
2015-10-17 10:31:48 +02:00
}
2014-12-12 19:27:03 +03:00
}
2017-01-14 21:50:16 +03:00
_sideResizeArea - > setGeometryToLeft ( _history - > x ( ) , 0 , st : : historyResizeWidth , height ( ) ) ;
auto isSideResizeAreaVisible = [ this ] {
if ( width ( ) < st : : windowMinWidth + st : : dialogsWidthMin ) {
return false ;
}
if ( Adaptive : : OneColumn ( ) & & ! isSectionShown ( ) ) {
return false ;
}
return true ;
} ;
_sideResizeArea - > setVisible ( isSideResizeAreaVisible ( ) ) ;
2016-04-13 00:31:28 +03:00
_mediaType - > moveToLeft ( width ( ) - _mediaType - > width ( ) , _playerHeight + st : : topBarHeight ) ;
2016-05-19 15:03:51 +03:00
if ( _wideSection ) {
QRect wideSectionGeometry ( _history - > x ( ) , _playerHeight , _history - > width ( ) , height ( ) - _playerHeight ) ;
_wideSection - > setGeometryWithTopMoved ( wideSectionGeometry , _contentScrollAddToY ) ;
2016-05-12 19:05:20 +03:00
}
2016-04-13 00:31:28 +03:00
if ( _overview ) _overview - > setGeometry ( _history - > geometry ( ) ) ;
2016-10-12 22:34:25 +03:00
updateMediaPlayerPosition ( ) ;
2016-10-14 20:10:15 +03:00
updateMediaPlaylistPosition ( _playerPlaylist - > x ( ) ) ;
2015-07-03 11:47:16 +03:00
_contentScrollAddToY = 0 ;
}
2017-01-14 21:50:16 +03:00
void MainWidget : : updateDialogsWidthAnimated ( ) {
if ( ! Adaptive : : SmallColumn ( ) ) {
return ;
}
auto dialogsWidth = _dialogsWidth ;
updateWindowAdaptiveLayout ( ) ;
if ( Adaptive : : SmallColumn ( ) & & ( _dialogsWidth ! = dialogsWidth | | _a_dialogsWidth . animating ( ) ) ) {
_dialogs - > startWidthAnimation ( ) ;
_a_dialogsWidth . start ( [ this ] { updateControlsGeometry ( ) ; } , dialogsWidth , _dialogsWidth , st : : dialogsWidthDuration , anim : : easeOutCirc ) ;
updateControlsGeometry ( ) ;
}
}
2016-09-23 19:04:26 +03:00
void MainWidget : : updateMediaPlayerPosition ( ) {
2016-10-14 20:10:15 +03:00
_playerPanel - > moveToRight ( 0 , 0 ) ;
if ( _player & & _playerVolume ) {
2016-10-12 22:34:25 +03:00
auto relativePosition = _player - > entity ( ) - > getPositionForVolumeWidget ( ) ;
auto playerMargins = _playerVolume - > getMargin ( ) ;
_playerVolume - > moveToLeft ( _player - > x ( ) + relativePosition . x ( ) - playerMargins . left ( ) , _player - > y ( ) + relativePosition . y ( ) - playerMargins . top ( ) ) ;
2016-09-23 19:04:26 +03:00
}
}
2016-10-14 20:10:15 +03:00
void MainWidget : : updateMediaPlaylistPosition ( int x ) {
if ( _player ) {
auto playlistLeft = x ;
auto playlistWidth = _playerPlaylist - > width ( ) ;
auto playlistTop = _player - > y ( ) + _player - > height ( ) ;
auto rightEdge = width ( ) ;
if ( playlistLeft + playlistWidth > rightEdge ) {
playlistLeft = rightEdge - playlistWidth ;
} else if ( playlistLeft < 0 ) {
playlistLeft = 0 ;
}
_playerPlaylist - > move ( playlistLeft , playlistTop ) ;
}
}
2016-04-08 13:20:10 +04:00
int MainWidget : : contentScrollAddToY ( ) const {
2015-07-03 11:47:16 +03:00
return _contentScrollAddToY ;
2014-05-30 12:53:19 +04:00
}
void MainWidget : : keyPressEvent ( QKeyEvent * e ) {
}
2017-01-14 21:50:16 +03:00
bool MainWidget : : eventFilter ( QObject * o , QEvent * e ) {
if ( o = = _sideResizeArea ) {
auto mouseLeft = [ this , e ] {
return mapFromGlobal ( static_cast < QMouseEvent * > ( e ) - > globalPos ( ) ) . x ( ) ;
} ;
if ( e - > type ( ) = = QEvent : : MouseButtonPress & & static_cast < QMouseEvent * > ( e ) - > button ( ) = = Qt : : LeftButton ) {
_resizingSide = true ;
_resizingSideShift = mouseLeft ( ) - ( Adaptive : : OneColumn ( ) ? 0 : _dialogsWidth ) ;
} else if ( e - > type ( ) = = QEvent : : MouseButtonRelease ) {
_resizingSide = false ;
if ( ! Adaptive : : OneColumn ( ) ) {
Global : : SetDialogsWidthRatio ( float64 ( _dialogsWidth ) / width ( ) ) ;
}
Local : : writeUserSettings ( ) ;
} else if ( e - > type ( ) = = QEvent : : MouseMove & & _resizingSide ) {
auto newWidth = mouseLeft ( ) - _resizingSideShift ;
Global : : SetDialogsWidthRatio ( float64 ( newWidth ) / width ( ) ) ;
updateControlsGeometry ( ) ;
}
} else if ( e - > type ( ) = = QEvent : : FocusIn ) {
if ( auto widget = qobject_cast < QWidget * > ( o ) ) {
if ( _history = = widget | | _history - > isAncestorOf ( widget )
| | ( _overview & & ( _overview = = widget | | _overview - > isAncestorOf ( widget ) ) )
| | ( _wideSection & & ( _wideSection = = widget | | _wideSection - > isAncestorOf ( widget ) ) ) ) {
Global : : RefDialogsListFocused ( ) . set ( false , false ) ;
} else if ( _dialogs = = widget | | _dialogs - > isAncestorOf ( widget ) ) {
Global : : RefDialogsListFocused ( ) . set ( true , false ) ;
}
}
}
return TWidget : : eventFilter ( o , e ) ;
}
void MainWidget : : handleAdaptiveLayoutUpdate ( ) {
2014-12-12 19:27:03 +03:00
showAll ( ) ;
2016-10-12 22:34:25 +03:00
_sideShadow - > setVisible ( ! Adaptive : : OneColumn ( ) ) ;
if ( _player ) {
_player - > updateAdaptiveLayout ( ) ;
}
2014-12-12 19:27:03 +03:00
}
2017-01-14 21:50:16 +03:00
void MainWidget : : updateWindowAdaptiveLayout ( ) {
auto layout = Adaptive : : WindowLayout : : OneColumn ;
auto dialogsWidth = qRound ( width ( ) * Global : : DialogsWidthRatio ( ) ) ;
auto historyWidth = width ( ) - dialogsWidth ;
accumulate_max ( historyWidth , st : : windowMinWidth ) ;
dialogsWidth = width ( ) - historyWidth ;
auto useOneColumnLayout = [ this , dialogsWidth ] {
auto someSectionShown = ! selectingPeer ( ) & & isSectionShown ( ) ;
if ( dialogsWidth < st : : dialogsPadding . x ( ) & & ( Adaptive : : OneColumn ( ) | | someSectionShown ) ) {
return true ;
}
if ( width ( ) < st : : windowMinWidth + st : : dialogsWidthMin ) {
return true ;
}
return false ;
} ;
auto useSmallColumnLayout = [ this , dialogsWidth ] {
// used if useOneColumnLayout() == false.
if ( dialogsWidth < st : : dialogsWidthMin / 2 ) {
return true ;
}
return false ;
} ;
if ( useOneColumnLayout ( ) ) {
dialogsWidth = width ( ) ;
} else if ( useSmallColumnLayout ( ) ) {
layout = Adaptive : : WindowLayout : : SmallColumn ;
auto forceWideDialogs = [ this ] {
if ( Global : : DialogsListDisplayForced ( ) . value ( ) ) {
return true ;
} else if ( Global : : DialogsListFocused ( ) . value ( ) ) {
return true ;
}
return ! isSectionShown ( ) ;
} ;
if ( forceWideDialogs ( ) ) {
dialogsWidth = st : : dialogsWidthMin ;
} else {
dialogsWidth = st : : dialogsPadding . x ( ) + st : : dialogsPhotoSize + st : : dialogsPadding . x ( ) ;
}
} else {
layout = Adaptive : : WindowLayout : : Normal ;
accumulate_max ( dialogsWidth , st : : dialogsWidthMin ) ;
}
_dialogsWidth = dialogsWidth ;
if ( layout ! = Global : : AdaptiveWindowLayout ( ) ) {
Global : : SetAdaptiveWindowLayout ( layout ) ;
Adaptive : : Changed ( ) . notify ( true ) ;
}
}
2014-12-12 19:27:03 +03:00
bool MainWidget : : needBackButton ( ) {
2017-01-14 21:50:16 +03:00
return isSectionShown ( ) ;
2014-12-12 19:27:03 +03:00
}
2016-12-01 22:20:33 +03:00
bool MainWidget : : paintTopBar ( Painter & p , int decreaseWidth , TimeMs ms ) {
2016-05-19 15:03:51 +03:00
if ( _overview ) {
2016-11-19 12:22:53 +03:00
return _overview - > paintTopBar ( p , decreaseWidth ) ;
2016-05-19 15:03:51 +03:00
} else if ( ! _wideSection ) {
2016-12-01 22:20:33 +03:00
return _history - > paintTopBar ( p , decreaseWidth , ms ) ;
2014-05-30 12:53:19 +04:00
}
2016-11-06 20:23:13 +03:00
return false ;
2014-05-30 12:53:19 +04:00
}
2016-06-17 21:18:01 +03:00
QRect MainWidget : : getMembersShowAreaGeometry ( ) const {
if ( ! _overview & & ! _wideSection ) {
return _history - > getMembersShowAreaGeometry ( ) ;
}
return QRect ( ) ;
}
void MainWidget : : setMembersShowAreaActive ( bool active ) {
if ( ! active | | ( ! _overview & & ! _wideSection ) ) {
_history - > setMembersShowAreaActive ( active ) ;
}
}
2014-08-21 16:18:56 +04:00
void MainWidget : : onPhotosSelect ( ) {
2016-04-13 00:31:28 +03:00
if ( _overview ) _overview - > switchType ( OverviewPhotos ) ;
2016-10-26 19:43:13 +03:00
_mediaType - > hideAnimated ( ) ;
2014-08-21 16:18:56 +04:00
}
void MainWidget : : onVideosSelect ( ) {
2016-04-13 00:31:28 +03:00
if ( _overview ) _overview - > switchType ( OverviewVideos ) ;
2016-10-26 19:43:13 +03:00
_mediaType - > hideAnimated ( ) ;
2014-08-21 16:18:56 +04:00
}
2015-10-23 21:24:05 +02:00
void MainWidget : : onSongsSelect ( ) {
2016-04-13 00:31:28 +03:00
if ( _overview ) _overview - > switchType ( OverviewMusicFiles ) ;
2016-10-26 19:43:13 +03:00
_mediaType - > hideAnimated ( ) ;
2015-10-23 21:24:05 +02:00
}
2014-08-21 16:18:56 +04:00
void MainWidget : : onDocumentsSelect ( ) {
2016-04-13 00:31:28 +03:00
if ( _overview ) _overview - > switchType ( OverviewFiles ) ;
2016-10-26 19:43:13 +03:00
_mediaType - > hideAnimated ( ) ;
2014-08-21 16:18:56 +04:00
}
void MainWidget : : onAudiosSelect ( ) {
2016-04-13 00:31:28 +03:00
if ( _overview ) _overview - > switchType ( OverviewVoiceFiles ) ;
2016-10-26 19:43:13 +03:00
_mediaType - > hideAnimated ( ) ;
2014-08-21 16:18:56 +04:00
}
2015-08-28 18:15:56 +03:00
void MainWidget : : onLinksSelect ( ) {
2016-04-13 00:31:28 +03:00
if ( _overview ) _overview - > switchType ( OverviewLinks ) ;
2016-10-26 19:43:13 +03:00
_mediaType - > hideAnimated ( ) ;
2015-08-28 18:15:56 +03:00
}
2016-04-13 00:31:28 +03:00
Window : : TopBarWidget * MainWidget : : topBar ( ) {
return _topBar ;
2014-05-30 12:53:19 +04:00
}
2016-10-12 22:34:25 +03:00
int MainWidget : : backgroundFromY ( ) const {
return ( _topBar - > isHidden ( ) ? 0 : ( - st : : topBarHeight ) ) - _playerHeight ;
2015-07-03 11:47:16 +03:00
}
2014-05-30 12:53:19 +04:00
void MainWidget : : onTopBarClick ( ) {
2016-05-19 15:03:51 +03:00
if ( _overview ) {
2016-04-13 00:31:28 +03:00
_overview - > topBarClick ( ) ;
2016-05-19 15:03:51 +03:00
} else if ( ! _wideSection ) {
2016-04-13 00:31:28 +03:00
_history - > topBarClick ( ) ;
2014-05-30 12:53:19 +04:00
}
}
2015-10-03 13:09:09 +03:00
void MainWidget : : onHistoryShown ( History * history , MsgId atMsgId ) {
2016-05-12 19:05:20 +03:00
if ( ( ! Adaptive : : OneColumn ( ) | | ! selectingPeer ( ) ) & & ( _overview | | history ) ) {
2016-04-13 00:31:28 +03:00
_topBar - > show ( ) ;
2014-05-30 12:53:19 +04:00
} else {
2016-04-13 00:31:28 +03:00
_topBar - > hide ( ) ;
2014-05-30 12:53:19 +04:00
}
2017-01-30 18:27:13 +03:00
updateControlsGeometry ( ) ;
2015-10-17 16:52:26 +02:00
if ( _a_show . animating ( ) ) {
2016-04-13 00:31:28 +03:00
_topBar - > hide ( ) ;
2015-09-01 16:50:56 +03:00
}
2015-11-13 18:14:33 +03:00
2016-12-05 14:01:08 +03:00
dlgUpdated ( history ? history - > peer : nullptr , atMsgId ) ;
2014-05-30 12:53:19 +04:00
}
2015-08-04 18:01:47 +03:00
void MainWidget : : searchInPeer ( PeerData * peer ) {
2016-04-13 00:31:28 +03:00
_dialogs - > searchInPeer ( peer ) ;
2016-02-08 17:54:55 +03:00
if ( Adaptive : : OneColumn ( ) ) {
2015-08-04 18:01:47 +03:00
dialogsToUp ( ) ;
2015-12-13 14:36:08 +03:00
Ui : : showChatsList ( ) ;
2016-02-08 17:54:55 +03:00
} else {
2016-04-13 00:31:28 +03:00
_dialogs - > activate ( ) ;
2015-08-04 18:01:47 +03:00
}
}
2014-05-30 12:53:19 +04:00
void MainWidget : : onUpdateNotifySettings ( ) {
2015-03-02 15:34:16 +03:00
if ( this ! = App : : main ( ) ) return ;
2014-05-30 12:53:19 +04:00
while ( ! updateNotifySettingPeers . isEmpty ( ) ) {
PeerData * peer = * updateNotifySettingPeers . begin ( ) ;
updateNotifySettingPeers . erase ( updateNotifySettingPeers . begin ( ) ) ;
if ( peer - > notify = = UnknownNotifySettings | | peer - > notify = = EmptyNotifySettings ) {
peer - > notify = new NotifySettings ( ) ;
}
2016-03-19 19:55:15 +03:00
MTP : : send ( MTPaccount_UpdateNotifySettings ( MTP_inputNotifyPeer ( peer - > input ) , MTP_inputPeerNotifySettings ( MTP_flags ( mtpCastFlags ( peer - > notify - > flags ) ) , MTP_int ( peer - > notify - > mute ) , MTP_string ( peer - > notify - > sound ) ) ) , RPCResponseHandler ( ) , 0 , updateNotifySettingPeers . isEmpty ( ) ? 0 : 10 ) ;
2014-05-30 12:53:19 +04:00
}
}
2015-09-21 23:57:42 +03:00
void MainWidget : : feedUpdateVector ( const MTPVector < MTPUpdate > & updates , bool skipMessageIds ) {
2016-04-08 14:44:35 +04:00
const auto & v ( updates . c_vector ( ) . v ) ;
2014-05-30 12:53:19 +04:00
for ( QVector < MTPUpdate > : : const_iterator i = v . cbegin ( ) , e = v . cend ( ) ; i ! = e ; + + i ) {
if ( skipMessageIds & & i - > type ( ) = = mtpc_updateMessageID ) continue ;
feedUpdate ( * i ) ;
}
}
void MainWidget : : feedMessageIds ( const MTPVector < MTPUpdate > & updates ) {
2016-04-08 14:44:35 +04:00
const auto & v ( updates . c_vector ( ) . v ) ;
2014-05-30 12:53:19 +04:00
for ( QVector < MTPUpdate > : : const_iterator i = v . cbegin ( ) , e = v . cend ( ) ; i ! = e ; + + i ) {
if ( i - > type ( ) = = mtpc_updateMessageID ) {
feedUpdate ( * i ) ;
}
}
}
bool MainWidget : : updateFail ( const RPCError & e ) {
2016-03-31 18:06:40 +04:00
App : : logOutDelayed ( ) ;
2014-05-30 12:53:19 +04:00
return true ;
}
void MainWidget : : updSetState ( int32 pts , int32 date , int32 qts , int32 seq ) {
2016-03-11 18:01:32 +03:00
if ( pts ) {
_ptsWaiter . init ( pts ) ;
}
if ( updDate < date & & ! _byMinChannelTimer . isActive ( ) ) {
updDate = date ;
}
2014-11-05 20:43:32 +03:00
if ( qts & & updQts < qts ) {
updQts = qts ;
}
if ( seq & & seq ! = updSeq ) {
updSeq = seq ;
if ( _bySeqTimer . isActive ( ) ) _bySeqTimer . stop ( ) ;
for ( QMap < int32 , MTPUpdates > : : iterator i = _bySeqUpdates . begin ( ) ; i ! = _bySeqUpdates . end ( ) ; ) {
int32 s = i . key ( ) ;
if ( s < = seq + 1 ) {
MTPUpdates v = i . value ( ) ;
i = _bySeqUpdates . erase ( i ) ;
if ( s = = seq + 1 ) {
2015-09-21 23:57:42 +03:00
return feedUpdates ( v ) ;
2014-11-05 20:43:32 +03:00
}
} else {
2015-03-13 16:01:25 +03:00
if ( ! _bySeqTimer . isActive ( ) ) _bySeqTimer . start ( WaitForSkippedTimeout ) ;
2014-11-05 20:43:32 +03:00
break ;
}
}
}
2014-05-30 12:53:19 +04:00
}
2015-09-13 11:41:27 +03:00
void MainWidget : : gotChannelDifference ( ChannelData * channel , const MTPupdates_ChannelDifference & diff ) {
_channelFailDifferenceTimeout . remove ( channel ) ;
2015-12-31 23:27:21 +08:00
2015-10-28 20:16:52 -04:00
int32 timeout = 0 ;
bool isFinal = true ;
2015-09-13 11:41:27 +03:00
switch ( diff . type ( ) ) {
case mtpc_updates_channelDifferenceEmpty : {
2016-09-25 22:04:02 +03:00
auto & d = diff . c_updates_channelDifferenceEmpty ( ) ;
2015-09-13 11:41:27 +03:00
if ( d . has_timeout ( ) ) timeout = d . vtimeout . v ;
2015-10-28 20:16:52 -04:00
isFinal = d . is_final ( ) ;
2015-09-13 20:27:29 +03:00
channel - > ptsInit ( d . vpts . v ) ;
2015-09-13 11:41:27 +03:00
} break ;
case mtpc_updates_channelDifferenceTooLong : {
2016-09-25 22:04:02 +03:00
auto & d = diff . c_updates_channelDifferenceTooLong ( ) ;
2015-09-13 11:41:27 +03:00
App : : feedUsers ( d . vusers ) ;
App : : feedChats ( d . vchats ) ;
2016-09-25 22:04:02 +03:00
auto h = App : : historyLoaded ( channel - > id ) ;
2015-09-20 11:55:41 +03:00
if ( h ) {
h - > setNotLoadedAtBottom ( ) ;
}
App : : feedMsgs ( d . vmessages , NewMessageLast ) ;
if ( h ) {
2016-05-27 19:47:46 +03:00
if ( auto item = App : : histItemById ( peerToChannel ( channel - > id ) , d . vtop_message . v ) ) {
2015-09-13 11:41:27 +03:00
h - > setLastMessage ( item ) ;
}
2016-05-27 19:47:46 +03:00
if ( d . vunread_count . v > = h - > unreadCount ( ) ) {
h - > setUnreadCount ( d . vunread_count . v ) ;
2015-09-20 11:55:41 +03:00
h - > inboxReadBefore = d . vread_inbox_max_id . v + 1 ;
}
2016-04-13 00:31:28 +03:00
if ( _history - > peer ( ) = = channel ) {
2016-12-07 16:32:25 +03:00
_history - > updateHistoryDownVisibility ( ) ;
2016-04-13 00:31:28 +03:00
_history - > preloadHistoryIfNeeded ( ) ;
2015-09-13 11:41:27 +03:00
}
2015-09-21 23:57:42 +03:00
h - > asChannelHistory ( ) - > getRangeDifference ( ) ;
2015-09-13 11:41:27 +03:00
}
if ( d . has_timeout ( ) ) timeout = d . vtimeout . v ;
2015-10-28 20:16:52 -04:00
isFinal = d . is_final ( ) ;
2015-09-13 20:27:29 +03:00
channel - > ptsInit ( d . vpts . v ) ;
2015-09-13 11:41:27 +03:00
} break ;
case mtpc_updates_channelDifference : {
2016-09-25 22:04:02 +03:00
auto & d = diff . c_updates_channelDifference ( ) ;
2015-09-13 11:41:27 +03:00
App : : feedUsers ( d . vusers ) ;
2016-06-02 16:57:49 +03:00
App : : feedChats ( d . vchats ) ;
2015-12-31 23:27:21 +08:00
2015-09-21 23:57:42 +03:00
_handlingChannelDifference = true ;
2015-09-13 11:41:27 +03:00
feedMessageIds ( d . vother_updates ) ;
2015-09-21 23:57:42 +03:00
// feed messages and groups, copy from App::feedMsgs
2016-09-25 22:04:02 +03:00
auto h = App : : history ( channel - > id ) ;
auto & vmsgs = d . vnew_messages . c_vector ( ) . v ;
QMap < uint64 , int > msgsIds ;
for ( int i = 0 , l = vmsgs . size ( ) ; i < l ; + + i ) {
auto & msg = vmsgs [ i ] ;
2015-09-21 23:57:42 +03:00
switch ( msg . type ( ) ) {
case mtpc_message : {
2016-04-08 14:44:35 +04:00
const auto & d ( msg . c_message ( ) ) ;
2016-04-13 00:31:28 +03:00
if ( App : : checkEntitiesAndViewsUpdate ( d ) ) { // new message, index my forwarded messages to links _overview, already in blocks
2015-10-15 02:15:28 +02:00
LOG ( ( " Skipping message, because it is already in blocks! " ) ) ;
} else {
msgsIds . insert ( ( uint64 ( uint32 ( d . vid . v ) ) < < 32 ) | uint64 ( i ) , i + 1 ) ;
}
2015-09-21 23:57:42 +03:00
} break ;
case mtpc_messageEmpty : msgsIds . insert ( ( uint64 ( uint32 ( msg . c_messageEmpty ( ) . vid . v ) ) < < 32 ) | uint64 ( i ) , i + 1 ) ; break ;
case mtpc_messageService : msgsIds . insert ( ( uint64 ( uint32 ( msg . c_messageService ( ) . vid . v ) ) < < 32 ) | uint64 ( i ) , i + 1 ) ; break ;
}
}
2016-09-25 22:04:02 +03:00
for_const ( auto msgIndex , msgsIds ) {
if ( msgIndex > 0 ) { // add message
auto & msg = vmsgs . at ( msgIndex - 1 ) ;
2015-09-21 23:57:42 +03:00
if ( channel - > id ! = peerFromMessage ( msg ) ) {
LOG ( ( " API Error: message with invalid peer returned in channelDifference, channelId: %1, peer: %2 " ) . arg ( peerToChannel ( channel - > id ) ) . arg ( peerFromMessage ( msg ) ) ) ;
continue ; // wtf
}
h - > addNewMessage ( msg , NewMessageUnread ) ;
}
}
feedUpdateVector ( d . vother_updates , true ) ;
_handlingChannelDifference = false ;
2015-09-13 11:41:27 +03:00
if ( d . has_timeout ( ) ) timeout = d . vtimeout . v ;
2015-10-28 20:16:52 -04:00
isFinal = d . is_final ( ) ;
2015-09-13 20:27:29 +03:00
channel - > ptsInit ( d . vpts . v ) ;
2015-09-13 11:41:27 +03:00
} break ;
}
channel - > ptsSetRequesting ( false ) ;
2015-10-28 20:16:52 -04:00
if ( ! isFinal ) {
2015-09-13 11:41:27 +03:00
MTP_LOG ( 0 , ( " getChannelDifference { good - after not final channelDifference was received }%1 " ) . arg ( cTestMode ( ) ? " TESTMODE " : " " ) ) ;
getChannelDifference ( channel ) ;
2015-09-20 11:55:41 +03:00
} else if ( activePeer ( ) = = channel ) {
2015-09-20 12:54:22 +03:00
channel - > ptsWaitingForShortPoll ( timeout ? ( timeout * 1000 ) : WaitForChannelGetDifference ) ;
2015-09-13 11:41:27 +03:00
}
}
2015-09-21 23:57:42 +03:00
void MainWidget : : gotRangeDifference ( ChannelData * channel , const MTPupdates_ChannelDifference & diff ) {
2015-10-28 20:16:52 -04:00
int32 nextRequestPts = 0 ;
bool isFinal = true ;
2015-09-21 23:57:42 +03:00
switch ( diff . type ( ) ) {
case mtpc_updates_channelDifferenceEmpty : {
2016-04-08 14:44:35 +04:00
const auto & d ( diff . c_updates_channelDifferenceEmpty ( ) ) ;
2015-09-21 23:57:42 +03:00
nextRequestPts = d . vpts . v ;
2015-10-28 20:16:52 -04:00
isFinal = d . is_final ( ) ;
2015-09-21 23:57:42 +03:00
} break ;
case mtpc_updates_channelDifferenceTooLong : {
2016-04-08 14:44:35 +04:00
const auto & d ( diff . c_updates_channelDifferenceTooLong ( ) ) ;
2015-09-21 23:57:42 +03:00
App : : feedUsers ( d . vusers ) ;
App : : feedChats ( d . vchats ) ;
nextRequestPts = d . vpts . v ;
2015-10-28 20:16:52 -04:00
isFinal = d . is_final ( ) ;
2015-09-21 23:57:42 +03:00
} break ;
case mtpc_updates_channelDifference : {
2016-04-08 14:44:35 +04:00
const auto & d ( diff . c_updates_channelDifference ( ) ) ;
2015-09-21 23:57:42 +03:00
App : : feedUsers ( d . vusers ) ;
2016-06-02 16:57:49 +03:00
App : : feedChats ( d . vchats ) ;
2015-09-21 23:57:42 +03:00
_handlingChannelDifference = true ;
feedMessageIds ( d . vother_updates ) ;
App : : feedMsgs ( d . vnew_messages , NewMessageUnread ) ;
feedUpdateVector ( d . vother_updates , true ) ;
_handlingChannelDifference = false ;
nextRequestPts = d . vpts . v ;
2015-10-28 20:16:52 -04:00
isFinal = d . is_final ( ) ;
2015-09-21 23:57:42 +03:00
} break ;
}
2015-10-28 20:16:52 -04:00
if ( ! isFinal ) {
2015-09-21 23:57:42 +03:00
if ( History * h = App : : historyLoaded ( channel - > id ) ) {
MTP_LOG ( 0 , ( " getChannelDifference { good - after not final channelDifference was received, validating history part }%1 " ) . arg ( cTestMode ( ) ? " TESTMODE " : " " ) ) ;
h - > asChannelHistory ( ) - > getRangeDifferenceNext ( nextRequestPts ) ;
}
}
}
2015-09-13 11:41:27 +03:00
bool MainWidget : : failChannelDifference ( ChannelData * channel , const RPCError & error ) {
2016-04-08 14:44:35 +04:00
if ( MTP : : isDefaultHandledError ( error ) ) return false ;
2015-09-13 11:41:27 +03:00
LOG ( ( " RPC Error in getChannelDifference: %1 %2: %3 " ) . arg ( error . code ( ) ) . arg ( error . type ( ) ) . arg ( error . description ( ) ) ) ;
failDifferenceStartTimerFor ( channel ) ;
return true ;
}
2014-05-30 12:53:19 +04:00
void MainWidget : : gotState ( const MTPupdates_State & state ) {
2016-04-08 14:44:35 +04:00
const auto & d ( state . c_updates_state ( ) ) ;
2014-05-30 12:53:19 +04:00
updSetState ( d . vpts . v , d . vdate . v , d . vqts . v , d . vseq . v ) ;
2014-11-12 23:30:26 +03:00
_lastUpdateTime = getms ( true ) ;
2014-05-30 12:53:19 +04:00
noUpdatesTimer . start ( NoUpdatesTimeout ) ;
2015-09-13 11:41:27 +03:00
_ptsWaiter . setRequesting ( false ) ;
2014-05-30 12:53:19 +04:00
2016-04-13 00:31:28 +03:00
_dialogs - > loadDialogs ( ) ;
2015-01-26 16:04:41 +03:00
updateOnline ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-10-24 00:03:10 +03:00
void MainWidget : : gotDifference ( const MTPupdates_Difference & difference ) {
2014-11-05 20:43:32 +03:00
_failDifferenceTimeout = 1 ;
2016-10-24 00:03:10 +03:00
switch ( difference . type ( ) ) {
2014-05-30 12:53:19 +04:00
case mtpc_updates_differenceEmpty : {
2016-10-24 00:03:10 +03:00
auto & d = difference . c_updates_differenceEmpty ( ) ;
2015-09-13 11:41:27 +03:00
updSetState ( _ptsWaiter . current ( ) , d . vdate . v , updQts , d . vseq . v ) ;
2014-05-30 12:53:19 +04:00
2014-11-12 23:30:26 +03:00
_lastUpdateTime = getms ( true ) ;
2014-05-30 12:53:19 +04:00
noUpdatesTimer . start ( NoUpdatesTimeout ) ;
2014-11-22 12:45:04 +03:00
2015-09-13 11:41:27 +03:00
_ptsWaiter . setRequesting ( false ) ;
2014-05-30 12:53:19 +04:00
} break ;
case mtpc_updates_differenceSlice : {
2016-10-24 00:03:10 +03:00
auto & d = difference . c_updates_differenceSlice ( ) ;
2014-05-30 12:53:19 +04:00
feedDifference ( d . vusers , d . vchats , d . vnew_messages , d . vother_updates ) ;
2016-10-24 00:03:10 +03:00
auto & s = d . vintermediate_state . c_updates_state ( ) ;
2014-05-30 12:53:19 +04:00
updSetState ( s . vpts . v , s . vdate . v , s . vqts . v , s . vseq . v ) ;
2015-09-13 11:41:27 +03:00
_ptsWaiter . setRequesting ( false ) ;
2014-05-30 12:53:19 +04:00
2015-04-30 16:53:36 +03:00
MTP_LOG ( 0 , ( " getDifference { good - after a slice of difference was received }%1 " ) . arg ( cTestMode ( ) ? " TESTMODE " : " " ) ) ;
2014-05-30 12:53:19 +04:00
getDifference ( ) ;
} break ;
case mtpc_updates_difference : {
2016-10-24 00:03:10 +03:00
auto & d = difference . c_updates_difference ( ) ;
2014-05-30 12:53:19 +04:00
feedDifference ( d . vusers , d . vchats , d . vnew_messages , d . vother_updates ) ;
gotState ( d . vstate ) ;
} break ;
2016-10-24 00:03:10 +03:00
case mtpc_updates_differenceTooLong : {
auto & d = difference . c_updates_differenceTooLong ( ) ;
LOG ( ( " API Error: updates.differenceTooLong is not supported by Telegram Desktop! " ) ) ;
} break ;
2014-05-30 12:53:19 +04:00
} ;
}
2016-12-01 22:20:33 +03:00
bool MainWidget : : getDifferenceTimeChanged ( ChannelData * channel , int32 ms , ChannelGetDifferenceTime & channelCurTime , TimeMs & curTime ) {
2015-09-13 11:41:27 +03:00
if ( channel ) {
if ( ms < = 0 ) {
ChannelGetDifferenceTime : : iterator i = channelCurTime . find ( channel ) ;
if ( i ! = channelCurTime . cend ( ) ) {
channelCurTime . erase ( i ) ;
} else {
return false ;
}
} else {
2016-12-01 22:20:33 +03:00
auto when = getms ( true ) + ms ;
2015-09-13 11:41:27 +03:00
ChannelGetDifferenceTime : : iterator i = channelCurTime . find ( channel ) ;
if ( i ! = channelCurTime . cend ( ) ) {
if ( i . value ( ) > when ) {
i . value ( ) = when ;
} else {
return false ;
}
} else {
channelCurTime . insert ( channel , when ) ;
}
}
} else {
if ( ms < = 0 ) {
if ( curTime ) {
curTime = 0 ;
} else {
return false ;
}
} else {
2016-12-01 22:20:33 +03:00
auto when = getms ( true ) + ms ;
2015-09-13 11:41:27 +03:00
if ( ! curTime | | curTime > when ) {
curTime = when ;
} else {
return false ;
}
}
}
return true ;
}
void MainWidget : : ptsWaiterStartTimerFor ( ChannelData * channel , int32 ms ) {
if ( getDifferenceTimeChanged ( channel , ms , _channelGetDifferenceTimeByPts , _getDifferenceTimeByPts ) ) {
onGetDifferenceTimeByPts ( ) ;
}
2015-03-13 16:01:25 +03:00
}
2015-09-13 11:41:27 +03:00
void MainWidget : : failDifferenceStartTimerFor ( ChannelData * channel ) {
int32 ms = 0 ;
ChannelFailDifferenceTimeout : : iterator i ;
if ( channel ) {
i = _channelFailDifferenceTimeout . find ( channel ) ;
if ( i = = _channelFailDifferenceTimeout . cend ( ) ) {
i = _channelFailDifferenceTimeout . insert ( channel , 1 ) ;
2015-03-13 16:01:25 +03:00
}
2015-09-13 11:41:27 +03:00
ms = i . value ( ) * 1000 ;
} else {
ms = _failDifferenceTimeout * 1000 ;
}
if ( getDifferenceTimeChanged ( channel , ms , _channelGetDifferenceTimeAfterFail , _getDifferenceTimeAfterFail ) ) {
onGetDifferenceTimeAfterFail ( ) ;
}
if ( channel ) {
if ( i . value ( ) < 64 ) i . value ( ) * = 2 ;
} else {
if ( _failDifferenceTimeout < 64 ) _failDifferenceTimeout * = 2 ;
2015-03-13 16:01:25 +03:00
}
}
2015-09-13 11:41:27 +03:00
bool MainWidget : : ptsUpdated ( int32 pts , int32 ptsCount ) { // return false if need to save that update and apply later
return _ptsWaiter . updated ( 0 , pts , ptsCount ) ;
2015-03-13 16:01:25 +03:00
}
2015-09-13 11:41:27 +03:00
bool MainWidget : : ptsUpdated ( int32 pts , int32 ptsCount , const MTPUpdates & updates ) {
return _ptsWaiter . updated ( 0 , pts , ptsCount , updates ) ;
}
2015-03-13 16:01:25 +03:00
2015-09-13 11:41:27 +03:00
bool MainWidget : : ptsUpdated ( int32 pts , int32 ptsCount , const MTPUpdate & update ) {
return _ptsWaiter . updated ( 0 , pts , ptsCount , update ) ;
2014-05-30 12:53:19 +04:00
}
2015-09-20 12:54:22 +03:00
void MainWidget : : ptsApplySkippedUpdates ( ) {
return _ptsWaiter . applySkippedUpdates ( 0 ) ;
}
2014-05-30 12:53:19 +04:00
void MainWidget : : feedDifference ( const MTPVector < MTPUser > & users , const MTPVector < MTPChat > & chats , const MTPVector < MTPMessage > & msgs , const MTPVector < MTPUpdate > & other ) {
2015-03-02 15:34:16 +03:00
App : : wnd ( ) - > checkAutoLock ( ) ;
2016-06-02 16:57:49 +03:00
App : : feedUsers ( users ) ;
App : : feedChats ( chats ) ;
2014-05-30 12:53:19 +04:00
feedMessageIds ( other ) ;
2015-09-20 11:55:41 +03:00
App : : feedMsgs ( msgs , NewMessageUnread ) ;
2015-09-21 23:57:42 +03:00
feedUpdateVector ( other , true ) ;
2016-04-13 00:31:28 +03:00
_history - > peerMessagesUpdated ( ) ;
2014-05-30 12:53:19 +04:00
}
2015-04-04 23:01:34 +03:00
bool MainWidget : : failDifference ( const RPCError & error ) {
2016-04-08 14:44:35 +04:00
if ( MTP : : isDefaultHandledError ( error ) ) return false ;
2015-04-04 23:01:34 +03:00
2015-09-13 11:41:27 +03:00
LOG ( ( " RPC Error in getDifference: %1 %2: %3 " ) . arg ( error . code ( ) ) . arg ( error . type ( ) ) . arg ( error . description ( ) ) ) ;
failDifferenceStartTimerFor ( 0 ) ;
2014-11-05 20:43:32 +03:00
return true ;
}
2015-09-13 11:41:27 +03:00
void MainWidget : : onGetDifferenceTimeByPts ( ) {
if ( ! MTP : : authedId ( ) ) return ;
2016-12-01 22:20:33 +03:00
auto now = getms ( true ) , wait = 0LL ;
2015-09-13 11:41:27 +03:00
if ( _getDifferenceTimeByPts ) {
if ( _getDifferenceTimeByPts > now ) {
wait = _getDifferenceTimeByPts - now ;
} else {
getDifference ( ) ;
}
}
for ( ChannelGetDifferenceTime : : iterator i = _channelGetDifferenceTimeByPts . begin ( ) ; i ! = _channelGetDifferenceTimeByPts . cend ( ) ; ) {
if ( i . value ( ) > now ) {
2015-09-13 20:27:29 +03:00
wait = wait ? qMin ( wait , i . value ( ) - now ) : ( i . value ( ) - now ) ;
2015-09-13 11:41:27 +03:00
+ + i ;
} else {
2016-10-24 00:03:10 +03:00
getChannelDifference ( i . key ( ) , ChannelDifferenceRequest : : PtsGapOrShortPoll ) ;
2015-09-13 11:41:27 +03:00
i = _channelGetDifferenceTimeByPts . erase ( i ) ;
}
}
if ( wait ) {
_byPtsTimer . start ( wait ) ;
} else {
_byPtsTimer . stop ( ) ;
}
}
void MainWidget : : onGetDifferenceTimeAfterFail ( ) {
if ( ! MTP : : authedId ( ) ) return ;
2016-12-01 22:20:33 +03:00
auto now = getms ( true ) , wait = 0LL ;
2015-09-13 11:41:27 +03:00
if ( _getDifferenceTimeAfterFail ) {
if ( _getDifferenceTimeAfterFail > now ) {
wait = _getDifferenceTimeAfterFail - now ;
} else {
_ptsWaiter . setRequesting ( false ) ;
MTP_LOG ( 0 , ( " getDifference { force - after get difference failed }%1 " ) . arg ( cTestMode ( ) ? " TESTMODE " : " " ) ) ;
getDifference ( ) ;
}
}
2016-12-01 22:20:33 +03:00
for ( auto i = _channelGetDifferenceTimeAfterFail . begin ( ) ; i ! = _channelGetDifferenceTimeAfterFail . cend ( ) ; ) {
2015-09-13 11:41:27 +03:00
if ( i . value ( ) > now ) {
2015-09-13 20:27:29 +03:00
wait = wait ? qMin ( wait , i . value ( ) - now ) : ( i . value ( ) - now ) ;
2015-09-13 11:41:27 +03:00
+ + i ;
} else {
2016-10-24 00:03:10 +03:00
getChannelDifference ( i . key ( ) , ChannelDifferenceRequest : : AfterFail ) ;
2015-09-13 11:41:27 +03:00
i = _channelGetDifferenceTimeAfterFail . erase ( i ) ;
}
}
if ( wait ) {
_failDifferenceTimer . start ( wait ) ;
} else {
_failDifferenceTimer . stop ( ) ;
2014-05-30 12:53:19 +04:00
}
}
void MainWidget : : getDifference ( ) {
2015-03-02 15:34:16 +03:00
if ( this ! = App : : main ( ) ) return ;
2015-09-13 11:41:27 +03:00
_getDifferenceTimeByPts = 0 ;
2016-06-22 21:41:13 +03:00
if ( requestingDifference ( ) ) return ;
2014-11-05 20:43:32 +03:00
_bySeqUpdates . clear ( ) ;
_bySeqTimer . stop ( ) ;
noUpdatesTimer . stop ( ) ;
2015-09-13 11:41:27 +03:00
_getDifferenceTimeAfterFail = 0 ;
2014-11-05 20:43:32 +03:00
2015-09-13 11:41:27 +03:00
_ptsWaiter . setRequesting ( true ) ;
2016-10-24 00:03:10 +03:00
MTPupdates_GetDifference : : Flags flags = 0 ;
MTP : : send ( MTPupdates_GetDifference ( MTP_flags ( flags ) , MTP_int ( _ptsWaiter . current ( ) ) , MTPint ( ) , MTP_int ( updDate ) , MTP_int ( updQts ) ) , rpcDone ( & MainWidget : : gotDifference ) , rpcFail ( & MainWidget : : failDifference ) ) ;
2015-09-13 11:41:27 +03:00
}
2016-10-24 00:03:10 +03:00
void MainWidget : : getChannelDifference ( ChannelData * channel , ChannelDifferenceRequest from ) {
2015-09-13 11:41:27 +03:00
if ( this ! = App : : main ( ) | | ! channel ) return ;
2016-10-24 00:03:10 +03:00
if ( from ! = ChannelDifferenceRequest : : PtsGapOrShortPoll ) {
2015-09-13 11:41:27 +03:00
_channelGetDifferenceTimeByPts . remove ( channel ) ;
}
if ( ! channel - > ptsInited ( ) | | channel - > ptsRequesting ( ) ) return ;
2016-10-24 00:03:10 +03:00
if ( from ! = ChannelDifferenceRequest : : AfterFail ) {
2015-09-13 11:41:27 +03:00
_channelGetDifferenceTimeAfterFail . remove ( channel ) ;
}
channel - > ptsSetRequesting ( true ) ;
2015-09-20 12:54:22 +03:00
2016-05-27 19:47:46 +03:00
auto filter = MTP_channelMessagesFilterEmpty ( ) ;
2016-10-24 00:03:10 +03:00
MTPupdates_GetChannelDifference : : Flags flags = MTPupdates_GetChannelDifference : : Flag : : f_force ;
if ( from ! = ChannelDifferenceRequest : : PtsGapOrShortPoll ) {
if ( ! channel - > ptsWaitingForSkipped ( ) ) {
flags = 0 ; // No force flag when requesting for short poll.
}
}
MTP : : send ( MTPupdates_GetChannelDifference ( MTP_flags ( flags ) , channel - > inputChannel , filter , MTP_int ( channel - > pts ( ) ) , MTP_int ( MTPChannelGetDifferenceLimit ) ) , rpcDone ( & MainWidget : : gotChannelDifference , channel ) , rpcFail ( & MainWidget : : failChannelDifference , channel ) ) ;
2014-05-30 12:53:19 +04:00
}
2015-04-16 17:59:42 +03:00
void MainWidget : : mtpPing ( ) {
MTP : : ping ( ) ;
}
2014-05-30 12:53:19 +04:00
void MainWidget : : start ( const MTPUser & user ) {
2015-06-10 15:48:26 +03:00
int32 uid = user . c_user ( ) . vid . v ;
2015-03-02 15:34:16 +03:00
if ( MTP : : authedId ( ) ! = uid ) {
2016-09-21 14:44:20 +03:00
MTP : : setAuthedId ( uid ) ;
2015-03-02 15:34:16 +03:00
Local : : writeMtpData ( ) ;
}
2015-08-07 15:11:50 +03:00
Local : : readSavedPeers ( ) ;
2015-01-26 16:04:41 +03:00
cSetOtherOnline ( 0 ) ;
2016-11-16 13:44:06 +03:00
if ( auto self = App : : feedUsers ( MTP_vector < MTPUser > ( 1 , user ) ) ) {
self - > loadUserpic ( ) ;
}
2014-05-30 12:53:19 +04:00
MTP : : send ( MTPupdates_GetState ( ) , rpcDone ( & MainWidget : : gotState ) ) ;
update ( ) ;
2016-10-03 11:20:02 +03:00
2014-12-12 19:27:03 +03:00
_started = true ;
App : : wnd ( ) - > sendServiceHistoryRequest ( ) ;
2016-07-21 13:09:47 +03:00
Local : : readInstalledStickers ( ) ;
Local : : readFeaturedStickers ( ) ;
Local : : readRecentStickers ( ) ;
2015-12-28 00:37:48 +03:00
Local : : readSavedGifs ( ) ;
2016-04-13 00:31:28 +03:00
_history - > start ( ) ;
2016-10-03 11:20:02 +03:00
checkStartUrl ( ) ;
2014-12-12 19:27:03 +03:00
}
bool MainWidget : : started ( ) {
return _started ;
2014-12-03 16:10:32 +03:00
}
2016-10-03 11:20:02 +03:00
void MainWidget : : checkStartUrl ( ) {
if ( ! cStartUrl ( ) . isEmpty ( ) & & App : : self ( ) & & ! App : : passcoded ( ) ) {
auto url = cStartUrl ( ) ;
cSetStartUrl ( QString ( ) ) ;
openLocalUrl ( url ) ;
}
}
2014-12-03 16:10:32 +03:00
void MainWidget : : openLocalUrl ( const QString & url ) {
2016-09-07 12:04:57 +03:00
auto urlTrimmed = url . trimmed ( ) ;
if ( urlTrimmed . size ( ) > 8192 ) urlTrimmed = urlTrimmed . mid ( 0 , 8192 ) ;
2016-02-17 19:37:21 +03:00
2016-09-07 12:04:57 +03:00
if ( ! urlTrimmed . startsWith ( qstr ( " tg:// " ) , Qt : : CaseInsensitive ) ) {
2016-07-28 20:01:08 +03:00
return ;
}
2016-09-07 12:04:57 +03:00
auto command = urlTrimmed . midRef ( qstr ( " tg:// " ) . size ( ) ) ;
2016-02-17 19:37:21 +03:00
2016-07-28 20:01:08 +03:00
using namespace qthelp ;
auto matchOptions = RegExOption : : CaseInsensitive ;
2016-09-07 12:04:57 +03:00
if ( auto joinChatMatch = regex_match ( qsl ( " ^join/? \\ ?invite=([a-zA-Z0-9 \\ . \\ _ \\ -]+)(&|$) " ) , command , matchOptions ) ) {
2016-07-28 20:01:08 +03:00
joinGroupByHash ( joinChatMatch - > captured ( 1 ) ) ;
2016-09-07 12:04:57 +03:00
} else if ( auto stickerSetMatch = regex_match ( qsl ( " ^addstickers/? \\ ?set=([a-zA-Z0-9 \\ . \\ _]+) ( & | $ ) " ), command, matchOptions)) {
2016-07-28 20:01:08 +03:00
stickersBox ( MTP_inputStickerSetShortName ( MTP_string ( stickerSetMatch - > captured ( 1 ) ) ) ) ;
2016-09-07 12:04:57 +03:00
} else if ( auto shareUrlMatch = regex_match ( qsl ( " ^msg_url/? \\ ?(.+) ( # | $ ) " ), command, matchOptions)) {
2016-07-28 20:01:08 +03:00
auto params = url_parse_params ( shareUrlMatch - > captured ( 1 ) , UrlParamNameTransform : : ToLower ) ;
auto url = params . value ( qsl ( " url " ) ) ;
if ( ! url . isEmpty ( ) ) {
shareUrlLayer ( url , params . value ( " text " ) ) ;
}
2016-09-07 12:04:57 +03:00
} else if ( auto confirmPhoneMatch = regex_match ( qsl ( " ^confirmphone/? \\ ?(.+) ( # | $ ) " ), command, matchOptions)) {
2016-07-28 20:01:08 +03:00
auto params = url_parse_params ( confirmPhoneMatch - > captured ( 1 ) , UrlParamNameTransform : : ToLower ) ;
auto phone = params . value ( qsl ( " phone " ) ) ;
auto hash = params . value ( qsl ( " hash " ) ) ;
if ( ! phone . isEmpty ( ) & & ! hash . isEmpty ( ) ) {
ConfirmPhoneBox : : start ( phone , hash ) ;
}
2016-09-07 12:04:57 +03:00
} else if ( auto usernameMatch = regex_match ( qsl ( " ^resolve/? \\ ?(.+) ( # | $ ) " ), command, matchOptions)) {
2016-07-28 20:01:08 +03:00
auto params = url_parse_params ( usernameMatch - > captured ( 1 ) , UrlParamNameTransform : : ToLower ) ;
auto domain = params . value ( qsl ( " domain " ) ) ;
2016-09-28 19:23:25 +03:00
if ( regex_match ( qsl ( " ^[a-zA-Z0-9 \\ . \\ _]+$ " ) , domain , matchOptions ) ) {
2016-07-28 20:01:08 +03:00
auto start = qsl ( " start " ) ;
auto startToken = params . value ( start ) ;
if ( startToken . isEmpty ( ) ) {
start = qsl ( " startgroup " ) ;
startToken = params . value ( start ) ;
if ( startToken . isEmpty ( ) ) {
start = QString ( ) ;
2015-10-18 14:49:34 +02:00
}
}
2016-07-28 20:01:08 +03:00
auto post = ( start = = qsl ( " startgroup " ) ) ? ShowAtProfileMsgId : ShowAtUnreadMsgId ;
auto postParam = params . value ( qsl ( " post " ) ) ;
if ( auto postId = postParam . toInt ( ) ) {
post = postId ;
2015-10-18 14:49:34 +02:00
}
2016-09-28 19:23:25 +03:00
auto gameParam = params . value ( qsl ( " game " ) ) ;
if ( ! gameParam . isEmpty ( ) & & regex_match ( qsl ( " ^[a-zA-Z0-9 \\ . \\ _]+$ " ) , gameParam , matchOptions ) ) {
startToken = gameParam ;
post = ShowAtGameShareMsgId ;
}
2016-07-28 20:01:08 +03:00
openPeerByName ( domain , post , startToken ) ;
2015-10-18 14:49:34 +02:00
}
2016-09-07 12:04:57 +03:00
} else if ( auto shareGameScoreMatch = regex_match ( qsl ( " ^share_game_score/? \\ ?(.+) ( # | $ ) " ), command, matchOptions)) {
auto params = url_parse_params ( shareGameScoreMatch - > captured ( 1 ) , UrlParamNameTransform : : ToLower ) ;
shareGameScoreByHash ( params . value ( qsl ( " hash " ) ) ) ;
2014-12-03 16:10:32 +03:00
}
}
2016-02-17 19:37:21 +03:00
void MainWidget : : openPeerByName ( const QString & username , MsgId msgId , const QString & startToken ) {
2015-05-20 22:28:24 +03:00
App : : wnd ( ) - > hideMediaview ( ) ;
2015-09-06 13:17:09 +03:00
PeerData * peer = App : : peerByName ( username ) ;
if ( peer ) {
2016-09-28 19:23:25 +03:00
if ( msgId = = ShowAtGameShareMsgId ) {
if ( peer - > isUser ( ) & & peer - > asUser ( ) - > botInfo & & ! startToken . isEmpty ( ) ) {
peer - > asUser ( ) - > botInfo - > shareGameShortName = startToken ;
2016-12-13 20:07:56 +03:00
Ui : : show ( Box < ContactsBox > ( peer - > asUser ( ) ) ) ;
2016-09-28 19:23:25 +03:00
} else {
Ui : : showPeerHistoryAsync ( peer - > id , ShowAtUnreadMsgId , Ui : : ShowWay : : Forward ) ;
}
} else if ( msgId = = ShowAtProfileMsgId & & ! peer - > isChannel ( ) ) {
2015-09-06 13:17:09 +03:00
if ( peer - > isUser ( ) & & peer - > asUser ( ) - > botInfo & & ! peer - > asUser ( ) - > botInfo - > cantJoinGroups & & ! startToken . isEmpty ( ) ) {
peer - > asUser ( ) - > botInfo - > startGroupToken = startToken ;
2016-12-13 20:07:56 +03:00
Ui : : show ( Box < ContactsBox > ( peer - > asUser ( ) ) ) ;
2016-04-06 15:07:05 +04:00
} else if ( peer - > isUser ( ) & & peer - > asUser ( ) - > botInfo ) {
// Always open bot chats, even from mention links.
2016-07-05 17:48:36 +03:00
Ui : : showPeerHistoryAsync ( peer - > id , ShowAtUnreadMsgId , Ui : : ShowWay : : Forward ) ;
2015-06-17 22:43:03 +03:00
} else {
2016-05-19 15:03:51 +03:00
Ui : : showPeerProfile ( peer ) ;
2015-06-17 22:43:03 +03:00
}
2015-03-19 12:18:19 +03:00
} else {
2016-02-18 19:36:33 +03:00
if ( msgId = = ShowAtProfileMsgId | | ! peer - > isChannel ( ) ) { // show specific posts only in channels / supergroups
2016-02-17 19:37:21 +03:00
msgId = ShowAtUnreadMsgId ;
}
2015-09-06 13:17:09 +03:00
if ( peer - > isUser ( ) & & peer - > asUser ( ) - > botInfo ) {
peer - > asUser ( ) - > botInfo - > startToken = startToken ;
2016-04-13 00:31:28 +03:00
if ( peer = = _history - > peer ( ) ) {
_history - > updateControlsVisibility ( ) ;
2016-10-18 13:32:33 +03:00
_history - > updateControlsGeometry ( ) ;
2015-06-19 15:39:33 +03:00
}
}
2016-07-05 17:48:36 +03:00
Ui : : showPeerHistoryAsync ( peer - > id , msgId , Ui : : ShowWay : : Forward ) ;
2015-03-19 12:18:19 +03:00
}
2014-12-03 16:10:32 +03:00
} else {
2016-02-17 19:37:21 +03:00
MTP : : send ( MTPcontacts_ResolveUsername ( MTP_string ( username ) ) , rpcDone ( & MainWidget : : usernameResolveDone , qMakePair ( msgId , startToken ) ) , rpcFail ( & MainWidget : : usernameResolveFail , username ) ) ;
2014-12-03 16:10:32 +03:00
}
}
2015-04-30 16:53:36 +03:00
void MainWidget : : joinGroupByHash ( const QString & hash ) {
2015-05-20 22:28:24 +03:00
App : : wnd ( ) - > hideMediaview ( ) ;
2015-04-30 16:53:36 +03:00
MTP : : send ( MTPmessages_CheckChatInvite ( MTP_string ( hash ) ) , rpcDone ( & MainWidget : : inviteCheckDone , hash ) , rpcFail ( & MainWidget : : inviteCheckFail ) ) ;
}
2015-05-19 18:46:45 +03:00
void MainWidget : : stickersBox ( const MTPInputStickerSet & set ) {
2015-05-20 22:28:24 +03:00
App : : wnd ( ) - > hideMediaview ( ) ;
2016-12-13 20:07:56 +03:00
auto box = Ui : : show ( Box < StickerSetBox > ( set ) ) ;
2015-05-19 18:46:45 +03:00
connect ( box , SIGNAL ( installed ( uint64 ) ) , this , SLOT ( onStickersInstalled ( uint64 ) ) ) ;
}
void MainWidget : : onStickersInstalled ( uint64 setId ) {
2016-04-13 00:31:28 +03:00
_history - > stickersInstalled ( setId ) ;
2015-05-19 18:46:45 +03:00
}
2015-09-21 23:57:42 +03:00
void MainWidget : : onFullPeerUpdated ( PeerData * peer ) {
emit peerUpdated ( peer ) ;
}
void MainWidget : : onSelfParticipantUpdated ( ChannelData * channel ) {
History * h = App : : historyLoaded ( channel - > id ) ;
if ( _updatedChannels . contains ( channel ) ) {
_updatedChannels . remove ( channel ) ;
if ( ( h ? h : App : : history ( channel - > id ) ) - > isEmpty ( ) ) {
checkPeerHistory ( channel ) ;
} else {
2015-09-25 10:47:32 +03:00
h - > asChannelHistory ( ) - > checkJoinedMessage ( true ) ;
2016-04-13 00:31:28 +03:00
_history - > peerMessagesUpdated ( channel - > id ) ;
2015-09-21 23:57:42 +03:00
}
} else if ( h ) {
h - > asChannelHistory ( ) - > checkJoinedMessage ( ) ;
2016-04-13 00:31:28 +03:00
_history - > peerMessagesUpdated ( channel - > id ) ;
2015-09-21 23:57:42 +03:00
}
}
2015-10-01 17:05:05 +03:00
bool MainWidget : : contentOverlapped ( const QRect & globalRect ) {
2016-04-13 00:31:28 +03:00
return ( _history - > contentOverlapped ( globalRect ) | |
2016-10-14 20:10:15 +03:00
_playerPanel - > overlaps ( globalRect ) | |
_playerPlaylist - > overlaps ( globalRect ) | |
2016-10-12 22:34:25 +03:00
( _playerVolume & & _playerVolume - > overlaps ( globalRect ) ) | |
2016-04-13 00:31:28 +03:00
_mediaType - > overlaps ( globalRect ) ) ;
2015-10-01 17:05:05 +03:00
}
2016-02-17 19:37:21 +03:00
void MainWidget : : usernameResolveDone ( QPair < MsgId , QString > msgIdAndStartToken , const MTPcontacts_ResolvedPeer & result ) {
2015-12-07 21:09:05 +03:00
Ui : : hideLayer ( ) ;
2015-09-06 13:17:09 +03:00
if ( result . type ( ) ! = mtpc_contacts_resolvedPeer ) return ;
2016-04-08 14:44:35 +04:00
const auto & d ( result . c_contacts_resolvedPeer ( ) ) ;
2015-09-06 13:17:09 +03:00
App : : feedUsers ( d . vusers ) ;
App : : feedChats ( d . vchats ) ;
PeerId peerId = peerFromMTP ( d . vpeer ) ;
if ( ! peerId ) return ;
PeerData * peer = App : : peer ( peerId ) ;
2016-02-17 19:37:21 +03:00
MsgId msgId = msgIdAndStartToken . first ;
QString startToken = msgIdAndStartToken . second ;
if ( msgId = = ShowAtProfileMsgId & & ! peer - > isChannel ( ) ) {
if ( peer - > isUser ( ) & & peer - > asUser ( ) - > botInfo & & ! peer - > asUser ( ) - > botInfo - > cantJoinGroups & & ! startToken . isEmpty ( ) ) {
peer - > asUser ( ) - > botInfo - > startGroupToken = startToken ;
2016-12-13 20:07:56 +03:00
Ui : : show ( Box < ContactsBox > ( peer - > asUser ( ) ) ) ;
2016-04-12 01:34:29 +03:00
} else if ( peer - > isUser ( ) & & peer - > asUser ( ) - > botInfo ) {
// Always open bot chats, even from mention links.
2016-07-05 17:48:36 +03:00
Ui : : showPeerHistoryAsync ( peer - > id , ShowAtUnreadMsgId , Ui : : ShowWay : : Forward ) ;
2015-06-17 22:43:03 +03:00
} else {
2016-05-19 15:03:51 +03:00
Ui : : showPeerProfile ( peer ) ;
2015-06-17 22:43:03 +03:00
}
2015-03-19 12:18:19 +03:00
} else {
2016-02-18 19:36:33 +03:00
if ( msgId = = ShowAtProfileMsgId | | ! peer - > isChannel ( ) ) { // show specific posts only in channels / supergroups
2016-02-17 19:37:21 +03:00
msgId = ShowAtUnreadMsgId ;
}
2015-09-06 13:17:09 +03:00
if ( peer - > isUser ( ) & & peer - > asUser ( ) - > botInfo ) {
2016-02-17 19:37:21 +03:00
peer - > asUser ( ) - > botInfo - > startToken = startToken ;
2016-04-13 00:31:28 +03:00
if ( peer = = _history - > peer ( ) ) {
_history - > updateControlsVisibility ( ) ;
2016-10-18 13:32:33 +03:00
_history - > updateControlsGeometry ( ) ;
2015-06-19 15:39:33 +03:00
}
}
2016-09-01 21:37:30 -04:00
Ui : : showPeerHistory ( peer - > id , msgId , Ui : : ShowWay : : Forward ) ;
2015-03-19 12:18:19 +03:00
}
2014-05-30 12:53:19 +04:00
}
2014-12-05 16:44:27 +03:00
bool MainWidget : : usernameResolveFail ( QString name , const RPCError & error ) {
2016-04-08 14:44:35 +04:00
if ( MTP : : isDefaultHandledError ( error ) ) return false ;
2015-04-04 23:01:34 +03:00
2014-12-05 16:44:27 +03:00
if ( error . code ( ) = = 400 ) {
2016-12-13 20:07:56 +03:00
Ui : : show ( Box < InformBox > ( lng_username_not_found ( lt_user , name ) ) ) ;
2014-12-05 16:44:27 +03:00
}
return true ;
}
2015-04-30 16:53:36 +03:00
void MainWidget : : inviteCheckDone ( QString hash , const MTPChatInvite & invite ) {
switch ( invite . type ( ) ) {
case mtpc_chatInvite : {
2016-07-08 19:59:46 +03:00
auto & d ( invite . c_chatInvite ( ) ) ;
QVector < UserData * > participants ;
if ( d . has_participants ( ) ) {
auto & v = d . vparticipants . c_vector ( ) . v ;
participants . reserve ( v . size ( ) ) ;
for_const ( auto & user , v ) {
if ( auto feededUser = App : : feedUser ( user ) ) {
participants . push_back ( feededUser ) ;
}
}
}
2015-04-30 16:53:36 +03:00
_inviteHash = hash ;
2016-12-13 20:07:56 +03:00
Ui : : show ( Box < ConfirmInviteBox > ( qs ( d . vtitle ) , d . vphoto , d . vparticipants_count . v , participants ) ) ;
2015-04-30 16:53:36 +03:00
} break ;
case mtpc_chatInviteAlready : {
2016-04-08 14:44:35 +04:00
const auto & d ( invite . c_chatInviteAlready ( ) ) ;
2015-09-03 13:48:40 +03:00
PeerData * chat = App : : feedChats ( MTP_vector < MTPChat > ( 1 , d . vchat ) ) ;
2015-04-30 16:53:36 +03:00
if ( chat ) {
2015-12-13 14:36:08 +03:00
Ui : : showPeerHistory ( chat - > id , ShowAtUnreadMsgId ) ;
2015-04-30 16:53:36 +03:00
}
} break ;
}
}
bool MainWidget : : inviteCheckFail ( const RPCError & error ) {
2016-04-08 14:44:35 +04:00
if ( MTP : : isDefaultHandledError ( error ) ) return false ;
2015-04-30 16:53:36 +03:00
if ( error . code ( ) = = 400 ) {
2016-12-13 20:07:56 +03:00
Ui : : show ( Box < InformBox > ( lang ( lng_group_invite_bad_link ) ) ) ;
2015-04-30 16:53:36 +03:00
}
return true ;
}
void MainWidget : : onInviteImport ( ) {
if ( _inviteHash . isEmpty ( ) ) return ;
2015-10-29 11:26:41 -04:00
MTP : : send ( MTPmessages_ImportChatInvite ( MTP_string ( _inviteHash ) ) , rpcDone ( & MainWidget : : inviteImportDone ) , rpcFail ( & MainWidget : : inviteImportFail ) ) ;
2015-04-30 16:53:36 +03:00
}
void MainWidget : : inviteImportDone ( const MTPUpdates & updates ) {
App : : main ( ) - > sentUpdatesReceived ( updates ) ;
2015-12-07 21:09:05 +03:00
Ui : : hideLayer ( ) ;
2015-04-30 16:53:36 +03:00
const QVector < MTPChat > * v = 0 ;
switch ( updates . type ( ) ) {
case mtpc_updates : v = & updates . c_updates ( ) . vchats . c_vector ( ) . v ; break ;
case mtpc_updatesCombined : v = & updates . c_updatesCombined ( ) . vchats . c_vector ( ) . v ; break ;
2015-09-25 10:47:32 +03:00
default : LOG ( ( " API Error: unexpected update cons %1 (MainWidget::inviteImportDone) " ) . arg ( updates . type ( ) ) ) ; break ;
2015-04-30 16:53:36 +03:00
}
2015-09-21 23:57:42 +03:00
if ( v & & ! v - > isEmpty ( ) ) {
if ( v - > front ( ) . type ( ) = = mtpc_chat ) {
2015-12-13 14:36:08 +03:00
Ui : : showPeerHistory ( peerFromChat ( v - > front ( ) . c_chat ( ) . vid . v ) , ShowAtTheEndMsgId ) ;
2015-09-21 23:57:42 +03:00
} else if ( v - > front ( ) . type ( ) = = mtpc_channel ) {
2015-12-13 14:36:08 +03:00
Ui : : showPeerHistory ( peerFromChannel ( v - > front ( ) . c_channel ( ) . vid . v ) , ShowAtTheEndMsgId ) ;
2015-09-21 23:57:42 +03:00
}
2015-04-30 16:53:36 +03:00
}
}
bool MainWidget : : inviteImportFail ( const RPCError & error ) {
2016-04-08 14:44:35 +04:00
if ( MTP : : isDefaultHandledError ( error ) ) return false ;
2015-04-30 16:53:36 +03:00
2016-06-07 22:59:39 +03:00
if ( error . type ( ) = = qstr ( " CHANNELS_TOO_MUCH " ) ) {
2016-12-13 20:07:56 +03:00
Ui : : show ( Box < InformBox > ( lang ( lng_join_channel_error ) ) ) ;
2016-06-07 22:59:39 +03:00
} else if ( error . code ( ) = = 400 ) {
2016-12-13 20:07:56 +03:00
Ui : : show ( Box < InformBox > ( lang ( error . type ( ) = = qstr ( " USERS_TOO_MUCH " ) ? lng_group_invite_no_room : lng_group_invite_bad_link ) ) ) ;
2015-04-30 16:53:36 +03:00
}
2016-06-07 22:59:39 +03:00
2015-04-30 16:53:36 +03:00
return true ;
}
2014-05-30 12:53:19 +04:00
void MainWidget : : startFull ( const MTPVector < MTPUser > & users ) {
2016-04-08 14:44:35 +04:00
const auto & v ( users . c_vector ( ) . v ) ;
2015-10-28 20:16:52 -04:00
if ( v . isEmpty ( ) | | v [ 0 ] . type ( ) ! = mtpc_user | | ! v [ 0 ] . c_user ( ) . is_self ( ) ) { // wtf?..
2016-03-31 18:06:40 +04:00
return App : : logOutDelayed ( ) ;
2014-05-30 12:53:19 +04:00
}
start ( v [ 0 ] ) ;
}
2015-09-21 23:57:42 +03:00
void MainWidget : : applyNotifySetting ( const MTPNotifyPeer & peer , const MTPPeerNotifySettings & settings , History * h ) {
2016-05-12 19:05:20 +03:00
PeerData * updatePeer = nullptr ;
2016-06-02 16:57:49 +03:00
bool changed = false ;
2014-05-30 12:53:19 +04:00
switch ( settings . type ( ) ) {
case mtpc_peerNotifySettingsEmpty :
switch ( peer . type ( ) ) {
case mtpc_notifyAll : globalNotifyAllPtr = EmptyNotifySettings ; break ;
case mtpc_notifyUsers : globalNotifyUsersPtr = EmptyNotifySettings ; break ;
case mtpc_notifyChats : globalNotifyChatsPtr = EmptyNotifySettings ; break ;
case mtpc_notifyPeer : {
2016-06-02 16:57:49 +03:00
if ( ( updatePeer = App : : peerLoaded ( peerFromMTP ( peer . c_notifyPeer ( ) . vpeer ) ) ) ) {
changed = ( updatePeer - > notify ! = EmptyNotifySettings ) ;
if ( changed ) {
if ( updatePeer - > notify ! = UnknownNotifySettings ) {
delete updatePeer - > notify ;
}
updatePeer - > notify = EmptyNotifySettings ;
App : : unregMuted ( updatePeer ) ;
if ( ! h ) h = App : : history ( updatePeer - > id ) ;
h - > setMute ( false ) ;
2014-05-30 12:53:19 +04:00
}
}
} break ;
}
break ;
case mtpc_peerNotifySettings : {
2016-04-08 14:44:35 +04:00
const auto & d ( settings . c_peerNotifySettings ( ) ) ;
2014-05-30 12:53:19 +04:00
NotifySettingsPtr setTo = UnknownNotifySettings ;
switch ( peer . type ( ) ) {
case mtpc_notifyAll : setTo = globalNotifyAllPtr = & globalNotifyAll ; break ;
case mtpc_notifyUsers : setTo = globalNotifyUsersPtr = & globalNotifyUsers ; break ;
case mtpc_notifyChats : setTo = globalNotifyChatsPtr = & globalNotifyChats ; break ;
case mtpc_notifyPeer : {
2016-06-02 16:57:49 +03:00
if ( ( updatePeer = App : : peerLoaded ( peerFromMTP ( peer . c_notifyPeer ( ) . vpeer ) ) ) ) {
if ( updatePeer - > notify = = UnknownNotifySettings | | updatePeer - > notify = = EmptyNotifySettings ) {
changed = true ;
updatePeer - > notify = new NotifySettings ( ) ;
}
setTo = updatePeer - > notify ;
2014-05-30 12:53:19 +04:00
}
} break ;
}
if ( setTo = = UnknownNotifySettings ) break ;
2016-06-02 16:57:49 +03:00
changed = ( setTo - > flags ! = d . vflags . v ) | | ( setTo - > mute ! = d . vmute_until . v ) | | ( setTo - > sound ! = d . vsound . c_string ( ) . v ) ;
if ( changed ) {
setTo - > flags = d . vflags . v ;
setTo - > mute = d . vmute_until . v ;
setTo - > sound = d . vsound . c_string ( ) . v ;
if ( updatePeer ) {
if ( ! h ) h = App : : history ( updatePeer - > id ) ;
int32 changeIn = 0 ;
if ( isNotifyMuted ( setTo , & changeIn ) ) {
App : : wnd ( ) - > notifyClear ( h ) ;
h - > setMute ( true ) ;
App : : regMuted ( updatePeer , changeIn ) ;
} else {
h - > setMute ( false ) ;
}
2015-09-21 23:57:42 +03:00
}
2014-05-30 12:53:19 +04:00
}
} break ;
}
2015-12-02 20:17:53 +03:00
if ( updatePeer ) {
2016-04-13 00:31:28 +03:00
if ( _history - > peer ( ) = = updatePeer ) {
_history - > updateNotifySettings ( ) ;
2015-12-02 20:17:53 +03:00
}
2016-06-02 16:57:49 +03:00
if ( changed ) {
Notify : : peerUpdatedDelayed ( updatePeer , Notify : : PeerUpdate : : Flag : : NotificationsEnabled ) ;
2015-12-02 20:17:53 +03:00
}
2014-05-30 12:53:19 +04:00
}
}
2016-02-25 19:19:54 +03:00
void MainWidget : : updateNotifySetting ( PeerData * peer , NotifySettingStatus notify , SilentNotifiesStatus silent ) {
if ( notify = = NotifySettingDontChange & & silent = = SilentNotifiesDontChange ) return ;
2014-05-30 12:53:19 +04:00
updateNotifySettingPeers . insert ( peer ) ;
2015-04-30 16:53:36 +03:00
int32 muteFor = 86400 * 365 ;
2014-05-30 12:53:19 +04:00
if ( peer - > notify = = EmptyNotifySettings ) {
2016-02-25 19:19:54 +03:00
if ( notify = = NotifySettingSetMuted | | silent = = SilentNotifiesSetSilent ) {
2014-05-30 12:53:19 +04:00
peer - > notify = new NotifySettings ( ) ;
}
2016-02-25 19:19:54 +03:00
} else if ( peer - > notify = = UnknownNotifySettings ) {
peer - > notify = new NotifySettings ( ) ;
}
if ( peer - > notify ! = EmptyNotifySettings & & peer - > notify ! = UnknownNotifySettings ) {
if ( notify ! = NotifySettingDontChange ) {
peer - > notify - > sound = ( notify = = NotifySettingSetMuted ) ? " " : " default " ;
peer - > notify - > mute = ( notify = = NotifySettingSetMuted ) ? ( unixtime ( ) + muteFor ) : 0 ;
}
if ( silent = = SilentNotifiesSetSilent ) {
2016-03-19 19:55:15 +03:00
peer - > notify - > flags | = MTPDpeerNotifySettings : : Flag : : f_silent ;
2016-02-25 19:19:54 +03:00
} else if ( silent = = SilentNotifiesSetNotify ) {
2016-03-19 19:55:15 +03:00
peer - > notify - > flags & = ~ MTPDpeerNotifySettings : : Flag : : f_silent ;
2014-05-30 12:53:19 +04:00
}
2015-04-30 16:53:36 +03:00
}
2016-02-25 19:19:54 +03:00
if ( notify ! = NotifySettingDontChange ) {
if ( notify = = NotifySettingSetMuted ) {
App : : regMuted ( peer , muteFor + 1 ) ;
} else {
App : : unregMuted ( peer ) ;
}
App : : history ( peer - > id ) - > setMute ( notify = = NotifySettingSetMuted ) ;
2014-05-30 12:53:19 +04:00
}
2016-04-13 00:31:28 +03:00
if ( _history - > peer ( ) = = peer ) _history - > updateNotifySettings ( ) ;
2014-05-30 12:53:19 +04:00
updateNotifySettingTimer . start ( NotifySettingSaveTimeout ) ;
}
2015-01-02 17:55:24 +03:00
void MainWidget : : incrementSticker ( DocumentData * sticker ) {
2015-07-01 00:07:05 +03:00
if ( ! sticker | | ! sticker - > sticker ( ) ) return ;
2016-07-15 18:58:52 +03:00
if ( sticker - > sticker ( ) - > set . type ( ) = = mtpc_inputStickerSetEmpty ) return ;
2015-05-19 18:46:45 +03:00
2016-07-21 13:09:47 +03:00
bool writeRecentStickers = false ;
2016-07-15 18:58:52 +03:00
auto & sets = Global : : RefStickerSets ( ) ;
auto it = sets . find ( Stickers : : CloudRecentSetId ) ;
if ( it = = sets . cend ( ) ) {
if ( it = = sets . cend ( ) ) {
2016-07-29 11:29:15 +01:00
it = sets . insert ( Stickers : : CloudRecentSetId , Stickers : : Set ( Stickers : : CloudRecentSetId , 0 , lang ( lng_recent_stickers ) , QString ( ) , 0 , 0 , qFlags ( MTPDstickerSet_ClientFlag : : f_special ) ) ) ;
2016-07-15 18:58:52 +03:00
} else {
2016-07-29 11:29:15 +01:00
it - > title = lang ( lng_recent_stickers ) ;
2016-07-15 18:58:52 +03:00
}
}
auto index = it - > stickers . indexOf ( sticker ) ;
if ( index > 0 ) {
it - > stickers . removeAt ( index ) ;
}
if ( index ) {
it - > stickers . push_front ( sticker ) ;
2016-07-21 13:09:47 +03:00
writeRecentStickers = true ;
2016-07-15 18:58:52 +03:00
}
2015-05-19 18:46:45 +03:00
2016-07-15 18:58:52 +03:00
// Remove that sticker from old recent, now it is in cloud recent stickers.
2016-07-21 13:09:47 +03:00
bool writeOldRecent = false ;
2016-07-15 18:58:52 +03:00
auto & recent = cGetRecentStickers ( ) ;
for ( auto i = recent . begin ( ) , e = recent . end ( ) ; i ! = e ; + + i ) {
2015-01-02 17:55:24 +03:00
if ( i - > first = = sticker ) {
2016-07-21 13:09:47 +03:00
writeOldRecent = true ;
2016-07-15 18:58:52 +03:00
recent . erase ( i ) ;
2015-01-02 17:55:24 +03:00
break ;
}
}
2016-07-18 18:39:10 +03:00
while ( ! recent . isEmpty ( ) & & it - > stickers . size ( ) + recent . size ( ) > Global : : StickersRecentLimit ( ) ) {
2016-07-21 13:09:47 +03:00
writeOldRecent = true ;
2016-07-15 18:58:52 +03:00
recent . pop_back ( ) ;
2015-01-02 17:55:24 +03:00
}
2016-07-21 13:09:47 +03:00
if ( writeOldRecent ) {
2016-07-15 18:58:52 +03:00
Local : : writeUserSettings ( ) ;
}
2015-05-19 18:46:45 +03:00
2016-07-15 18:58:52 +03:00
// Remove that sticker from custom stickers, now it is in cloud recent stickers.
2016-07-21 13:09:47 +03:00
bool writeInstalledStickers = false ;
2016-07-15 18:58:52 +03:00
auto custom = sets . find ( Stickers : : CustomSetId ) ;
if ( custom ! = sets . cend ( ) ) {
int removeIndex = custom - > stickers . indexOf ( sticker ) ;
if ( removeIndex > = 0 ) {
custom - > stickers . removeAt ( removeIndex ) ;
if ( custom - > stickers . isEmpty ( ) ) {
sets . erase ( custom ) ;
2015-05-19 18:46:45 +03:00
}
2016-07-21 13:09:47 +03:00
writeInstalledStickers = true ;
2015-05-19 18:46:45 +03:00
}
}
2016-07-15 18:58:52 +03:00
2016-07-21 13:09:47 +03:00
if ( writeInstalledStickers ) {
Local : : writeInstalledStickers ( ) ;
}
if ( writeRecentStickers ) {
Local : : writeRecentStickers ( ) ;
2015-05-19 18:46:45 +03:00
}
2016-04-13 00:31:28 +03:00
_history - > updateRecentStickers ( ) ;
2015-01-02 17:55:24 +03:00
}
2014-05-30 12:53:19 +04:00
void MainWidget : : activate ( ) {
2015-10-17 16:52:26 +02:00
if ( _a_show . animating ( ) ) return ;
2016-05-19 15:03:51 +03:00
if ( ! _wideSection & & ! _overview ) {
2015-07-17 22:17:37 +03:00
if ( _hider ) {
if ( _hider - > wasOffered ( ) ) {
_hider - > setFocus ( ) ;
2014-05-30 12:53:19 +04:00
} else {
2016-04-13 00:31:28 +03:00
_dialogs - > activate ( ) ;
2014-05-30 12:53:19 +04:00
}
2015-12-07 21:09:05 +03:00
} else if ( App : : wnd ( ) & & ! Ui : : isLayerShown ( ) ) {
2014-07-18 14:37:34 +04:00
if ( ! cSendPaths ( ) . isEmpty ( ) ) {
2014-12-12 19:27:03 +03:00
forwardLayer ( - 1 ) ;
2016-04-13 00:31:28 +03:00
} else if ( _history - > peer ( ) ) {
_history - > activate ( ) ;
2014-07-18 14:37:34 +04:00
} else {
2016-04-13 00:31:28 +03:00
_dialogs - > activate ( ) ;
2014-07-18 14:37:34 +04:00
}
2014-05-30 12:53:19 +04:00
}
}
App : : wnd ( ) - > fixOrder ( ) ;
}
void MainWidget : : destroyData ( ) {
2016-04-13 00:31:28 +03:00
_history - > destroyData ( ) ;
_dialogs - > destroyData ( ) ;
2014-05-30 12:53:19 +04:00
}
void MainWidget : : updateOnlineDisplayIn ( int32 msecs ) {
2015-01-26 16:04:41 +03:00
_onlineUpdater . start ( msecs ) ;
2014-05-30 12:53:19 +04:00
}
bool MainWidget : : isActive ( ) const {
2015-10-17 16:52:26 +02:00
return ! _isIdle & & isVisible ( ) & & ! _a_show . animating ( ) ;
2014-05-30 12:53:19 +04:00
}
2016-06-03 15:45:33 +03:00
bool MainWidget : : doWeReadServerHistory ( ) const {
2016-06-06 18:16:52 +03:00
return isActive ( ) & & ! _wideSection & & ! _overview & & _history - > doWeReadServerHistory ( ) ;
2014-05-30 12:53:19 +04:00
}
2015-01-26 16:04:41 +03:00
bool MainWidget : : lastWasOnline ( ) const {
return _lastWasOnline ;
}
2016-12-01 22:20:33 +03:00
TimeMs MainWidget : : lastSetOnline ( ) const {
2015-01-26 16:04:41 +03:00
return _lastSetOnline ;
}
2014-05-30 12:53:19 +04:00
int32 MainWidget : : dlgsWidth ( ) const {
2016-04-13 00:31:28 +03:00
return _dialogs - > width ( ) ;
2014-05-30 12:53:19 +04:00
}
MainWidget : : ~ MainWidget ( ) {
2016-04-13 00:31:28 +03:00
if ( App : : main ( ) = = this ) _history - > showHistory ( 0 , 0 ) ;
2015-02-03 18:02:46 +03:00
2016-07-29 17:33:49 +01:00
if ( HistoryHider * hider = _hider ) {
_hider = nullptr ;
delete hider ;
}
2014-05-30 12:53:19 +04:00
MTP : : clearGlobalHandlers ( ) ;
2016-04-13 00:31:28 +03:00
2014-05-30 12:53:19 +04:00
if ( App : : wnd ( ) ) App : : wnd ( ) - > noMain ( this ) ;
}
2015-01-26 16:04:41 +03:00
void MainWidget : : updateOnline ( bool gotOtherOffline ) {
2015-03-02 15:34:16 +03:00
if ( this ! = App : : main ( ) ) return ;
App : : wnd ( ) - > checkAutoLock ( ) ;
2015-01-26 16:04:41 +03:00
bool isOnline = App : : wnd ( ) - > isActive ( ) ;
2016-02-18 19:36:33 +03:00
int updateIn = Global : : OnlineUpdatePeriod ( ) ;
2015-01-26 16:04:41 +03:00
if ( isOnline ) {
2016-12-01 22:20:33 +03:00
auto idle = psIdleTime ( ) ;
if ( idle > = Global : : OfflineIdleTimeout ( ) ) {
2015-01-26 16:04:41 +03:00
isOnline = false ;
if ( ! _isIdle ) {
_isIdle = true ;
_idleFinishTimer . start ( 900 ) ;
}
} else {
2016-02-18 19:36:33 +03:00
updateIn = qMin ( updateIn , int ( Global : : OfflineIdleTimeout ( ) - idle ) ) ;
2015-01-26 16:04:41 +03:00
}
2014-05-30 12:53:19 +04:00
}
2016-12-01 22:20:33 +03:00
auto ms = getms ( true ) ;
2016-02-18 19:36:33 +03:00
if ( isOnline ! = _lastWasOnline | | ( isOnline & & _lastSetOnline + Global : : OnlineUpdatePeriod ( ) < = ms ) | | ( isOnline & & gotOtherOffline ) ) {
2015-01-26 16:04:41 +03:00
if ( _onlineRequest ) {
MTP : : cancel ( _onlineRequest ) ;
_onlineRequest = 0 ;
}
_lastWasOnline = isOnline ;
_lastSetOnline = ms ;
_onlineRequest = MTP : : send ( MTPaccount_UpdateStatus ( MTP_bool ( ! isOnline ) ) ) ;
2016-06-03 21:24:27 +03:00
if ( App : : self ( ) ) {
App : : self ( ) - > onlineTill = unixtime ( ) + ( isOnline ? ( Global : : OnlineUpdatePeriod ( ) / 1000 ) : - 1 ) ;
2016-06-03 10:20:24 +03:00
Notify : : peerUpdatedDelayed ( App : : self ( ) , Notify : : PeerUpdate : : Flag : : UserOnlineChanged ) ;
2016-06-03 21:24:27 +03:00
}
if ( ! isOnline ) { // Went offline, so we need to save message draft to the cloud.
saveDraftToCloud ( ) ;
}
2015-01-26 16:04:41 +03:00
2016-06-03 21:24:27 +03:00
_lastSetOnline = ms ;
2015-01-26 16:04:41 +03:00
updateOnlineDisplay ( ) ;
} else if ( isOnline ) {
2016-02-18 19:36:33 +03:00
updateIn = qMin ( updateIn , int ( _lastSetOnline + Global : : OnlineUpdatePeriod ( ) - ms ) ) ;
2014-05-30 12:53:19 +04:00
}
2015-01-26 16:04:41 +03:00
_onlineTimer . start ( updateIn ) ;
2014-05-30 12:53:19 +04:00
}
2016-06-03 21:24:27 +03:00
void MainWidget : : saveDraftToCloud ( ) {
_history - > saveFieldToHistoryLocalDraft ( ) ;
auto peer = _history - > peer ( ) ;
if ( auto history = App : : historyLoaded ( peer ) ) {
2016-06-09 17:31:10 +03:00
writeDrafts ( history ) ;
2016-06-03 21:24:27 +03:00
auto localDraft = history - > localDraft ( ) ;
auto cloudDraft = history - > cloudDraft ( ) ;
2016-06-09 17:31:10 +03:00
if ( ! Data : : draftsAreEqual ( localDraft , cloudDraft ) ) {
2016-06-07 22:59:39 +03:00
App : : api ( ) - > saveDraftToCloudDelayed ( history ) ;
2016-06-03 21:24:27 +03:00
}
}
}
void MainWidget : : applyCloudDraft ( History * history ) {
_history - > applyCloudDraft ( history ) ;
}
2016-06-09 17:31:10 +03:00
void MainWidget : : writeDrafts ( History * history ) {
Local : : MessageDraft storedLocalDraft , storedEditDraft ;
MessageCursor localCursor , editCursor ;
if ( auto localDraft = history - > localDraft ( ) ) {
if ( ! Data : : draftsAreEqual ( localDraft , history - > cloudDraft ( ) ) ) {
storedLocalDraft = Local : : MessageDraft ( localDraft - > msgId , localDraft - > textWithTags , localDraft - > previewCancelled ) ;
localCursor = localDraft - > cursor ;
}
}
if ( auto editDraft = history - > editDraft ( ) ) {
storedEditDraft = Local : : MessageDraft ( editDraft - > msgId , editDraft - > textWithTags , editDraft - > previewCancelled ) ;
editCursor = editDraft - > cursor ;
}
Local : : writeDrafts ( history - > peer - > id , storedLocalDraft , storedEditDraft ) ;
Local : : writeDraftCursors ( history - > peer - > id , localCursor , editCursor ) ;
}
2015-01-26 16:04:41 +03:00
void MainWidget : : checkIdleFinish ( ) {
2015-03-02 15:34:16 +03:00
if ( this ! = App : : main ( ) ) return ;
2016-12-01 22:20:33 +03:00
if ( psIdleTime ( ) < Global : : OfflineIdleTimeout ( ) ) {
2015-01-26 16:04:41 +03:00
_idleFinishTimer . stop ( ) ;
_isIdle = false ;
updateOnline ( ) ;
if ( App : : wnd ( ) ) App : : wnd ( ) - > checkHistoryActivation ( ) ;
} else {
_idleFinishTimer . start ( 900 ) ;
}
2014-05-30 12:53:19 +04:00
}
void MainWidget : : updateReceived ( const mtpPrime * from , const mtpPrime * end ) {
if ( end < = from | | ! MTP : : authedId ( ) ) return ;
2015-03-02 15:34:16 +03:00
App : : wnd ( ) - > checkAutoLock ( ) ;
2015-12-31 23:27:21 +08:00
2014-06-14 23:32:11 +04:00
if ( mtpTypeId ( * from ) = = mtpc_new_session_created ) {
2014-05-30 12:53:19 +04:00
MTPNewSession newSession ( from , end ) ;
updSeq = 0 ;
2015-04-30 16:53:36 +03:00
MTP_LOG ( 0 , ( " getDifference { after new_session_created }%1 " ) . arg ( cTestMode ( ) ? " TESTMODE " : " " ) ) ;
2014-05-30 12:53:19 +04:00
return getDifference ( ) ;
} else {
try {
MTPUpdates updates ( from , end ) ;
2014-11-12 23:30:26 +03:00
_lastUpdateTime = getms ( true ) ;
2014-05-30 12:53:19 +04:00
noUpdatesTimer . start ( NoUpdatesTimeout ) ;
2016-06-22 21:41:13 +03:00
if ( ! requestingDifference ( ) ) {
2015-09-21 23:57:42 +03:00
feedUpdates ( updates ) ;
}
2016-03-20 11:16:35 +03:00
} catch ( mtpErrorUnexpected & ) { // just some other type
2014-11-05 20:43:32 +03:00
}
}
update ( ) ;
}
2014-05-30 12:53:19 +04:00
2016-05-09 13:07:25 +03:00
namespace {
bool fwdInfoDataLoaded ( const MTPMessageFwdHeader & header ) {
if ( header . type ( ) ! = mtpc_messageFwdHeader ) {
return true ;
}
auto & info = header . c_messageFwdHeader ( ) ;
if ( info . has_channel_id ( ) ) {
if ( ! App : : channelLoaded ( peerFromChannel ( info . vchannel_id ) ) ) {
return false ;
}
if ( info . has_from_id ( ) & & ! App : : user ( peerFromUser ( info . vfrom_id ) , PeerData : : MinimalLoaded ) ) {
return false ;
}
} else {
if ( info . has_from_id ( ) & & ! App : : userLoaded ( peerFromUser ( info . vfrom_id ) ) ) {
return false ;
}
}
return true ;
}
bool mentionUsersLoaded ( const MTPVector < MTPMessageEntity > & entities ) {
for_const ( auto & entity , entities . c_vector ( ) . v ) {
auto type = entity . type ( ) ;
if ( type = = mtpc_messageEntityMentionName ) {
if ( ! App : : userLoaded ( peerFromUser ( entity . c_messageEntityMentionName ( ) . vuser_id ) ) ) {
return false ;
}
} else if ( type = = mtpc_inputMessageEntityMentionName ) {
auto & inputUser = entity . c_inputMessageEntityMentionName ( ) . vuser_id ;
if ( inputUser . type ( ) = = mtpc_inputUser ) {
if ( ! App : : userLoaded ( peerFromUser ( inputUser . c_inputUser ( ) . vuser_id ) ) ) {
return false ;
}
}
}
}
return true ;
}
enum class DataIsLoadedResult {
NotLoaded = 0 ,
FromNotLoaded = 1 ,
MentionNotLoaded = 2 ,
Ok = 3 ,
} ;
DataIsLoadedResult allDataLoadedForMessage ( const MTPMessage & msg ) {
switch ( msg . type ( ) ) {
case mtpc_message : {
const MTPDmessage & d ( msg . c_message ( ) ) ;
if ( ! d . is_post ( ) & & d . has_from_id ( ) ) {
if ( ! App : : userLoaded ( peerFromUser ( d . vfrom_id ) ) ) {
return DataIsLoadedResult : : FromNotLoaded ;
}
}
if ( d . has_via_bot_id ( ) ) {
if ( ! App : : userLoaded ( peerFromUser ( d . vvia_bot_id ) ) ) {
return DataIsLoadedResult : : NotLoaded ;
}
}
if ( d . has_fwd_from ( ) & & ! fwdInfoDataLoaded ( d . vfwd_from ) ) {
return DataIsLoadedResult : : NotLoaded ;
}
if ( d . has_entities ( ) & & ! mentionUsersLoaded ( d . ventities ) ) {
return DataIsLoadedResult : : MentionNotLoaded ;
}
} break ;
case mtpc_messageService : {
const MTPDmessageService & d ( msg . c_messageService ( ) ) ;
if ( ! d . is_post ( ) & & d . has_from_id ( ) ) {
if ( ! App : : userLoaded ( peerFromUser ( d . vfrom_id ) ) ) {
return DataIsLoadedResult : : FromNotLoaded ;
}
}
switch ( d . vaction . type ( ) ) {
case mtpc_messageActionChatAddUser : {
for_const ( const MTPint & userId , d . vaction . c_messageActionChatAddUser ( ) . vusers . c_vector ( ) . v ) {
if ( ! App : : userLoaded ( peerFromUser ( userId ) ) ) {
return DataIsLoadedResult : : NotLoaded ;
}
}
} break ;
case mtpc_messageActionChatJoinedByLink : {
if ( ! App : : userLoaded ( peerFromUser ( d . vaction . c_messageActionChatJoinedByLink ( ) . vinviter_id ) ) ) {
return DataIsLoadedResult : : NotLoaded ;
}
} break ;
case mtpc_messageActionChatDeleteUser : {
if ( ! App : : userLoaded ( peerFromUser ( d . vaction . c_messageActionChatDeleteUser ( ) . vuser_id ) ) ) {
return DataIsLoadedResult : : NotLoaded ;
}
} break ;
}
} break ;
}
return DataIsLoadedResult : : Ok ;
}
} // namespace
2015-09-21 23:57:42 +03:00
void MainWidget : : feedUpdates ( const MTPUpdates & updates , uint64 randomId ) {
2014-11-05 20:43:32 +03:00
switch ( updates . type ( ) ) {
case mtpc_updates : {
2016-09-26 15:09:59 +03:00
auto & d = updates . c_updates ( ) ;
2014-11-05 20:43:32 +03:00
if ( d . vseq . v ) {
if ( d . vseq . v < = updSeq ) return ;
if ( d . vseq . v > updSeq + 1 ) {
_bySeqUpdates . insert ( d . vseq . v , updates ) ;
2015-03-13 16:01:25 +03:00
return _bySeqTimer . start ( WaitForSkippedTimeout ) ;
2014-11-05 20:43:32 +03:00
}
}
2014-05-30 12:53:19 +04:00
2016-06-02 16:57:49 +03:00
App : : feedUsers ( d . vusers ) ;
App : : feedChats ( d . vchats ) ;
2015-09-21 23:57:42 +03:00
feedUpdateVector ( d . vupdates ) ;
2014-05-30 12:53:19 +04:00
2015-03-13 16:01:25 +03:00
updSetState ( 0 , d . vdate . v , updQts , d . vseq . v ) ;
2014-11-05 20:43:32 +03:00
} break ;
2014-05-30 12:53:19 +04:00
2014-11-05 20:43:32 +03:00
case mtpc_updatesCombined : {
2016-09-26 15:09:59 +03:00
auto & d = updates . c_updatesCombined ( ) ;
2014-11-05 20:43:32 +03:00
if ( d . vseq_start . v ) {
if ( d . vseq_start . v < = updSeq ) return ;
if ( d . vseq_start . v > updSeq + 1 ) {
_bySeqUpdates . insert ( d . vseq_start . v , updates ) ;
2015-03-13 16:01:25 +03:00
return _bySeqTimer . start ( WaitForSkippedTimeout ) ;
2014-11-05 20:43:32 +03:00
}
}
2014-05-30 12:53:19 +04:00
2016-06-02 16:57:49 +03:00
App : : feedUsers ( d . vusers ) ;
App : : feedChats ( d . vchats ) ;
2015-09-21 23:57:42 +03:00
feedUpdateVector ( d . vupdates ) ;
2014-05-30 12:53:19 +04:00
2015-03-13 16:01:25 +03:00
updSetState ( 0 , d . vdate . v , updQts , d . vseq . v ) ;
2014-11-05 20:43:32 +03:00
} break ;
2014-05-30 12:53:19 +04:00
2014-11-05 20:43:32 +03:00
case mtpc_updateShort : {
2016-09-26 15:09:59 +03:00
auto & d = updates . c_updateShort ( ) ;
2014-11-05 20:43:32 +03:00
feedUpdate ( d . vupdate ) ;
2014-05-30 12:53:19 +04:00
2015-03-13 16:01:25 +03:00
updSetState ( 0 , d . vdate . v , updQts , updSeq ) ;
2014-11-05 20:43:32 +03:00
} break ;
2014-05-30 12:53:19 +04:00
2014-11-05 20:43:32 +03:00
case mtpc_updateShortMessage : {
2016-09-26 15:09:59 +03:00
auto & d = updates . c_updateShortMessage ( ) ;
2016-05-09 13:07:25 +03:00
if ( ! App : : userLoaded ( d . vuser_id . v )
| | ( d . has_via_bot_id ( ) & & ! App : : userLoaded ( d . vvia_bot_id . v ) )
| | ( d . has_entities ( ) & & ! mentionUsersLoaded ( d . ventities ) )
| | ( d . has_fwd_from ( ) & & ! fwdInfoDataLoaded ( d . vfwd_from ) ) ) {
2015-04-30 16:53:36 +03:00
MTP_LOG ( 0 , ( " getDifference { good - getting user for updateShortMessage }%1 " ) . arg ( cTestMode ( ) ? " TESTMODE " : " " ) ) ;
2015-03-20 00:56:13 +03:00
return getDifference ( ) ;
}
2015-09-13 11:41:27 +03:00
if ( ! ptsUpdated ( d . vpts . v , d . vpts_count . v , updates ) ) {
2015-03-13 16:01:25 +03:00
return ;
2014-11-05 20:43:32 +03:00
}
2015-09-20 12:54:22 +03:00
// update before applying skipped
2016-03-19 19:55:15 +03:00
MTPDmessage : : Flags flags = mtpCastFlags ( d . vflags . v ) | MTPDmessage : : Flag : : f_from_id ;
2016-09-26 15:09:59 +03:00
auto item = App : : histories ( ) . addNewMessage ( MTP_message ( MTP_flags ( flags ) , d . vid , d . is_out ( ) ? MTP_int ( MTP : : authedId ( ) ) : d . vuser_id , MTP_peerUser ( d . is_out ( ) ? d . vuser_id : MTP_int ( MTP : : authedId ( ) ) ) , d . vfwd_from , d . vvia_bot_id , d . vreply_to_msg_id , d . vdate , d . vmessage , MTP_messageMediaEmpty ( ) , MTPnullMarkup , d . has_entities ( ) ? d . ventities : MTPnullEntities , MTPint ( ) , MTPint ( ) ) , NewMessageUnread ) ;
2014-11-05 20:43:32 +03:00
if ( item ) {
2016-04-13 00:31:28 +03:00
_history - > peerMessagesUpdated ( item - > history ( ) - > peer - > id ) ;
2014-11-05 20:43:32 +03:00
}
2014-05-30 12:53:19 +04:00
2015-09-20 12:54:22 +03:00
ptsApplySkippedUpdates ( ) ;
2015-03-13 16:01:25 +03:00
updSetState ( 0 , d . vdate . v , updQts , updSeq ) ;
2014-11-05 20:43:32 +03:00
} break ;
2014-05-30 12:53:19 +04:00
2014-11-05 20:43:32 +03:00
case mtpc_updateShortChatMessage : {
2016-09-26 15:09:59 +03:00
auto & d = updates . c_updateShortChatMessage ( ) ;
2015-05-08 16:06:53 +03:00
bool noFrom = ! App : : userLoaded ( d . vfrom_id . v ) ;
2016-05-09 13:07:25 +03:00
if ( ! App : : chatLoaded ( d . vchat_id . v )
| | noFrom
| | ( d . has_via_bot_id ( ) & & ! App : : userLoaded ( d . vvia_bot_id . v ) )
| | ( d . has_entities ( ) & & ! mentionUsersLoaded ( d . ventities ) )
| | ( d . has_fwd_from ( ) & & ! fwdInfoDataLoaded ( d . vfwd_from ) ) ) {
2015-04-30 16:53:36 +03:00
MTP_LOG ( 0 , ( " getDifference { good - getting user for updateShortChatMessage }%1 " ) . arg ( cTestMode ( ) ? " TESTMODE " : " " ) ) ;
2015-10-03 14:33:51 +03:00
if ( noFrom & & App : : api ( ) ) App : : api ( ) - > requestFullPeer ( App : : chatLoaded ( d . vchat_id . v ) ) ;
2015-03-20 00:56:13 +03:00
return getDifference ( ) ;
}
2015-09-13 11:41:27 +03:00
if ( ! ptsUpdated ( d . vpts . v , d . vpts_count . v , updates ) ) {
2015-03-13 16:01:25 +03:00
return ;
2014-05-30 12:53:19 +04:00
}
2015-09-20 12:54:22 +03:00
// update before applying skipped
2016-03-19 19:55:15 +03:00
MTPDmessage : : Flags flags = mtpCastFlags ( d . vflags . v ) | MTPDmessage : : Flag : : f_from_id ;
2016-09-26 15:09:59 +03:00
auto item = App : : histories ( ) . addNewMessage ( MTP_message ( MTP_flags ( flags ) , d . vid , d . vfrom_id , MTP_peerChat ( d . vchat_id ) , d . vfwd_from , d . vvia_bot_id , d . vreply_to_msg_id , d . vdate , d . vmessage , MTP_messageMediaEmpty ( ) , MTPnullMarkup , d . has_entities ( ) ? d . ventities : MTPnullEntities , MTPint ( ) , MTPint ( ) ) , NewMessageUnread ) ;
2014-11-05 20:43:32 +03:00
if ( item ) {
2016-04-13 00:31:28 +03:00
_history - > peerMessagesUpdated ( item - > history ( ) - > peer - > id ) ;
2014-11-05 20:43:32 +03:00
}
2015-09-20 12:54:22 +03:00
ptsApplySkippedUpdates ( ) ;
2015-03-13 16:01:25 +03:00
updSetState ( 0 , d . vdate . v , updQts , updSeq ) ;
2014-11-05 20:43:32 +03:00
} break ;
2015-08-30 17:57:21 +03:00
case mtpc_updateShortSentMessage : {
2016-09-26 15:09:59 +03:00
auto & d = updates . c_updateShortSentMessage ( ) ;
2015-08-30 17:57:21 +03:00
if ( randomId ) {
2015-09-03 13:48:40 +03:00
PeerId peerId = 0 ;
QString text ;
App : : histSentDataByItem ( randomId , peerId , text ) ;
2015-08-30 17:57:21 +03:00
feedUpdate ( MTP_updateMessageID ( d . vid , MTP_long ( randomId ) ) ) ; // ignore real date
2015-09-03 13:48:40 +03:00
if ( peerId ) {
2016-05-06 20:33:48 +03:00
if ( auto item = App : : histItemById ( peerToChannel ( peerId ) , d . vid . v ) ) {
2016-05-09 13:07:25 +03:00
if ( d . has_entities ( ) & & ! mentionUsersLoaded ( d . ventities ) ) {
2016-09-26 15:09:59 +03:00
api ( ) - > requestMessageData ( item - > history ( ) - > peer - > asChannel ( ) , item - > id , ApiWrap : : RequestMessageDataCallback ( ) ) ;
2016-05-09 13:07:25 +03:00
}
2016-05-06 20:33:48 +03:00
auto entities = d . has_entities ( ) ? entitiesFromMTP ( d . ventities . c_vector ( ) . v ) : EntitiesInText ( ) ;
item - > setText ( { text , entities } ) ;
2016-04-01 14:23:40 +04:00
item - > updateMedia ( d . has_media ( ) ? ( & d . vmedia ) : nullptr ) ;
2016-01-03 09:43:42 +08:00
item - > addToOverview ( AddToOverviewNew ) ;
2015-09-03 13:48:40 +03:00
}
2015-08-30 17:57:21 +03:00
}
}
2015-12-31 23:27:21 +08:00
2015-09-13 11:41:27 +03:00
if ( ! ptsUpdated ( d . vpts . v , d . vpts_count . v , updates ) ) {
2015-08-30 17:57:21 +03:00
return ;
}
2015-09-20 12:54:22 +03:00
// update before applying skipped
ptsApplySkippedUpdates ( ) ;
2015-08-30 17:57:21 +03:00
updSetState ( 0 , d . vdate . v , updQts , updSeq ) ;
} break ;
2014-11-05 20:43:32 +03:00
case mtpc_updatesTooLong : {
2015-04-30 16:53:36 +03:00
MTP_LOG ( 0 , ( " getDifference { good - updatesTooLong received }%1 " ) . arg ( cTestMode ( ) ? " TESTMODE " : " " ) ) ;
2014-11-05 20:43:32 +03:00
return getDifference ( ) ;
} break ;
2014-05-30 12:53:19 +04:00
}
}
void MainWidget : : feedUpdate ( const MTPUpdate & update ) {
if ( ! MTP : : authedId ( ) ) return ;
switch ( update . type ( ) ) {
case mtpc_updateNewMessage : {
2016-07-21 20:35:55 +03:00
auto & d = update . c_updateNewMessage ( ) ;
DataIsLoadedResult isDataLoaded = allDataLoadedForMessage ( d . vmessage ) ;
if ( ! requestingDifference ( ) & & isDataLoaded ! = DataIsLoadedResult : : Ok ) {
MTP_LOG ( 0 , ( " getDifference { good - after not all data loaded in updateNewMessage }%1 " ) . arg ( cTestMode ( ) ? " TESTMODE " : " " ) ) ;
// This can be if this update was created by grouping
// some short message update into an updates vector.
return getDifference ( ) ;
}
2015-09-20 12:54:22 +03:00
2015-09-13 11:41:27 +03:00
if ( ! ptsUpdated ( d . vpts . v , d . vpts_count . v , update ) ) {
2015-03-13 16:01:25 +03:00
return ;
}
2015-09-20 12:54:22 +03:00
// update before applying skipped
2015-10-15 02:15:28 +02:00
bool needToAdd = true ;
2016-04-13 00:31:28 +03:00
if ( d . vmessage . type ( ) = = mtpc_message ) { // index forwarded messages to links _overview
2015-10-15 02:15:28 +02:00
if ( App : : checkEntitiesAndViewsUpdate ( d . vmessage . c_message ( ) ) ) { // already in blocks
LOG ( ( " Skipping message, because it is already in blocks! " ) ) ;
needToAdd = false ;
}
2015-09-02 00:33:44 +03:00
}
2015-10-15 02:15:28 +02:00
if ( needToAdd ) {
2016-09-27 16:37:18 +03:00
if ( auto item = App : : histories ( ) . addNewMessage ( d . vmessage , NewMessageUnread ) ) {
2016-04-13 00:31:28 +03:00
_history - > peerMessagesUpdated ( item - > history ( ) - > peer - > id ) ;
2015-10-15 02:15:28 +02:00
}
2014-07-04 15:12:54 +04:00
}
2015-09-20 12:54:22 +03:00
ptsApplySkippedUpdates ( ) ;
2014-05-30 12:53:19 +04:00
} break ;
case mtpc_updateMessageID : {
2016-09-27 16:37:18 +03:00
auto & d = update . c_updateMessageID ( ) ;
auto msg = App : : histItemByRandom ( d . vrandom_id . v ) ;
2015-09-03 13:48:40 +03:00
if ( msg . msg ) {
2016-09-27 16:37:18 +03:00
if ( auto msgRow = App : : histItemById ( msg ) ) {
2015-12-23 15:55:32 +03:00
if ( App : : histItemById ( msg . channel , d . vid . v ) ) {
2017-01-01 20:45:20 +04:00
auto history = msgRow - > history ( ) ;
auto wasLast = ( history - > lastMsg = = msgRow ) ;
2014-05-30 12:53:19 +04:00
msgRow - > destroy ( ) ;
2017-01-01 20:45:20 +04:00
if ( wasLast & & ! history - > lastMsg ) {
checkPeerHistory ( history - > peer ) ;
2015-09-19 12:13:21 +03:00
}
2016-04-13 00:31:28 +03:00
_history - > peerMessagesUpdated ( ) ;
2015-12-23 15:55:32 +03:00
} else {
App : : historyUnregItem ( msgRow ) ;
if ( App : : wnd ( ) ) App : : wnd ( ) - > changingMsgId ( msgRow , d . vid . v ) ;
msgRow - > setId ( d . vid . v ) ;
if ( msgRow - > history ( ) - > peer - > isSelf ( ) ) {
2016-12-01 22:20:33 +03:00
msgRow - > history ( ) - > unregSendAction ( App : : self ( ) ) ;
2015-12-23 15:55:32 +03:00
}
App : : historyRegItem ( msgRow ) ;
2015-12-28 00:37:48 +03:00
Ui : : repaintHistoryItem ( msgRow ) ;
2014-05-30 12:53:19 +04:00
}
}
App : : historyUnregRandom ( d . vrandom_id . v ) ;
}
2015-09-03 13:48:40 +03:00
App : : historyUnregSentData ( d . vrandom_id . v ) ;
2014-05-30 12:53:19 +04:00
} break ;
2015-04-30 16:53:36 +03:00
case mtpc_updateReadMessagesContents : {
2016-09-27 16:37:18 +03:00
auto & d = update . c_updateReadMessagesContents ( ) ;
2015-09-20 12:54:22 +03:00
2015-09-13 11:41:27 +03:00
if ( ! ptsUpdated ( d . vpts . v , d . vpts_count . v , update ) ) {
2015-03-13 16:01:25 +03:00
return ;
}
2015-09-20 12:54:22 +03:00
// update before applying skipped
2016-09-27 16:37:18 +03:00
auto & v = d . vmessages . c_vector ( ) . v ;
2015-04-30 16:53:36 +03:00
for ( int32 i = 0 , l = v . size ( ) ; i < l ; + + i ) {
2015-09-03 13:48:40 +03:00
if ( HistoryItem * item = App : : histItemById ( NoChannel , v . at ( i ) . v ) ) {
2015-04-30 16:53:36 +03:00
if ( item - > isMediaUnread ( ) ) {
item - > markMediaRead ( ) ;
2015-12-28 00:37:48 +03:00
Ui : : repaintHistoryItem ( item ) ;
2016-06-22 21:41:13 +03:00
2015-09-03 13:48:40 +03:00
if ( item - > out ( ) & & item - > history ( ) - > peer - > isUser ( ) ) {
2016-06-22 21:41:13 +03:00
auto when = requestingDifference ( ) ? 0 : unixtime ( ) ;
item - > history ( ) - > peer - > asUser ( ) - > madeAction ( when ) ;
2015-06-28 15:37:10 +03:00
}
2015-04-30 16:53:36 +03:00
}
}
}
2015-09-20 12:54:22 +03:00
ptsApplySkippedUpdates ( ) ;
2015-03-13 16:01:25 +03:00
} break ;
case mtpc_updateReadHistoryInbox : {
2016-09-27 16:37:18 +03:00
auto & d = update . c_updateReadHistoryInbox ( ) ;
2015-09-20 12:54:22 +03:00
2015-09-13 11:41:27 +03:00
if ( ! ptsUpdated ( d . vpts . v , d . vpts_count . v , update ) ) {
2015-03-13 16:01:25 +03:00
return ;
}
2015-09-20 12:54:22 +03:00
// update before applying skipped
2015-09-03 13:48:40 +03:00
App : : feedInboxRead ( peerFromMTP ( d . vpeer ) , d . vmax_id . v ) ;
2015-09-20 12:54:22 +03:00
ptsApplySkippedUpdates ( ) ;
2015-03-13 16:01:25 +03:00
} break ;
case mtpc_updateReadHistoryOutbox : {
2016-09-27 16:37:18 +03:00
auto & d = update . c_updateReadHistoryOutbox ( ) ;
2015-09-20 12:54:22 +03:00
2015-09-13 11:41:27 +03:00
if ( ! ptsUpdated ( d . vpts . v , d . vpts_count . v , update ) ) {
2015-03-13 16:01:25 +03:00
return ;
}
2015-09-20 12:54:22 +03:00
// update before applying skipped
2016-06-09 22:28:58 +03:00
auto peerId = peerFromMTP ( d . vpeer ) ;
2016-06-22 21:41:13 +03:00
auto when = requestingDifference ( ) ? 0 : unixtime ( ) ;
App : : feedOutboxRead ( peerId , d . vmax_id . v , when ) ;
2016-06-09 22:28:58 +03:00
if ( _history - > peer ( ) & & _history - > peer ( ) - > id = = peerId ) {
2016-04-13 00:31:28 +03:00
_history - > update ( ) ;
2015-10-03 13:09:09 +03:00
}
2015-09-20 12:54:22 +03:00
ptsApplySkippedUpdates ( ) ;
2014-05-30 12:53:19 +04:00
} break ;
2015-04-02 13:33:19 +03:00
case mtpc_updateWebPage : {
2016-09-27 16:37:18 +03:00
auto & d = update . c_updateWebPage ( ) ;
2015-09-20 12:54:22 +03:00
2016-12-08 17:08:54 +03:00
// update web page anyway
2015-04-08 02:03:32 +03:00
App : : feedWebPage ( d . vwebpage ) ;
2016-04-13 00:31:28 +03:00
_history - > updatePreview ( ) ;
2016-09-27 16:37:18 +03:00
webPagesOrGamesUpdate ( ) ;
2015-09-20 12:54:22 +03:00
2016-12-08 17:08:54 +03:00
if ( ! ptsUpdated ( d . vpts . v , d . vpts_count . v , update ) ) {
return ;
}
2015-09-20 12:54:22 +03:00
ptsApplySkippedUpdates ( ) ;
2015-04-02 13:33:19 +03:00
} break ;
2014-05-30 12:53:19 +04:00
case mtpc_updateDeleteMessages : {
2016-09-27 16:37:18 +03:00
auto & d = update . c_updateDeleteMessages ( ) ;
2015-09-20 12:54:22 +03:00
2015-09-13 11:41:27 +03:00
if ( ! ptsUpdated ( d . vpts . v , d . vpts_count . v , update ) ) {
2015-03-13 16:01:25 +03:00
return ;
}
2015-09-20 12:54:22 +03:00
// update before applying skipped
2015-09-03 13:48:40 +03:00
App : : feedWereDeleted ( NoChannel , d . vmessages . c_vector ( ) . v ) ;
2016-04-13 00:31:28 +03:00
_history - > peerMessagesUpdated ( ) ;
2015-09-20 12:54:22 +03:00
ptsApplySkippedUpdates ( ) ;
2014-05-30 12:53:19 +04:00
} break ;
case mtpc_updateUserTyping : {
2016-09-27 16:37:18 +03:00
auto & d = update . c_updateUserTyping ( ) ;
auto history = App : : historyLoaded ( peerFromUser ( d . vuser_id ) ) ;
auto user = App : : userLoaded ( d . vuser_id . v ) ;
2014-05-30 12:53:19 +04:00
if ( history & & user ) {
2016-06-22 21:41:13 +03:00
auto when = requestingDifference ( ) ? 0 : unixtime ( ) ;
App : : histories ( ) . regSendAction ( history , user , d . vaction , when ) ;
2014-05-30 12:53:19 +04:00
}
} break ;
case mtpc_updateChatUserTyping : {
2016-09-27 16:37:18 +03:00
auto & d = update . c_updateChatUserTyping ( ) ;
2015-09-08 16:34:22 +03:00
History * history = 0 ;
2016-09-27 16:37:18 +03:00
if ( auto chat = App : : chatLoaded ( d . vchat_id . v ) ) {
2015-09-08 16:34:22 +03:00
history = App : : historyLoaded ( chat - > id ) ;
2016-09-27 16:37:18 +03:00
} else if ( auto channel = App : : channelLoaded ( d . vchat_id . v ) ) {
2015-09-08 16:34:22 +03:00
history = App : : historyLoaded ( channel - > id ) ;
}
2016-09-27 16:37:18 +03:00
auto user = ( d . vuser_id . v = = MTP : : authedId ( ) ) ? nullptr : App : : userLoaded ( d . vuser_id . v ) ;
2014-05-30 12:53:19 +04:00
if ( history & & user ) {
2016-06-22 21:41:13 +03:00
auto when = requestingDifference ( ) ? 0 : unixtime ( ) ;
App : : histories ( ) . regSendAction ( history , user , d . vaction , when ) ;
2014-05-30 12:53:19 +04:00
}
} break ;
case mtpc_updateChatParticipants : {
2015-10-29 15:10:49 -04:00
App : : feedParticipants ( update . c_updateChatParticipants ( ) . vparticipants , true , false ) ;
2014-05-30 12:53:19 +04:00
} break ;
case mtpc_updateChatParticipantAdd : {
2015-10-29 15:10:49 -04:00
App : : feedParticipantAdd ( update . c_updateChatParticipantAdd ( ) , false ) ;
2014-05-30 12:53:19 +04:00
} break ;
case mtpc_updateChatParticipantDelete : {
2015-10-29 15:10:49 -04:00
App : : feedParticipantDelete ( update . c_updateChatParticipantDelete ( ) , false ) ;
} break ;
case mtpc_updateChatAdmins : {
App : : feedChatAdmins ( update . c_updateChatAdmins ( ) , false ) ;
} break ;
case mtpc_updateChatParticipantAdmin : {
App : : feedParticipantAdmin ( update . c_updateChatParticipantAdmin ( ) , false ) ;
2014-05-30 12:53:19 +04:00
} break ;
case mtpc_updateUserStatus : {
2016-09-27 16:37:18 +03:00
auto & d = update . c_updateUserStatus ( ) ;
if ( auto user = App : : userLoaded ( d . vuser_id . v ) ) {
2015-01-26 16:04:41 +03:00
switch ( d . vstatus . type ( ) ) {
case mtpc_userStatusEmpty : user - > onlineTill = 0 ; break ;
case mtpc_userStatusRecently :
if ( user - > onlineTill > - 10 ) { // don't modify pseudo-online
user - > onlineTill = - 2 ;
}
break ;
case mtpc_userStatusLastWeek : user - > onlineTill = - 3 ; break ;
case mtpc_userStatusLastMonth : user - > onlineTill = - 4 ; break ;
case mtpc_userStatusOffline : user - > onlineTill = d . vstatus . c_userStatusOffline ( ) . vwas_online . v ; break ;
case mtpc_userStatusOnline : user - > onlineTill = d . vstatus . c_userStatusOnline ( ) . vexpires . v ; break ;
}
2015-06-30 01:09:23 +03:00
App : : markPeerUpdated ( user ) ;
2016-06-03 10:20:24 +03:00
Notify : : peerUpdatedDelayed ( user , Notify : : PeerUpdate : : Flag : : UserOnlineChanged ) ;
2015-01-26 16:04:41 +03:00
}
if ( d . vuser_id . v = = MTP : : authedId ( ) ) {
if ( d . vstatus . type ( ) = = mtpc_userStatusOffline | | d . vstatus . type ( ) = = mtpc_userStatusEmpty ) {
updateOnline ( true ) ;
if ( d . vstatus . type ( ) = = mtpc_userStatusOffline ) {
cSetOtherOnline ( d . vstatus . c_userStatusOffline ( ) . vwas_online . v ) ;
2014-05-30 12:53:19 +04:00
}
2015-01-26 16:04:41 +03:00
} else if ( d . vstatus . type ( ) = = mtpc_userStatusOnline ) {
cSetOtherOnline ( d . vstatus . c_userStatusOnline ( ) . vexpires . v ) ;
2014-05-30 12:53:19 +04:00
}
}
} break ;
case mtpc_updateUserName : {
2016-09-27 16:37:18 +03:00
auto & d = update . c_updateUserName ( ) ;
2016-05-25 15:09:05 +03:00
if ( auto user = App : : userLoaded ( d . vuser_id . v ) ) {
2014-11-15 02:23:35 +03:00
if ( user - > contact < = 0 ) {
user - > setName ( textOneLine ( qs ( d . vfirst_name ) ) , textOneLine ( qs ( d . vlast_name ) ) , user - > nameOrPhone , textOneLine ( qs ( d . vusername ) ) ) ;
} else {
user - > setName ( textOneLine ( user - > firstName ) , textOneLine ( user - > lastName ) , user - > nameOrPhone , textOneLine ( qs ( d . vusername ) ) ) ;
}
2015-06-30 01:09:23 +03:00
App : : markPeerUpdated ( user ) ;
2014-05-30 12:53:19 +04:00
}
} break ;
case mtpc_updateUserPhoto : {
2016-09-27 16:37:18 +03:00
auto & d = update . c_updateUserPhoto ( ) ;
if ( auto user = App : : userLoaded ( d . vuser_id . v ) ) {
2014-05-30 12:53:19 +04:00
user - > setPhoto ( d . vphoto ) ;
2016-03-18 13:18:30 +03:00
user - > loadUserpic ( ) ;
2015-10-28 20:16:52 -04:00
if ( mtpIsTrue ( d . vprevious ) ) {
2014-08-11 13:03:45 +04:00
user - > photosCount = - 1 ;
user - > photos . clear ( ) ;
} else {
2015-06-30 01:09:23 +03:00
if ( user - > photoId & & user - > photoId ! = UnknownPeerPhotoId ) {
2014-08-11 13:03:45 +04:00
if ( user - > photosCount > 0 ) + + user - > photosCount ;
user - > photos . push_front ( App : : photo ( user - > photoId ) ) ;
} else {
user - > photosCount = - 1 ;
user - > photos . clear ( ) ;
}
2014-05-30 12:53:19 +04:00
}
2015-06-30 01:09:23 +03:00
App : : markPeerUpdated ( user ) ;
2017-01-01 20:45:20 +04:00
Notify : : mediaOverviewUpdated ( user , OverviewCount ) ;
2014-05-30 12:53:19 +04:00
}
} break ;
case mtpc_updateContactRegistered : {
2016-09-27 16:37:18 +03:00
auto & d = update . c_updateContactRegistered ( ) ;
if ( auto user = App : : userLoaded ( d . vuser_id . v ) ) {
2014-07-04 15:12:54 +04:00
if ( App : : history ( user - > id ) - > loadedAtBottom ( ) ) {
2016-05-20 19:01:06 +03:00
App : : history ( user - > id ) - > addNewService ( clientMsgId ( ) , date ( d . vdate ) , lng_action_user_registered ( lt_from , user - > name ) , 0 ) ;
2014-07-04 15:12:54 +04:00
}
2014-05-30 12:53:19 +04:00
}
} break ;
case mtpc_updateContactLink : {
2016-09-27 16:37:18 +03:00
auto & d = update . c_updateContactLink ( ) ;
2016-06-02 16:57:49 +03:00
App : : feedUserLink ( d . vuser_id , d . vmy_link , d . vforeign_link ) ;
2014-05-30 12:53:19 +04:00
} break ;
2014-12-03 16:10:32 +03:00
case mtpc_updateNotifySettings : {
2016-09-27 16:37:18 +03:00
auto & d = update . c_updateNotifySettings ( ) ;
2014-12-03 16:10:32 +03:00
applyNotifySetting ( d . vpeer , d . vnotify_settings ) ;
} break ;
case mtpc_updateDcOptions : {
2016-09-27 16:37:18 +03:00
auto & d = update . c_updateDcOptions ( ) ;
2014-12-03 16:10:32 +03:00
MTP : : updateDcOptions ( d . vdc_options . c_vector ( ) . v ) ;
} break ;
case mtpc_updateUserPhone : {
2016-09-27 16:37:18 +03:00
auto & d = update . c_updateUserPhone ( ) ;
2016-05-25 15:09:05 +03:00
if ( auto user = App : : userLoaded ( d . vuser_id . v ) ) {
2016-05-31 22:27:11 +03:00
auto newPhone = qs ( d . vphone ) ;
if ( newPhone ! = user - > phone ( ) ) {
user - > setPhone ( newPhone ) ;
2016-06-02 16:57:49 +03:00
user - > setName ( user - > firstName , user - > lastName , ( user - > contact | | isServiceUser ( user - > id ) | | user - > isSelf ( ) | | user - > phone ( ) . isEmpty ( ) ) ? QString ( ) : App : : formatPhone ( user - > phone ( ) ) , user - > username ) ;
2016-05-31 22:27:11 +03:00
App : : markPeerUpdated ( user ) ;
2016-06-01 23:05:37 +03:00
Notify : : peerUpdatedDelayed ( user , Notify : : PeerUpdate : : Flag : : UserPhoneChanged ) ;
2016-05-31 22:27:11 +03:00
}
2014-12-03 16:10:32 +03:00
}
} break ;
2014-05-30 12:53:19 +04:00
case mtpc_updateNewEncryptedMessage : {
2016-09-27 16:37:18 +03:00
auto & d = update . c_updateNewEncryptedMessage ( ) ;
2014-05-30 12:53:19 +04:00
} break ;
case mtpc_updateEncryptedChatTyping : {
2016-09-27 16:37:18 +03:00
auto & d = update . c_updateEncryptedChatTyping ( ) ;
2014-05-30 12:53:19 +04:00
} break ;
case mtpc_updateEncryption : {
2016-09-27 16:37:18 +03:00
auto & d = update . c_updateEncryption ( ) ;
2014-05-30 12:53:19 +04:00
} break ;
case mtpc_updateEncryptedMessagesRead : {
2016-09-27 16:37:18 +03:00
auto & d = update . c_updateEncryptedMessagesRead ( ) ;
2014-05-30 12:53:19 +04:00
} break ;
2016-12-13 10:59:57 +03:00
case mtpc_updatePhoneCall : {
auto & d = update . c_updatePhoneCall ( ) ;
} break ;
2014-05-30 12:53:19 +04:00
case mtpc_updateUserBlocked : {
2016-09-27 16:37:18 +03:00
auto & d = update . c_updateUserBlocked ( ) ;
if ( auto user = App : : userLoaded ( d . vuser_id . v ) ) {
2016-06-01 23:05:37 +03:00
user - > setBlockStatus ( mtpIsTrue ( d . vblocked ) ? UserData : : BlockStatus : : Blocked : UserData : : BlockStatus : : NotBlocked ) ;
2015-08-12 21:01:32 +03:00
App : : markPeerUpdated ( user ) ;
}
2014-05-30 12:53:19 +04:00
} break ;
2014-10-22 22:39:03 +04:00
case mtpc_updateServiceNotification : {
2016-09-27 16:37:18 +03:00
auto & d = update . c_updateServiceNotification ( ) ;
2016-12-13 10:59:57 +03:00
if ( d . is_popup ( ) ) {
2016-12-13 20:07:56 +03:00
Ui : : show ( Box < InformBox > ( qs ( d . vmessage ) ) ) ;
2014-12-12 19:27:03 +03:00
} else {
2016-12-13 10:59:57 +03:00
App : : wnd ( ) - > serviceNotification ( { qs ( d . vmessage ) , entitiesFromMTP ( d . ventities . c_vector ( ) . v ) } , d . vmedia ) ;
emit App : : wnd ( ) - > checkNewAuthorization ( ) ;
2014-12-05 16:44:27 +03:00
}
2014-12-03 16:10:32 +03:00
} break ;
case mtpc_updatePrivacy : {
2016-09-25 22:04:02 +03:00
auto & d = update . c_updatePrivacy ( ) ;
2014-10-22 22:39:03 +04:00
} break ;
2015-09-06 13:17:09 +03:00
2016-12-13 10:59:57 +03:00
case mtpc_updatePinnedDialogs : {
auto & d = update . c_updatePinnedDialogs ( ) ;
if ( d . has_order ( ) ) {
auto allLoaded = true ;
auto & order = d . vorder . c_vector ( ) . v ;
for_const ( auto & peer , order ) {
auto peerId = peerFromMTP ( peer ) ;
if ( ! App : : historyLoaded ( peerId ) ) {
allLoaded = false ;
DEBUG_LOG ( ( " API Error: pinned chat not loaded for peer %1 " ) . arg ( peerId ) ) ;
break ;
}
}
if ( allLoaded ) {
App : : histories ( ) . clearPinned ( ) ;
for ( auto i = order . size ( ) ; i ! = 0 ; ) {
auto history = App : : historyLoaded ( peerFromMTP ( order [ - - i ] ) ) ;
t_assert ( history ! = nullptr ) ;
history - > setPinnedDialog ( true ) ;
}
} else {
_dialogs - > loadPinnedDialogs ( ) ;
}
} else {
_dialogs - > loadPinnedDialogs ( ) ;
}
} break ;
case mtpc_updateDialogPinned : {
auto & d = update . c_updateDialogPinned ( ) ;
auto peerId = peerFromMTP ( d . vpeer ) ;
if ( auto history = App : : historyLoaded ( peerId ) ) {
history - > setPinnedDialog ( d . is_pinned ( ) ) ;
} else {
DEBUG_LOG ( ( " API Error: pinned chat not loaded for peer %1 " ) . arg ( peerId ) ) ;
_dialogs - > loadPinnedDialogs ( ) ;
}
} break ;
2016-02-18 19:36:33 +03:00
/////// Channel updates
2015-09-20 11:55:41 +03:00
case mtpc_updateChannel : {
2016-09-25 22:04:02 +03:00
auto & d = update . c_updateChannel ( ) ;
if ( auto channel = App : : channelLoaded ( d . vchannel_id . v ) ) {
2015-09-21 23:57:42 +03:00
App : : markPeerUpdated ( channel ) ;
2015-09-22 12:58:40 +03:00
channel - > inviter = 0 ;
2015-09-23 20:43:08 +03:00
if ( ! channel - > amIn ( ) ) {
2015-09-24 11:58:10 +03:00
deleteConversation ( channel , false ) ;
2015-09-21 23:57:42 +03:00
} else if ( ! channel - > amCreator ( ) & & App : : history ( channel - > id ) ) { // create history
_updatedChannels . insert ( channel , true ) ;
2015-10-03 14:33:51 +03:00
if ( App : : api ( ) ) App : : api ( ) - > requestSelfParticipant ( channel ) ;
2015-09-21 23:57:42 +03:00
}
}
2015-09-20 11:55:41 +03:00
} break ;
2015-09-06 13:17:09 +03:00
case mtpc_updateNewChannelMessage : {
2016-07-21 20:35:55 +03:00
auto & d = update . c_updateNewChannelMessage ( ) ;
2016-09-25 22:04:02 +03:00
auto channel = App : : channelLoaded ( peerToChannel ( peerFromMessage ( d . vmessage ) ) ) ;
2016-10-22 18:58:14 +03:00
auto isDataLoaded = allDataLoadedForMessage ( d . vmessage ) ;
2016-06-22 21:41:13 +03:00
if ( ! requestingDifference ( ) & & ( ! channel | | isDataLoaded ! = DataIsLoadedResult : : Ok ) ) {
2016-04-06 15:07:05 +04:00
MTP_LOG ( 0 , ( " getDifference { good - after not all data loaded in updateNewChannelMessage }%1 " ) . arg ( cTestMode ( ) ? " TESTMODE " : " " ) ) ;
// Request last active supergroup participants if the 'from' user was not loaded yet.
// This will optimize similar getDifference() calls for almost all next messages.
if ( isDataLoaded = = DataIsLoadedResult : : FromNotLoaded & & channel & & channel - > isMegagroup ( ) & & App : : api ( ) ) {
2016-06-02 16:02:55 +03:00
if ( channel - > mgInfo - > lastParticipants . size ( ) < Global : : ChatSizeMax ( ) & & ( channel - > mgInfo - > lastParticipants . isEmpty ( ) | | channel - > mgInfo - > lastParticipants . size ( ) < channel - > membersCount ( ) ) ) {
2016-04-06 15:07:05 +04:00
App : : api ( ) - > requestLastParticipants ( channel ) ;
}
}
2016-03-11 18:01:32 +03:00
if ( ! _byMinChannelTimer . isActive ( ) ) { // getDifference after timeout
_byMinChannelTimer . start ( WaitForSkippedTimeout ) ;
}
return ;
}
2015-09-21 23:57:42 +03:00
if ( channel & & ! _handlingChannelDifference ) {
if ( channel - > ptsRequesting ( ) ) { // skip global updates while getting channel difference
return ;
} else if ( ! channel - > ptsUpdated ( d . vpts . v , d . vpts_count . v , update ) ) {
return ;
}
2015-09-13 11:41:27 +03:00
}
2015-09-20 12:54:22 +03:00
// update before applying skipped
2015-10-15 02:15:28 +02:00
bool needToAdd = true ;
2016-04-13 00:31:28 +03:00
if ( d . vmessage . type ( ) = = mtpc_message ) { // index forwarded messages to links _overview
2015-10-15 02:15:28 +02:00
if ( App : : checkEntitiesAndViewsUpdate ( d . vmessage . c_message ( ) ) ) { // already in blocks
LOG ( ( " Skipping message, because it is already in blocks! " ) ) ;
needToAdd = false ;
}
2015-09-06 13:17:09 +03:00
}
2015-10-15 02:15:28 +02:00
if ( needToAdd ) {
2016-09-25 22:04:02 +03:00
if ( auto item = App : : histories ( ) . addNewMessage ( d . vmessage , NewMessageUnread ) ) {
2016-04-13 00:31:28 +03:00
_history - > peerMessagesUpdated ( item - > history ( ) - > peer - > id ) ;
2015-10-15 02:15:28 +02:00
}
2015-09-06 13:17:09 +03:00
}
2015-09-21 23:57:42 +03:00
if ( channel & & ! _handlingChannelDifference ) {
2015-09-20 12:54:22 +03:00
channel - > ptsApplySkippedUpdates ( ) ;
}
2015-09-06 13:17:09 +03:00
} break ;
2016-02-18 19:36:33 +03:00
case mtpc_updateEditChannelMessage : {
2016-09-25 22:04:02 +03:00
auto & d = update . c_updateEditChannelMessage ( ) ;
auto channel = App : : channelLoaded ( peerToChannel ( peerFromMessage ( d . vmessage ) ) ) ;
2016-02-18 19:36:33 +03:00
if ( channel & & ! _handlingChannelDifference ) {
if ( channel - > ptsRequesting ( ) ) { // skip global updates while getting channel difference
return ;
} else if ( ! channel - > ptsUpdated ( d . vpts . v , d . vpts_count . v , update ) ) {
return ;
}
}
// update before applying skipped
2016-09-23 21:26:53 +03:00
App : : updateEditedMessage ( d . vmessage ) ;
2016-02-18 19:36:33 +03:00
if ( channel & & ! _handlingChannelDifference ) {
channel - > ptsApplySkippedUpdates ( ) ;
}
} break ;
2016-03-30 21:13:07 +04:00
case mtpc_updateEditMessage : {
2016-09-25 22:04:02 +03:00
auto & d = update . c_updateEditMessage ( ) ;
2016-03-30 21:13:07 +04:00
if ( ! ptsUpdated ( d . vpts . v , d . vpts_count . v , update ) ) {
return ;
}
// update before applying skipped
2016-09-23 21:26:53 +03:00
App : : updateEditedMessage ( d . vmessage ) ;
2016-03-30 21:13:07 +04:00
ptsApplySkippedUpdates ( ) ;
} break ;
2016-03-04 17:34:46 +02:00
case mtpc_updateChannelPinnedMessage : {
2016-09-25 22:04:02 +03:00
auto & d = update . c_updateChannelPinnedMessage ( ) ;
2016-03-04 17:34:46 +02:00
2016-09-25 22:04:02 +03:00
if ( auto channel = App : : channelLoaded ( d . vchannel_id . v ) ) {
2016-03-04 17:34:46 +02:00
if ( channel - > isMegagroup ( ) ) {
channel - > mgInfo - > pinnedMsgId = d . vid . v ;
if ( App : : api ( ) ) {
emit App : : api ( ) - > fullPeerUpdated ( channel ) ;
}
}
}
} break ;
2015-09-06 13:17:09 +03:00
case mtpc_updateReadChannelInbox : {
2016-09-25 22:04:02 +03:00
auto & d = update . c_updateReadChannelInbox ( ) ;
2015-09-17 00:15:13 +03:00
App : : feedInboxRead ( peerFromChannel ( d . vchannel_id . v ) , d . vmax_id . v ) ;
2015-09-06 13:17:09 +03:00
} break ;
2016-05-20 19:01:06 +03:00
case mtpc_updateReadChannelOutbox : {
2016-09-25 22:04:02 +03:00
auto & d = update . c_updateReadChannelOutbox ( ) ;
2016-06-09 22:28:58 +03:00
auto peerId = peerFromChannel ( d . vchannel_id . v ) ;
2016-06-22 21:41:13 +03:00
auto when = requestingDifference ( ) ? 0 : unixtime ( ) ;
App : : feedOutboxRead ( peerId , d . vmax_id . v , when ) ;
2016-06-09 22:28:58 +03:00
if ( _history - > peer ( ) & & _history - > peer ( ) - > id = = peerId ) {
_history - > update ( ) ;
}
2016-05-20 19:01:06 +03:00
} break ;
2016-10-24 00:03:10 +03:00
case mtpc_updateChannelWebPage : {
auto & d = update . c_updateChannelWebPage ( ) ;
2016-12-08 17:08:54 +03:00
// update web page anyway
App : : feedWebPage ( d . vwebpage ) ;
_history - > updatePreview ( ) ;
webPagesOrGamesUpdate ( ) ;
auto channel = App : : channelLoaded ( d . vchannel_id . v ) ;
2016-10-24 00:03:10 +03:00
if ( channel & & ! _handlingChannelDifference ) {
if ( channel - > ptsRequesting ( ) ) { // skip global updates while getting channel difference
return ;
} else if ( ! channel - > ptsUpdated ( d . vpts . v , d . vpts_count . v , update ) ) {
return ;
}
}
if ( channel & & ! _handlingChannelDifference ) {
channel - > ptsApplySkippedUpdates ( ) ;
}
} break ;
2015-09-06 13:17:09 +03:00
case mtpc_updateDeleteChannelMessages : {
2016-09-25 22:04:02 +03:00
auto & d = update . c_updateDeleteChannelMessages ( ) ;
auto channel = App : : channelLoaded ( d . vchannel_id . v ) ;
2015-09-20 12:54:22 +03:00
2015-09-21 23:57:42 +03:00
if ( channel & & ! _handlingChannelDifference ) {
if ( channel - > ptsRequesting ( ) ) { // skip global updates while getting channel difference
return ;
} else if ( ! channel - > ptsUpdated ( d . vpts . v , d . vpts_count . v , update ) ) {
return ;
}
2015-09-13 11:41:27 +03:00
}
2015-09-20 12:54:22 +03:00
// update before applying skipped
2015-09-17 00:15:13 +03:00
App : : feedWereDeleted ( d . vchannel_id . v , d . vmessages . c_vector ( ) . v ) ;
2016-04-13 00:31:28 +03:00
_history - > peerMessagesUpdated ( ) ;
2015-09-20 12:54:22 +03:00
2015-09-21 23:57:42 +03:00
if ( channel & & ! _handlingChannelDifference ) {
2015-09-20 12:54:22 +03:00
channel - > ptsApplySkippedUpdates ( ) ;
}
2015-09-06 13:17:09 +03:00
} break ;
case mtpc_updateChannelTooLong : {
2016-09-25 22:04:02 +03:00
auto & d = update . c_updateChannelTooLong ( ) ;
if ( auto channel = App : : channelLoaded ( d . vchannel_id . v ) ) {
2016-03-11 18:01:32 +03:00
if ( ! d . has_pts ( ) | | channel - > pts ( ) < d . vpts . v ) {
getChannelDifference ( channel ) ;
}
2015-09-13 11:41:27 +03:00
}
} break ;
case mtpc_updateChannelMessageViews : {
2016-09-25 22:04:02 +03:00
auto & d = update . c_updateChannelMessageViews ( ) ;
if ( auto item = App : : histItemById ( d . vchannel_id . v , d . vid . v ) ) {
2015-09-17 00:15:13 +03:00
item - > setViewsCount ( d . vviews . v ) ;
2015-09-13 11:41:27 +03:00
}
2015-09-06 13:17:09 +03:00
} break ;
2016-02-18 19:36:33 +03:00
////// Cloud sticker sets
2015-12-02 20:17:53 +03:00
case mtpc_updateNewStickerSet : {
2016-07-21 16:57:31 +03:00
auto & d = update . c_updateNewStickerSet ( ) ;
bool writeArchived = false ;
2015-12-02 20:17:53 +03:00
if ( d . vstickerset . type ( ) = = mtpc_messages_stickerSet ) {
2016-07-21 16:57:31 +03:00
auto & set = d . vstickerset . c_messages_stickerSet ( ) ;
2015-12-02 20:17:53 +03:00
if ( set . vset . type ( ) = = mtpc_stickerSet ) {
2016-07-21 16:57:31 +03:00
auto & s = set . vset . c_stickerSet ( ) ;
2016-09-15 22:15:49 +03:00
if ( ! s . is_masks ( ) ) {
auto & sets = Global : : RefStickerSets ( ) ;
auto it = sets . find ( s . vid . v ) ;
if ( it = = sets . cend ( ) ) {
it = sets . insert ( s . vid . v , Stickers : : Set ( s . vid . v , s . vaccess_hash . v , stickerSetTitle ( s ) , qs ( s . vshort_name ) , s . vcount . v , s . vhash . v , s . vflags . v | MTPDstickerSet : : Flag : : f_installed ) ) ;
} else {
it - > flags | = MTPDstickerSet : : Flag : : f_installed ;
if ( it - > flags & MTPDstickerSet : : Flag : : f_archived ) {
it - > flags & = ~ MTPDstickerSet : : Flag : : f_archived ;
writeArchived = true ;
}
2016-07-21 16:57:31 +03:00
}
2016-09-15 22:15:49 +03:00
auto inputSet = MTP_inputStickerSetID ( MTP_long ( it - > id ) , MTP_long ( it - > access ) ) ;
auto & v = set . vdocuments . c_vector ( ) . v ;
it - > stickers . clear ( ) ;
it - > stickers . reserve ( v . size ( ) ) ;
for ( int i = 0 , l = v . size ( ) ; i < l ; + + i ) {
auto doc = App : : feedDocument ( v . at ( i ) ) ;
if ( ! doc | | ! doc - > sticker ( ) ) continue ;
it - > stickers . push_back ( doc ) ;
if ( doc - > sticker ( ) - > set . type ( ) ! = mtpc_inputStickerSetID ) {
doc - > sticker ( ) - > set = inputSet ;
}
2016-09-10 23:54:59 +03:00
}
2016-09-15 22:15:49 +03:00
it - > emoji . clear ( ) ;
auto & packs = set . vpacks . c_vector ( ) . v ;
for ( int i = 0 , l = packs . size ( ) ; i < l ; + + i ) {
if ( packs . at ( i ) . type ( ) ! = mtpc_stickerPack ) continue ;
auto & pack = packs . at ( i ) . c_stickerPack ( ) ;
if ( auto e = emojiGetNoColor ( emojiFromText ( qs ( pack . vemoticon ) ) ) ) {
auto & stickers = pack . vdocuments . c_vector ( ) . v ;
StickerPack p ;
p . reserve ( stickers . size ( ) ) ;
for ( int j = 0 , c = stickers . size ( ) ; j < c ; + + j ) {
auto doc = App : : document ( stickers . at ( j ) . v ) ;
if ( ! doc | | ! doc - > sticker ( ) ) continue ;
p . push_back ( doc ) ;
}
it - > emoji . insert ( e , p ) ;
2016-01-09 20:51:42 +08:00
}
}
2015-12-02 20:17:53 +03:00
2016-09-15 22:15:49 +03:00
auto & order ( Global : : RefStickerSetsOrder ( ) ) ;
int32 insertAtIndex = 0 , currentIndex = order . indexOf ( s . vid . v ) ;
if ( currentIndex ! = insertAtIndex ) {
if ( currentIndex > 0 ) {
order . removeAt ( currentIndex ) ;
}
order . insert ( insertAtIndex , s . vid . v ) ;
2015-12-02 20:17:53 +03:00
}
2016-09-15 22:15:49 +03:00
auto custom = sets . find ( Stickers : : CustomSetId ) ;
if ( custom ! = sets . cend ( ) ) {
for ( int32 i = 0 , l = it - > stickers . size ( ) ; i < l ; + + i ) {
int32 removeIndex = custom - > stickers . indexOf ( it - > stickers . at ( i ) ) ;
if ( removeIndex > = 0 ) custom - > stickers . removeAt ( removeIndex ) ;
}
if ( custom - > stickers . isEmpty ( ) ) {
sets . erase ( custom ) ;
}
2015-12-02 20:17:53 +03:00
}
2016-09-15 22:15:49 +03:00
Local : : writeInstalledStickers ( ) ;
if ( writeArchived ) Local : : writeArchivedStickers ( ) ;
emit stickersUpdated ( ) ;
2015-12-02 20:17:53 +03:00
}
}
}
} break ;
case mtpc_updateStickerSetsOrder : {
2016-06-27 19:25:21 +03:00
auto & d = update . c_updateStickerSetsOrder ( ) ;
2016-09-07 12:04:57 +03:00
if ( ! d . is_masks ( ) ) {
auto & order = d . vorder . c_vector ( ) . v ;
auto & sets = Global : : StickerSets ( ) ;
Stickers : : Order result ;
2016-09-15 22:15:49 +03:00
for ( int i = 0 , l = order . size ( ) ; i < l ; + + i ) {
2016-09-07 12:04:57 +03:00
if ( sets . constFind ( order . at ( i ) . v ) = = sets . cend ( ) ) {
break ;
}
result . push_back ( order . at ( i ) . v ) ;
}
if ( result . size ( ) ! = Global : : StickerSetsOrder ( ) . size ( ) | | result . size ( ) ! = order . size ( ) ) {
Global : : SetLastStickersUpdate ( 0 ) ;
App : : main ( ) - > updateStickers ( ) ;
} else {
Global : : SetStickerSetsOrder ( result ) ;
Local : : writeInstalledStickers ( ) ;
emit stickersUpdated ( ) ;
2015-12-02 20:17:53 +03:00
}
}
} break ;
case mtpc_updateStickerSets : {
2016-03-19 19:55:15 +03:00
Global : : SetLastStickersUpdate ( 0 ) ;
2015-12-28 00:37:48 +03:00
App : : main ( ) - > updateStickers ( ) ;
} break ;
2016-07-15 18:58:52 +03:00
case mtpc_updateRecentStickers : {
Global : : SetLastStickersUpdate ( 0 ) ;
App : : main ( ) - > updateStickers ( ) ;
} break ;
2016-06-27 19:25:21 +03:00
case mtpc_updateReadFeaturedStickers : {
2016-09-10 23:54:59 +03:00
// We read some of the featured stickers, perhaps not all of them.
// Here we don't know what featured sticker sets were read, so we
// request all of them once again.
Global : : SetLastFeaturedStickersUpdate ( 0 ) ;
App : : main ( ) - > updateStickers ( ) ;
2016-06-27 19:25:21 +03:00
} break ;
2016-05-31 12:46:31 +03:00
////// Cloud saved GIFs
2015-12-28 00:37:48 +03:00
case mtpc_updateSavedGifs : {
cSetLastSavedGifsUpdate ( 0 ) ;
2015-12-02 20:17:53 +03:00
App : : main ( ) - > updateStickers ( ) ;
} break ;
2016-05-31 12:46:31 +03:00
////// Cloud drafts
case mtpc_updateDraftMessage : {
auto & peerDraft = update . c_updateDraftMessage ( ) ;
auto peerId = peerFromMTP ( peerDraft . vpeer ) ;
auto & draftMessage = peerDraft . vdraft ;
if ( draftMessage . type ( ) = = mtpc_draftMessage ) {
auto & draft = draftMessage . c_draftMessage ( ) ;
Data : : applyPeerCloudDraft ( peerId , draft ) ;
2016-06-09 17:31:10 +03:00
} else {
Data : : clearPeerCloudDraft ( peerId ) ;
2016-05-31 12:46:31 +03:00
}
} break ;
2014-05-30 12:53:19 +04:00
}
}