From 0edbb91b72b056dca43517677fa5f4d46b1998a7 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 26 May 2023 19:18:10 +0400 Subject: [PATCH] Process media edition updates from API. --- Telegram/Resources/langs/lang.strings | 1 + Telegram/SourceFiles/data/data_stories.cpp | 90 ++++++++++++++-------- Telegram/SourceFiles/data/data_stories.h | 4 +- 3 files changed, 60 insertions(+), 35 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 1b1d41d18..7fa025d38 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1962,6 +1962,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_in_dlg_sticker" = "Sticker"; "lng_in_dlg_sticker_emoji" = "{emoji} Sticker"; "lng_in_dlg_poll" = "Poll"; +"lng_in_dlg_story" = "Story"; "lng_in_dlg_media_count#one" = "{count} media"; "lng_in_dlg_media_count#other" = "{count} media"; "lng_in_dlg_photo_count#one" = "{count} photo"; diff --git a/Telegram/SourceFiles/data/data_stories.cpp b/Telegram/SourceFiles/data/data_stories.cpp index 3f12fd6fe..149125377 100644 --- a/Telegram/SourceFiles/data/data_stories.cpp +++ b/Telegram/SourceFiles/data/data_stories.cpp @@ -31,6 +31,31 @@ constexpr auto kMaxResolveTogether = 100; using UpdateFlag = StoryUpdate::Flag; +std::optional ParseMedia( + not_null owner, + const MTPMessageMedia &media) { + return media.match([&](const MTPDmessageMediaPhoto &data) + -> std::optional { + if (const auto photo = data.vphoto()) { + const auto result = owner->processPhoto(*photo); + if (!result->isNull()) { + return StoryMedia{ result }; + } + } + return {}; + }, [&](const MTPDmessageMediaDocument &data) + -> std::optional { + if (const auto document = data.vdocument()) { + const auto result = owner->processDocument(*document); + if (!result->isNull() + && (result->isGifv() || result->isVideoFile())) { + return StoryMedia{ result }; + } + } + return {}; + }, [](const auto &) { return std::optional(); }); +} + } // namespace bool StoriesList::unread() const { @@ -109,7 +134,7 @@ Image *Story::replyPreview() const { } TextWithEntities Story::inReplyText() const { - const auto type = u"Story"_q; + const auto type = tr::lng_in_dlg_story(tr::now); return _caption.text.isEmpty() ? Ui::Text::PlainLink(type) : tr::lng_dialogs_text_media( @@ -141,14 +166,24 @@ const TextWithEntities &Story::caption() const { return _caption; } -void Story::apply(const MTPDstoryItem &data) { - _pinned = data.is_pinned(); - _caption = TextWithEntities{ +bool Story::applyChanges(StoryMedia media, const MTPDstoryItem &data) { + const auto pinned = data.is_pinned(); + auto caption = TextWithEntities{ data.vcaption().value_or_empty(), Api::EntitiesFromMTP( &owner().session(), data.ventities().value_or_empty()), }; + const auto changed = (_media != media) + || (_pinned != pinned) + || (_caption != caption); + if (!changed) { + return false; + } + _media = std::move(media); + _pinned = pinned; + _caption = std::move(caption); + return true; } Stories::Stories(not_null owner) : _owner(owner) { @@ -184,9 +219,10 @@ StoriesList Stories::parse(const MTPUserStories &stories) { result.ids.reserve(list.size()); for (const auto &story : list) { story.match([&](const MTPDstoryItem &data) { - if (const auto story = parse(result.user, data)) { + if (const auto story = parseAndApply(result.user, data)) { result.ids.push_back(story->id()); } else { + applyDeleted({ peerFromUser(userId), data.vid().v }); --result.total; } }, [&](const MTPDstoryItemSkipped &data) { @@ -200,44 +236,30 @@ StoriesList Stories::parse(const MTPUserStories &stories) { return result; } -Story *Stories::parse(not_null peer, const MTPDstoryItem &data) { +Story *Stories::parseAndApply( + not_null peer, + const MTPDstoryItem &data) { + const auto media = ParseMedia(_owner, data.vmedia()); + if (!media) { + return nullptr; + } const auto id = data.vid().v; auto &stories = _stories[peer->id]; const auto i = stories.find(id); if (i != end(stories)) { - i->second->apply(data); + if (i->second->applyChanges(*media, data)) { + session().changes().storyUpdated( + i->second.get(), + UpdateFlag::Edited); + } return i->second.get(); } - using MaybeMedia = std::optional< - std::variant, not_null>>; - const auto media = data.vmedia().match([&]( - const MTPDmessageMediaPhoto &data) -> MaybeMedia { - if (const auto photo = data.vphoto()) { - const auto result = _owner->processPhoto(*photo); - if (!result->isNull()) { - return result; - } - } - return {}; - }, [&](const MTPDmessageMediaDocument &data) -> MaybeMedia { - if (const auto document = data.vdocument()) { - const auto result = _owner->processDocument(*document); - if (!result->isNull() - && (result->isGifv() || result->isVideoFile())) { - return result; - } - } - return {}; - }, [](const auto &) { return MaybeMedia(); }); - if (!media) { - return nullptr; - } const auto result = stories.emplace(id, std::make_unique( id, peer, StoryMedia{ *media }, data.vdate().v)).first->second.get(); - result->apply(data); + result->applyChanges(*media, data); return result; } @@ -373,7 +395,9 @@ void Stories::processResolvedStories( const QVector &list) { for (const auto &item : list) { item.match([&](const MTPDstoryItem &data) { - [[maybe_unused]] const auto story = parse(peer, data); + if (!parseAndApply(peer, data)) { + applyDeleted({ peer->id, data.vid().v }); + } }, [&](const MTPDstoryItemSkipped &data) { LOG(("API Error: Unexpected storyItemSkipped in resolve.")); }, [&](const MTPDstoryItemDeleted &data) { diff --git a/Telegram/SourceFiles/data/data_stories.h b/Telegram/SourceFiles/data/data_stories.h index 979cba19b..c669fe47c 100644 --- a/Telegram/SourceFiles/data/data_stories.h +++ b/Telegram/SourceFiles/data/data_stories.h @@ -56,7 +56,7 @@ public: void setCaption(TextWithEntities &&caption); [[nodiscard]] const TextWithEntities &caption() const; - void apply(const MTPDstoryItem &data); + bool applyChanges(StoryMedia media, const MTPDstoryItem &data); private: const StoryId _id = 0; @@ -113,7 +113,7 @@ public: private: [[nodiscard]] StoriesList parse(const MTPUserStories &stories); - [[nodiscard]] Story *parse( + [[nodiscard]] Story *parseAndApply( not_null peer, const MTPDstoryItem &data); void processResolvedStories(