/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once #include "storage/storage_databases.h" #include "chat_helpers/stickers.h" #include "dialogs/dialogs_key.h" #include "data/data_groups.h" #include "history/history_location_manager.h" #include "base/timer.h" class HistoryItem; class BoxContent; struct WebPageCollage; enum class WebPageType; namespace HistoryView { struct Group; class Element; } // namespace HistoryView class AuthSession; namespace Media { namespace Clip { class Reader; } // namespace Clip } // namespace Media namespace Export { class ControllerWrap; namespace View { class PanelController; } // namespace View } // namespace Export namespace Passport { struct SavedCredentials; } // namespace Passport namespace Data { class Feed; enum class FeedUpdateFlag; struct FeedUpdate; class Session final { public: using ViewElement = HistoryView::Element; explicit Session(not_null session); ~Session(); AuthSession &session() const { return *_session; } void startExport(PeerData *peer = nullptr); void startExport(const MTPInputPeer &singlePeer); void suggestStartExport(TimeId availableAt); void clearExportSuggestion(); rpl::producer currentExportView() const; bool exportInProgress() const; void stopExportWithConfirmation(FnMut callback); void stopExport(); const Passport::SavedCredentials *passportCredentials() const; void rememberPassportCredentials( Passport::SavedCredentials data, TimeMs rememberFor); void forgetPassportCredentials(); Storage::Cache::Database &cache(); [[nodiscard]] base::Variable &contactsLoaded() { return _contactsLoaded; } [[nodiscard]] base::Variable &allChatsLoaded() { return _allChatsLoaded; } [[nodiscard]] base::Observable &moreChatsLoaded() { return _moreChatsLoaded; } struct ItemVisibilityQuery { not_null item; not_null isVisible; }; [[nodiscard]] base::Observable &queryItemVisibility() { return _queryItemVisibility; } struct IdChange { not_null item; MsgId oldId = 0; }; void notifyItemIdChange(IdChange event); [[nodiscard]] rpl::producer itemIdChanged() const; void notifyItemLayoutChange(not_null item); [[nodiscard]] rpl::producer> itemLayoutChanged() const; void notifyViewLayoutChange(not_null view); [[nodiscard]] rpl::producer> viewLayoutChanged() const; void requestItemRepaint(not_null item); [[nodiscard]] rpl::producer> itemRepaintRequest() const; void requestViewRepaint(not_null view); [[nodiscard]] rpl::producer> viewRepaintRequest() const; void requestItemResize(not_null item); [[nodiscard]] rpl::producer> itemResizeRequest() const; void requestViewResize(not_null view); [[nodiscard]] rpl::producer> viewResizeRequest() const; void requestItemViewRefresh(not_null item); [[nodiscard]] rpl::producer> itemViewRefreshRequest() const; void requestItemTextRefresh(not_null item); void requestAnimationPlayInline(not_null item); [[nodiscard]] rpl::producer> animationPlayInlineRequest() const; void notifyHistoryUnloaded(not_null history); [[nodiscard]] rpl::producer> historyUnloaded() const; void notifyItemRemoved(not_null item); [[nodiscard]] rpl::producer> itemRemoved() const; void notifyViewRemoved(not_null view); [[nodiscard]] rpl::producer> viewRemoved() const; void notifyHistoryCleared(not_null history); [[nodiscard]] rpl::producer> historyCleared() const; void notifyHistoryChangeDelayed(not_null history); [[nodiscard]] rpl::producer> historyChanged() const; void sendHistoryChangeNotifications(); using MegagroupParticipant = std::tuple< not_null, not_null>; void removeMegagroupParticipant( not_null channel, not_null user); [[nodiscard]] rpl::producer megagroupParticipantRemoved() const; [[nodiscard]] rpl::producer> megagroupParticipantRemoved( not_null channel) const; void addNewMegagroupParticipant( not_null channel, not_null user); [[nodiscard]] rpl::producer megagroupParticipantAdded() const; [[nodiscard]] rpl::producer> megagroupParticipantAdded( not_null channel) const; void notifyFeedUpdated(not_null feed, FeedUpdateFlag update); [[nodiscard]] rpl::producer feedUpdated() const; void notifyStickersUpdated(); [[nodiscard]] rpl::producer<> stickersUpdated() const; void notifySavedGifsUpdated(); [[nodiscard]] rpl::producer<> savedGifsUpdated() const; bool stickersUpdateNeeded(TimeMs now) const { return stickersUpdateNeeded(_lastStickersUpdate, now); } void setLastStickersUpdate(TimeMs update) { _lastStickersUpdate = update; } bool recentStickersUpdateNeeded(TimeMs now) const { return stickersUpdateNeeded(_lastRecentStickersUpdate, now); } void setLastRecentStickersUpdate(TimeMs update) { _lastRecentStickersUpdate = update; } bool favedStickersUpdateNeeded(TimeMs now) const { return stickersUpdateNeeded(_lastFavedStickersUpdate, now); } void setLastFavedStickersUpdate(TimeMs update) { _lastFavedStickersUpdate = update; } bool featuredStickersUpdateNeeded(TimeMs now) const { return stickersUpdateNeeded(_lastFeaturedStickersUpdate, now); } void setLastFeaturedStickersUpdate(TimeMs update) { _lastFeaturedStickersUpdate = update; } bool savedGifsUpdateNeeded(TimeMs now) const { return stickersUpdateNeeded(_lastSavedGifsUpdate, now); } void setLastSavedGifsUpdate(TimeMs update) { _lastSavedGifsUpdate = update; } int featuredStickerSetsUnreadCount() const { return _featuredStickerSetsUnreadCount.current(); } void setFeaturedStickerSetsUnreadCount(int count) { _featuredStickerSetsUnreadCount = count; } [[nodiscard]] rpl::producer featuredStickerSetsUnreadCountValue() const { return _featuredStickerSetsUnreadCount.value(); } const Stickers::Sets &stickerSets() const { return _stickerSets; } Stickers::Sets &stickerSetsRef() { return _stickerSets; } const Stickers::Order &stickerSetsOrder() const { return _stickerSetsOrder; } Stickers::Order &stickerSetsOrderRef() { return _stickerSetsOrder; } const Stickers::Order &featuredStickerSetsOrder() const { return _featuredStickerSetsOrder; } Stickers::Order &featuredStickerSetsOrderRef() { return _featuredStickerSetsOrder; } const Stickers::Order &archivedStickerSetsOrder() const { return _archivedStickerSetsOrder; } Stickers::Order &archivedStickerSetsOrderRef() { return _archivedStickerSetsOrder; } const Stickers::SavedGifs &savedGifs() const { return _savedGifs; } Stickers::SavedGifs &savedGifsRef() { return _savedGifs; } HistoryItemsList idsToItems(const MessageIdsList &ids) const; MessageIdsList itemsToIds(const HistoryItemsList &items) const; MessageIdsList itemOrItsGroup(not_null item) const; int pinnedDialogsCount() const; const std::deque &pinnedDialogsOrder() const; void setPinnedDialog(const Dialogs::Key &key, bool pinned); void applyPinnedDialogs(const QVector &list); void applyPinnedDialogs(const QVector &list); void reorderTwoPinnedDialogs( const Dialogs::Key &key1, const Dialogs::Key &key2); void photoLoadSettingsChanged(); void voiceLoadSettingsChanged(); void animationLoadSettingsChanged(); void notifyPhotoLayoutChanged(not_null photo); void notifyDocumentLayoutChanged( not_null document); void requestDocumentViewRepaint(not_null document); void markMediaRead(not_null document); not_null photo(PhotoId id); not_null photo(const MTPPhoto &data); not_null photo(const MTPDphoto &data); not_null photo( const MTPPhoto &data, const PreparedPhotoThumbs &thumbs); not_null photo( PhotoId id, const uint64 &access, const QByteArray &fileReference, TimeId date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full); void photoConvert( not_null original, const MTPPhoto &data); PhotoData *photoFromWeb( const MTPWebDocument &data, ImagePtr thumb = ImagePtr(), bool willBecomeNormal = false); not_null document(DocumentId id); not_null document(const MTPDocument &data); not_null document(const MTPDdocument &data); not_null document( const MTPdocument &data, QImage &&thumb); not_null document( DocumentId id, const uint64 &access, const QByteArray &fileReference, TimeId date, const QVector &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation); void documentConvert( not_null original, const MTPDocument &data); DocumentData *documentFromWeb( const MTPWebDocument &data, ImagePtr thumb); not_null webpage(WebPageId id); not_null webpage(const MTPWebPage &data); not_null webpage(const MTPDwebPage &data); not_null webpage(const MTPDwebPagePending &data); not_null webpage( WebPageId id, const QString &siteName, const TextWithEntities &content); not_null webpage( WebPageId id, WebPageType type, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const TextWithEntities &description, PhotoData *photo, DocumentData *document, WebPageCollage &&collage, int duration, const QString &author, TimeId pendingTill); not_null game(GameId id); not_null game(const MTPDgame &data); not_null game( GameId id, const uint64 &accessHash, const QString &shortName, const QString &title, const QString &description, PhotoData *photo, DocumentData *document); void gameConvert( not_null original, const MTPGame &data); not_null location(const LocationCoords &coords); void registerPhotoItem( not_null photo, not_null item); void unregisterPhotoItem( not_null photo, not_null item); void registerDocumentItem( not_null document, not_null item); void unregisterDocumentItem( not_null document, not_null item); void registerWebPageView( not_null page, not_null view); void unregisterWebPageView( not_null page, not_null view); void registerWebPageItem( not_null page, not_null item); void unregisterWebPageItem( not_null page, not_null item); void registerGameView( not_null game, not_null view); void unregisterGameView( not_null game, not_null view); void registerContactView( UserId contactId, not_null view); void unregisterContactView( UserId contactId, not_null view); void registerContactItem( UserId contactId, not_null item); void unregisterContactItem( UserId contactId, not_null item); void registerAutoplayAnimation( not_null<::Media::Clip::Reader*> reader, not_null view); void unregisterAutoplayAnimation( not_null<::Media::Clip::Reader*> reader); HistoryItem *findWebPageItem(not_null page) const; QString findContactPhone(not_null contact) const; QString findContactPhone(UserId contactId) const; void notifyWebPageUpdateDelayed(not_null page); void notifyGameUpdateDelayed(not_null game); void sendWebPageGameNotifications(); void stopAutoplayAnimations(); void registerItemView(not_null view); void unregisterItemView(not_null view); not_null feed(FeedId id); Feed *feedLoaded(FeedId id); void setDefaultFeedId(FeedId id); FeedId defaultFeedId() const; rpl::producer defaultFeedIdValue() const; void requestNotifySettings(not_null peer); void applyNotifySetting( const MTPNotifyPeer ¬ifyPeer, const MTPPeerNotifySettings &settings); void updateNotifySettings( not_null peer, std::optional muteForSeconds, std::optional silentPosts = std::nullopt); bool notifyIsMuted( not_null peer, TimeMs *changesIn = nullptr) const; bool notifySilentPosts(not_null peer) const; bool notifyMuteUnknown(not_null peer) const; bool notifySilentPostsUnknown(not_null peer) const; bool notifySettingsUnknown(not_null peer) const; rpl::producer<> defaultUserNotifyUpdates() const; rpl::producer<> defaultChatNotifyUpdates() const; rpl::producer<> defaultBroadcastNotifyUpdates() const; rpl::producer<> defaultNotifyUpdates( not_null peer) const; void serviceNotification( const TextWithEntities &message, const MTPMessageMedia &media = MTP_messageMediaEmpty()); void setMimeForwardIds(MessageIdsList &&list); MessageIdsList takeMimeForwardIds(); void setProxyPromoted(PeerData *promoted); PeerData *proxyPromoted() const; Groups &groups() { return _groups; } const Groups &groups() const { return _groups; } private: void suggestStartExport(); void setupContactViewsViewer(); void setupChannelLeavingViewer(); void photoApplyFields( not_null photo, const MTPPhoto &data); void photoApplyFields( not_null photo, const MTPDphoto &data); void photoApplyFields( not_null photo, const uint64 &access, const QByteArray &fileReference, TimeId date, const ImagePtr &thumb, const ImagePtr &medium, const ImagePtr &full); void documentApplyFields( not_null document, const MTPDocument &data); void documentApplyFields( not_null document, const MTPDdocument &data); void documentApplyFields( not_null document, const uint64 &access, const QByteArray &fileReference, TimeId date, const QVector &attributes, const QString &mime, const ImagePtr &thumb, int32 dc, int32 size, const StorageImageLocation &thumbLocation); DocumentData *documentFromWeb( const MTPDwebDocument &data, ImagePtr thumb); DocumentData *documentFromWeb( const MTPDwebDocumentNoProxy &data, ImagePtr thumb); void webpageApplyFields( not_null page, const MTPDwebPage &data); void webpageApplyFields( not_null page, WebPageType type, const QString &url, const QString &displayUrl, const QString &siteName, const QString &title, const TextWithEntities &description, PhotoData *photo, DocumentData *document, WebPageCollage &&collage, int duration, const QString &author, TimeId pendingTill); void gameApplyFields( not_null game, const MTPDgame &data); void gameApplyFields( not_null game, const uint64 &accessHash, const QString &shortName, const QString &title, const QString &description, PhotoData *photo, DocumentData *document); bool stickersUpdateNeeded(TimeMs lastUpdate, TimeMs now) const { constexpr auto kStickersUpdateTimeout = TimeMs(3600'000); return (lastUpdate == 0) || (now >= lastUpdate + kStickersUpdateTimeout); } void userIsContactUpdated(not_null user); void clearPinnedDialogs(); void setIsPinned(const Dialogs::Key &key, bool pinned); NotifySettings &defaultNotifySettings(not_null peer); const NotifySettings &defaultNotifySettings( not_null peer) const; void unmuteByFinished(); void unmuteByFinishedDelayed(TimeMs delay); void updateNotifySettingsLocal(not_null peer); void sendNotifySettingsUpdates(); template void enumerateItemViews( not_null item, Method method); void insertCheckedServiceNotification( const TextWithEntities &message, const MTPMessageMedia &media, TimeId date); not_null _session; Storage::DatabasePointer _cache; std::unique_ptr _export; std::unique_ptr _exportPanel; rpl::event_stream _exportViewChanges; TimeId _exportAvailableAt = 0; QPointer _exportSuggestion; base::Variable _contactsLoaded = { false }; base::Variable _allChatsLoaded = { false }; base::Observable _moreChatsLoaded; base::Observable _queryItemVisibility; rpl::event_stream _itemIdChanges; rpl::event_stream> _itemLayoutChanges; rpl::event_stream> _viewLayoutChanges; rpl::event_stream> _itemRepaintRequest; rpl::event_stream> _viewRepaintRequest; rpl::event_stream> _itemResizeRequest; rpl::event_stream> _viewResizeRequest; rpl::event_stream> _itemViewRefreshRequest; rpl::event_stream> _itemTextRefreshRequest; rpl::event_stream> _animationPlayInlineRequest; rpl::event_stream> _itemRemoved; rpl::event_stream> _viewRemoved; rpl::event_stream> _historyUnloaded; rpl::event_stream> _historyCleared; base::flat_set> _historiesChanged; rpl::event_stream> _historyChanged; rpl::event_stream _megagroupParticipantRemoved; rpl::event_stream _megagroupParticipantAdded; rpl::event_stream _feedUpdates; rpl::event_stream<> _stickersUpdated; rpl::event_stream<> _savedGifsUpdated; TimeMs _lastStickersUpdate = 0; TimeMs _lastRecentStickersUpdate = 0; TimeMs _lastFavedStickersUpdate = 0; TimeMs _lastFeaturedStickersUpdate = 0; TimeMs _lastSavedGifsUpdate = 0; rpl::variable _featuredStickerSetsUnreadCount = 0; Stickers::Sets _stickerSets; Stickers::Order _stickerSetsOrder; Stickers::Order _featuredStickerSetsOrder; Stickers::Order _archivedStickerSetsOrder; Stickers::SavedGifs _savedGifs; std::unordered_map< PhotoId, std::unique_ptr> _photos; std::map< not_null, base::flat_set>> _photoItems; std::unordered_map< DocumentId, std::unique_ptr> _documents; std::map< not_null, base::flat_set>> _documentItems; std::unordered_map< WebPageId, std::unique_ptr> _webpages; std::unordered_map< LocationCoords, std::unique_ptr> _locations; std::map< not_null, base::flat_set>> _webpageItems; std::map< not_null, base::flat_set>> _webpageViews; std::unordered_map< GameId, std::unique_ptr> _games; std::map< not_null, base::flat_set>> _gameViews; std::map< UserId, base::flat_set>> _contactItems; std::map< UserId, base::flat_set>> _contactViews; base::flat_map< not_null<::Media::Clip::Reader*>, not_null> _autoplayAnimations; base::flat_set> _webpagesUpdated; base::flat_set> _gamesUpdated; std::deque _pinnedDialogs; base::flat_map> _feeds; rpl::variable _defaultFeedId = FeedId(); Groups _groups; std::map< not_null, std::vector>> _views; PeerData *_proxyPromoted = nullptr; NotifySettings _defaultUserNotifySettings; NotifySettings _defaultChatNotifySettings; NotifySettings _defaultBroadcastNotifySettings; rpl::event_stream<> _defaultUserNotifyUpdates; rpl::event_stream<> _defaultChatNotifyUpdates; rpl::event_stream<> _defaultBroadcastNotifyUpdates; std::unordered_set> _mutedPeers; base::Timer _unmuteByFinishedTimer; MessageIdsList _mimeForwardIds; using CredentialsWithGeneration = std::pair< const Passport::SavedCredentials, int>; std::unique_ptr _passportCredentials; rpl::lifetime _lifetime; }; } // namespace Data