diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index e485ad9cc4..cbd5cfcac0 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -6782,6 +6782,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_stealth_mode_already_about" = "The creators of stories you view in the next **{left}** won't see you in the viewers' lists."; "lng_stories_link_invalid" = "This link is broken or has expired."; +"lng_stories_live_finished" = "The live story has ended."; "lng_stats_title" = "Statistics"; "lng_stats_message_title" = "Message Statistic"; diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 30592eb60f..7aaef1e56e 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -787,8 +787,10 @@ QString ApiWrap::exportDirectStoryLink(not_null story) { const auto peer = story->peer(); const auto fallback = [&] { const auto base = peer->username(); - const auto story = QString::number(storyId.story); - const auto query = base + "/s/" + story; + const auto id = story->call() + ? u"live"_q + : QString::number(storyId.story); + const auto query = base + "/s/" + id; return session().createInternalLinkFull(query); }; const auto i = _unlikelyStoryLinks.find(storyId); diff --git a/Telegram/SourceFiles/core/local_url_handlers.cpp b/Telegram/SourceFiles/core/local_url_handlers.cpp index 2f71bb6fbc..49350e6893 100644 --- a/Telegram/SourceFiles/core/local_url_handlers.cpp +++ b/Telegram/SourceFiles/core/local_url_handlers.cpp @@ -662,7 +662,6 @@ bool ResolveUsernameOrPhone( post = postId; } const auto storyParam = params.value(u"story"_q); - const auto storyId = storyParam.toInt(); const auto storyAlbumParam = params.value(u"album"_q); const auto storyAlbumId = storyAlbumParam.toInt(); const auto giftCollectionParam = params.value(u"collection"_q); @@ -694,7 +693,7 @@ bool ResolveUsernameOrPhone( .usernameOrId = domain, .phone = phone, .messageId = post, - .storyId = storyId, + .storyParam = storyParam, .storyAlbumId = storyAlbumId, .giftCollectionId = giftCollectionId, .videoTimestamp = (!videot.isEmpty() @@ -1975,7 +1974,7 @@ QString TryConvertUrlToLocal(QString url) { "/?$|" "/[a-zA-Z0-9\\.\\_\\-]+/?(\\?|$)|" "/\\d+/?(\\?|$)|" - "/s/\\d+/?(\\?|$)|" + "/s/(\\d+|live)/?(\\?|$)|" "/a/\\d+/?(\\?|$)|" "/c/\\d+/?(\\?|$)|" "/\\d+/\\d+/?(\\?|$)" @@ -1998,7 +1997,7 @@ QString TryConvertUrlToLocal(QString url) { added = u"&topic=%1&post=%2"_q.arg(threadPostMatch->captured(1), threadPostMatch->captured(2)); } else if (const auto postMatch = regex_match(u"^/(\\d+)(/?\\?|/?$)"_q, usernameMatch->captured(2))) { added = u"&post="_q + postMatch->captured(1); - } else if (const auto storyMatch = regex_match(u"^/s/(\\d+)(/?\\?|/?$)"_q, usernameMatch->captured(2))) { + } else if (const auto storyMatch = regex_match(u"^/s/(\\d+|live)(/?\\?|/?$)"_q, usernameMatch->captured(2))) { added = u"&story="_q + storyMatch->captured(1); } else if (const auto albumMatch = regex_match(u"^/a/(\\d+)(/?\\?|/?$)"_q, usernameMatch->captured(2))) { added = u"&album="_q + albumMatch->captured(1); diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 9433f83ab2..ecf53a0514 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -661,19 +661,18 @@ void SessionNavigation::showPeerByLinkResolved( info.messageId, callback); } - } else if (info.storyId) { - const auto storyId = FullStoryId{ peer->id, info.storyId }; + } else if (info.storyParam == u"live"_q) { + parentController()->openPeerStories(peer->id, std::nullopt, true); + } else if (const auto storyId = info.storyParam.toInt()) { + const auto id = FullStoryId{ peer->id, storyId }; const auto context = (info.storyAlbumId > 0) ? Data::StoriesContext{ Data::StoriesContextAlbum{ info.storyAlbumId, } } : Data::StoriesContext{ Data::StoriesContextSingle() }; - peer->owner().stories().resolve(storyId, crl::guard(this, [=] { - if (peer->owner().stories().lookup(storyId)) { - parentController()->openPeerStory( - peer, - storyId.story, - context); + peer->owner().stories().resolve(id, crl::guard(this, [=] { + if (peer->owner().stories().lookup(id)) { + parentController()->openPeerStory(peer, id.story, context); } else { showToast(tr::lng_stories_link_invalid(tr::now)); } @@ -3514,7 +3513,9 @@ void SessionController::openPeerStory( void SessionController::openPeerStories( PeerId peerId, - std::optional list) { + std::optional list, + bool onlyLive, + bool afterReload) { using namespace Media::View; using namespace Data; @@ -3522,16 +3523,26 @@ void SessionController::openPeerStories( auto &stories = session().data().stories(); if (const auto source = stories.source(peerId)) { if (const auto idDates = source->toOpen()) { + if (onlyLive && !idDates.videoStream) { + showToast(tr::lng_stories_live_finished(tr::now)); + return; + } openPeerStory( source->peer, idDates.id, (list ? StoriesContext{ *list } : StoriesContext{ StoriesContextPeer() })); + } else if (onlyLive) { + showToast(tr::lng_stories_live_finished(tr::now)); + } + } else if (afterReload) { + if (onlyLive) { + showToast(tr::lng_stories_live_finished(tr::now)); } } else if (const auto peer = session().data().peerLoaded(peerId)) { const auto done = crl::guard(&_storyOpenGuard, [=] { - openPeerStories(peerId, list); + openPeerStories(peerId, list, onlyLive, true); }); stories.requestPeerStories(peer, done); } diff --git a/Telegram/SourceFiles/window/window_session_controller.h b/Telegram/SourceFiles/window/window_session_controller.h index be206dadf0..d0f74aa1ab 100644 --- a/Telegram/SourceFiles/window/window_session_controller.h +++ b/Telegram/SourceFiles/window/window_session_controller.h @@ -655,7 +655,9 @@ public: Data::StoriesContext context); void openPeerStories( PeerId peerId, - std::optional list = std::nullopt); + std::optional list = std::nullopt, + bool onlyLive = false, + bool afterReload = false); [[nodiscard]] Ui::ChatPaintContext preparePaintContext( Ui::ChatPaintContextArgs &&args); diff --git a/Telegram/SourceFiles/window/window_session_controller_link_info.h b/Telegram/SourceFiles/window/window_session_controller_link_info.h index 71590b4221..a8ecd9ac5d 100644 --- a/Telegram/SourceFiles/window/window_session_controller_link_info.h +++ b/Telegram/SourceFiles/window/window_session_controller_link_info.h @@ -40,7 +40,7 @@ struct PeerByLinkInfo { QString phone; QString chatLinkSlug; MsgId messageId = ShowAtUnreadMsgId; - StoryId storyId = 0; + QString storyParam; int storyAlbumId = 0; int giftCollectionId = 0; std::optional videoTimestamp;