mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Allow sharing video at a timestamp.
This commit is contained in:
parent
2077f51084
commit
999a13358e
12 changed files with 200 additions and 16 deletions
|
@ -4157,6 +4157,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_reply_cant_forward" = "Sorry, you can't reply to a message that was sent before the group was upgraded to a supergroup. Do you wish to forward it and add your comment?";
|
"lng_reply_cant_forward" = "Sorry, you can't reply to a message that was sent before the group was upgraded to a supergroup. Do you wish to forward it and add your comment?";
|
||||||
|
|
||||||
"lng_share_title" = "Share to";
|
"lng_share_title" = "Share to";
|
||||||
|
"lng_share_at_time_title" = "Share at {time} to";
|
||||||
"lng_share_copy_link" = "Copy share link";
|
"lng_share_copy_link" = "Copy share link";
|
||||||
"lng_share_confirm" = "Send";
|
"lng_share_confirm" = "Send";
|
||||||
"lng_share_wrong_user" = "This game was opened from a different user.";
|
"lng_share_wrong_user" = "This game was opened from a different user.";
|
||||||
|
@ -4280,7 +4281,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_media_save_progress" = "{ready} of {total} {mb}";
|
"lng_media_save_progress" = "{ready} of {total} {mb}";
|
||||||
"lng_mediaview_save_as" = "Save As...";
|
"lng_mediaview_save_as" = "Save As...";
|
||||||
"lng_mediaview_copy" = "Copy";
|
"lng_mediaview_copy" = "Copy";
|
||||||
|
"lng_mediaview_copy_frame" = "Copy Frame";
|
||||||
"lng_mediaview_forward" = "Forward";
|
"lng_mediaview_forward" = "Forward";
|
||||||
|
"lng_mediaview_share_at_time" = "Share at {time}";
|
||||||
"lng_mediaview_delete" = "Delete";
|
"lng_mediaview_delete" = "Delete";
|
||||||
"lng_mediaview_save_to_profile" = "Post to Profile";
|
"lng_mediaview_save_to_profile" = "Post to Profile";
|
||||||
"lng_mediaview_pin_story_done" = "Story pinned";
|
"lng_mediaview_pin_story_done" = "Story pinned";
|
||||||
|
|
|
@ -142,6 +142,16 @@ void ShowChannelsLimitBox(not_null<PeerData*> peer) {
|
||||||
action.replaceMediaOf);
|
action.replaceMediaOf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] QString FormatVideoTimestamp(TimeId seconds) {
|
||||||
|
const auto minutes = seconds / 60;
|
||||||
|
const auto hours = minutes / 60;
|
||||||
|
return hours
|
||||||
|
? u"%1h%2m%3s"_q.arg(hours).arg(minutes % 60).arg(seconds % 60)
|
||||||
|
: minutes
|
||||||
|
? u"%1m%2s"_q.arg(minutes).arg(seconds % 60)
|
||||||
|
: QString::number(seconds);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ApiWrap::ApiWrap(not_null<Main::Session*> session)
|
ApiWrap::ApiWrap(not_null<Main::Session*> session)
|
||||||
|
@ -717,7 +727,8 @@ void ApiWrap::finalizeMessageDataRequest(
|
||||||
QString ApiWrap::exportDirectMessageLink(
|
QString ApiWrap::exportDirectMessageLink(
|
||||||
not_null<HistoryItem*> item,
|
not_null<HistoryItem*> item,
|
||||||
bool inRepliesContext,
|
bool inRepliesContext,
|
||||||
bool forceNonPublicLink) {
|
bool forceNonPublicLink,
|
||||||
|
std::optional<TimeId> videoTimestamp) {
|
||||||
Expects(item->history()->peer->isChannel());
|
Expects(item->history()->peer->isChannel());
|
||||||
|
|
||||||
const auto itemId = item->fullId();
|
const auto itemId = item->fullId();
|
||||||
|
@ -790,7 +801,14 @@ QString ApiWrap::exportDirectMessageLink(
|
||||||
_unlikelyMessageLinks.emplace_or_assign(itemId, link);
|
_unlikelyMessageLinks.emplace_or_assign(itemId, link);
|
||||||
}
|
}
|
||||||
}).send();
|
}).send();
|
||||||
return current;
|
const auto addTimestamp = channel->hasUsername()
|
||||||
|
&& !inRepliesContext
|
||||||
|
&& videoTimestamp.has_value();
|
||||||
|
const auto addedSeparator = (current.indexOf('?') >= 0) ? '&' : '?';
|
||||||
|
const auto addedTimestamp = addTimestamp
|
||||||
|
? (addedSeparator + u"t="_q + FormatVideoTimestamp(*videoTimestamp))
|
||||||
|
: QString();
|
||||||
|
return current + addedTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ApiWrap::exportDirectStoryLink(not_null<Data::Story*> story) {
|
QString ApiWrap::exportDirectStoryLink(not_null<Data::Story*> story) {
|
||||||
|
|
|
@ -166,7 +166,8 @@ public:
|
||||||
QString exportDirectMessageLink(
|
QString exportDirectMessageLink(
|
||||||
not_null<HistoryItem*> item,
|
not_null<HistoryItem*> item,
|
||||||
bool inRepliesContext,
|
bool inRepliesContext,
|
||||||
bool forceNonPublicLink = false);
|
bool forceNonPublicLink = false,
|
||||||
|
std::optional<TimeId> videoTimestamp = {});
|
||||||
QString exportDirectStoryLink(not_null<Data::Story*> item);
|
QString exportDirectStoryLink(not_null<Data::Story*> item);
|
||||||
|
|
||||||
void requestContacts();
|
void requestContacts();
|
||||||
|
|
|
@ -277,7 +277,9 @@ void ShareBox::prepare() {
|
||||||
_select->resizeToWidth(st::boxWideWidth);
|
_select->resizeToWidth(st::boxWideWidth);
|
||||||
Ui::SendPendingMoveResizeEvents(_select);
|
Ui::SendPendingMoveResizeEvents(_select);
|
||||||
|
|
||||||
setTitle(tr::lng_share_title());
|
setTitle(_descriptor.titleOverride
|
||||||
|
? std::move(_descriptor.titleOverride)
|
||||||
|
: tr::lng_share_title());
|
||||||
|
|
||||||
_inner = setInnerWidget(
|
_inner = setInnerWidget(
|
||||||
object_ptr<Inner>(this, _descriptor, uiShow()),
|
object_ptr<Inner>(this, _descriptor, uiShow()),
|
||||||
|
@ -1495,7 +1497,8 @@ ChatHelpers::ForwardedMessagePhraseArgs CreateForwardedMessagePhraseArgs(
|
||||||
ShareBox::SubmitCallback ShareBox::DefaultForwardCallback(
|
ShareBox::SubmitCallback ShareBox::DefaultForwardCallback(
|
||||||
std::shared_ptr<Ui::Show> show,
|
std::shared_ptr<Ui::Show> show,
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
MessageIdsList msgIds) {
|
MessageIdsList msgIds,
|
||||||
|
std::optional<TimeId> videoTimestamp) {
|
||||||
struct State final {
|
struct State final {
|
||||||
base::flat_set<mtpRequestId> requests;
|
base::flat_set<mtpRequestId> requests;
|
||||||
};
|
};
|
||||||
|
@ -1531,6 +1534,9 @@ ShareBox::SubmitCallback ShareBox::DefaultForwardCallback(
|
||||||
: Flag(0))
|
: Flag(0))
|
||||||
| ((forwardOptions == Data::ForwardOptions::NoNamesAndCaptions)
|
| ((forwardOptions == Data::ForwardOptions::NoNamesAndCaptions)
|
||||||
? Flag::f_drop_media_captions
|
? Flag::f_drop_media_captions
|
||||||
|
: Flag(0))
|
||||||
|
| (videoTimestamp.has_value()
|
||||||
|
? Flag::f_video_timestamp
|
||||||
: Flag(0));
|
: Flag(0));
|
||||||
auto mtpMsgIds = QVector<MTPint>();
|
auto mtpMsgIds = QVector<MTPint>();
|
||||||
mtpMsgIds.reserve(existingIds.size());
|
mtpMsgIds.reserve(existingIds.size());
|
||||||
|
@ -1588,7 +1594,7 @@ ShareBox::SubmitCallback ShareBox::DefaultForwardCallback(
|
||||||
MTP_int(options.scheduled),
|
MTP_int(options.scheduled),
|
||||||
MTP_inputPeerEmpty(), // send_as
|
MTP_inputPeerEmpty(), // send_as
|
||||||
Data::ShortcutIdToMTP(session, options.shortcutId),
|
Data::ShortcutIdToMTP(session, options.shortcutId),
|
||||||
MTPint() // video_timestamp
|
MTP_int(videoTimestamp.value_or(0))
|
||||||
)).done([=](const MTPUpdates &updates, mtpRequestId reqId) {
|
)).done([=](const MTPUpdates &updates, mtpRequestId reqId) {
|
||||||
threadHistory->session().api().applyUpdates(updates);
|
threadHistory->session().api().applyUpdates(updates);
|
||||||
state->requests.remove(reqId);
|
state->requests.remove(reqId);
|
||||||
|
|
|
@ -104,7 +104,8 @@ public:
|
||||||
[[nodiscard]] static SubmitCallback DefaultForwardCallback(
|
[[nodiscard]] static SubmitCallback DefaultForwardCallback(
|
||||||
std::shared_ptr<Ui::Show> show,
|
std::shared_ptr<Ui::Show> show,
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
MessageIdsList msgIds);
|
MessageIdsList msgIds,
|
||||||
|
std::optional<TimeId> videoTimestamp = {});
|
||||||
|
|
||||||
struct Descriptor {
|
struct Descriptor {
|
||||||
not_null<Main::Session*> session;
|
not_null<Main::Session*> session;
|
||||||
|
@ -113,7 +114,9 @@ public:
|
||||||
FilterCallback filterCallback;
|
FilterCallback filterCallback;
|
||||||
object_ptr<Ui::RpWidget> bottomWidget = { nullptr };
|
object_ptr<Ui::RpWidget> bottomWidget = { nullptr };
|
||||||
rpl::producer<QString> copyLinkText;
|
rpl::producer<QString> copyLinkText;
|
||||||
|
rpl::producer<QString> titleOverride;
|
||||||
ShareBoxStyleOverrides st;
|
ShareBoxStyleOverrides st;
|
||||||
|
std::optional<TimeId> videoTimestamp;
|
||||||
struct {
|
struct {
|
||||||
int sendersCount = 0;
|
int sendersCount = 0;
|
||||||
int captionsCount = 0;
|
int captionsCount = 0;
|
||||||
|
|
|
@ -1295,25 +1295,28 @@ base::unique_qptr<Ui::PopupMenu> FillContextMenu(
|
||||||
void CopyPostLink(
|
void CopyPostLink(
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
FullMsgId itemId,
|
FullMsgId itemId,
|
||||||
Context context) {
|
Context context,
|
||||||
CopyPostLink(controller->uiShow(), itemId, context);
|
std::optional<TimeId> videoTimestamp) {
|
||||||
|
CopyPostLink(controller->uiShow(), itemId, context, videoTimestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CopyPostLink(
|
void CopyPostLink(
|
||||||
std::shared_ptr<Main::SessionShow> show,
|
std::shared_ptr<Main::SessionShow> show,
|
||||||
FullMsgId itemId,
|
FullMsgId itemId,
|
||||||
Context context) {
|
Context context,
|
||||||
|
std::optional<TimeId> videoTimestamp) {
|
||||||
const auto item = show->session().data().message(itemId);
|
const auto item = show->session().data().message(itemId);
|
||||||
if (!item || !item->hasDirectLink()) {
|
if (!item || !item->hasDirectLink()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto inRepliesContext = (context == Context::Replies);
|
const auto inRepliesContext = (context == Context::Replies);
|
||||||
const auto forceNonPublicLink = base::IsCtrlPressed();
|
const auto forceNonPublicLink = !videoTimestamp && base::IsCtrlPressed();
|
||||||
QGuiApplication::clipboard()->setText(
|
QGuiApplication::clipboard()->setText(
|
||||||
item->history()->session().api().exportDirectMessageLink(
|
item->history()->session().api().exportDirectMessageLink(
|
||||||
item,
|
item,
|
||||||
inRepliesContext,
|
inRepliesContext,
|
||||||
forceNonPublicLink));
|
forceNonPublicLink,
|
||||||
|
videoTimestamp));
|
||||||
|
|
||||||
const auto isPublicLink = [&] {
|
const auto isPublicLink = [&] {
|
||||||
if (forceNonPublicLink) {
|
if (forceNonPublicLink) {
|
||||||
|
@ -1334,7 +1337,7 @@ void CopyPostLink(
|
||||||
}
|
}
|
||||||
return channel->hasUsername();
|
return channel->hasUsername();
|
||||||
}();
|
}();
|
||||||
if (isPublicLink) {
|
if (isPublicLink && !videoTimestamp) {
|
||||||
show->showToast({
|
show->showToast({
|
||||||
.text = tr::lng_channel_public_link_copied(
|
.text = tr::lng_channel_public_link_copied(
|
||||||
tr::now, Ui::Text::Bold
|
tr::now, Ui::Text::Bold
|
||||||
|
|
|
@ -60,11 +60,13 @@ base::unique_qptr<Ui::PopupMenu> FillContextMenu(
|
||||||
void CopyPostLink(
|
void CopyPostLink(
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
FullMsgId itemId,
|
FullMsgId itemId,
|
||||||
Context context);
|
Context context,
|
||||||
|
std::optional<TimeId> videoTimestamp = {});
|
||||||
void CopyPostLink(
|
void CopyPostLink(
|
||||||
std::shared_ptr<Main::SessionShow> show,
|
std::shared_ptr<Main::SessionShow> show,
|
||||||
FullMsgId itemId,
|
FullMsgId itemId,
|
||||||
Context context);
|
Context context,
|
||||||
|
std::optional<TimeId> videoTimestamp = {});
|
||||||
void CopyStoryLink(
|
void CopyStoryLink(
|
||||||
std::shared_ptr<Main::SessionShow> show,
|
std::shared_ptr<Main::SessionShow> show,
|
||||||
FullStoryId storyId);
|
FullStoryId storyId);
|
||||||
|
|
|
@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "boxes/share_box.h"
|
#include "boxes/share_box.h"
|
||||||
#include "chat_helpers/compose/compose_show.h"
|
#include "chat_helpers/compose/compose_show.h"
|
||||||
#include "data/business/data_shortcut_messages.h"
|
#include "data/business/data_shortcut_messages.h"
|
||||||
|
#include "data/data_channel.h"
|
||||||
#include "data/data_chat_participant_status.h"
|
#include "data/data_chat_participant_status.h"
|
||||||
#include "data/data_forum_topic.h"
|
#include "data/data_forum_topic.h"
|
||||||
#include "data/data_histories.h"
|
#include "data/data_histories.h"
|
||||||
|
@ -181,4 +182,83 @@ namespace Media::Stories {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString FormatShareAtTime(TimeId seconds) {
|
||||||
|
const auto minutes = seconds / 60;
|
||||||
|
const auto h = minutes / 60;
|
||||||
|
const auto m = minutes % 60;
|
||||||
|
const auto s = seconds % 60;
|
||||||
|
const auto zero = QChar('0');
|
||||||
|
return h
|
||||||
|
? u"%1:%2:%3"_q.arg(h).arg(m, 2, 10, zero).arg(s, 2, 10, zero)
|
||||||
|
: u"%1:%2"_q.arg(m).arg(s, 2, 10, zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
object_ptr<Ui::BoxContent> PrepareShareAtTimeBox(
|
||||||
|
std::shared_ptr<ChatHelpers::Show> show,
|
||||||
|
not_null<HistoryItem*> item,
|
||||||
|
TimeId videoTimestamp) {
|
||||||
|
const auto id = item->fullId();
|
||||||
|
const auto history = item->history();
|
||||||
|
const auto owner = &history->owner();
|
||||||
|
const auto session = &history->session();
|
||||||
|
const auto canCopyLink = item->hasDirectLink()
|
||||||
|
&& history->peer->isBroadcast()
|
||||||
|
&& history->peer->asBroadcast()->hasUsername();
|
||||||
|
const auto hasCaptions = item->media()
|
||||||
|
&& !item->originalText().text.isEmpty()
|
||||||
|
&& item->media()->allowsEditCaption();
|
||||||
|
const auto hasOnlyForcedForwardedInfo = !hasCaptions
|
||||||
|
&& item->media()
|
||||||
|
&& item->media()->forceForwardedInfo();
|
||||||
|
|
||||||
|
auto copyCallback = [=] {
|
||||||
|
const auto item = owner->message(id);
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CopyPostLink(
|
||||||
|
show,
|
||||||
|
item->fullId(),
|
||||||
|
HistoryView::Context::History,
|
||||||
|
videoTimestamp);
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto requiredRight = item->requiredSendRight();
|
||||||
|
const auto requiresInline = item->requiresSendInlineRight();
|
||||||
|
auto filterCallback = [=](not_null<Data::Thread*> thread) {
|
||||||
|
if (const auto user = thread->peer()->asUser()) {
|
||||||
|
if (user->canSendIgnoreRequirePremium()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Data::CanSend(thread, requiredRight)
|
||||||
|
&& (!requiresInline
|
||||||
|
|| Data::CanSend(thread, ChatRestriction::SendInline));
|
||||||
|
};
|
||||||
|
auto copyLinkCallback = canCopyLink
|
||||||
|
? Fn<void()>(std::move(copyCallback))
|
||||||
|
: Fn<void()>();
|
||||||
|
const auto st = ::Settings::DarkCreditsEntryBoxStyle();
|
||||||
|
return Box<ShareBox>(ShareBox::Descriptor{
|
||||||
|
.session = session,
|
||||||
|
.copyCallback = std::move(copyLinkCallback),
|
||||||
|
.submitCallback = ShareBox::DefaultForwardCallback(
|
||||||
|
show,
|
||||||
|
history,
|
||||||
|
{ id },
|
||||||
|
videoTimestamp),
|
||||||
|
.filterCallback = std::move(filterCallback),
|
||||||
|
.titleOverride = tr::lng_share_at_time_title(
|
||||||
|
lt_time,
|
||||||
|
rpl::single(FormatShareAtTime(videoTimestamp))),
|
||||||
|
.st = st.shareBox ? *st.shareBox : ShareBoxStyleOverrides(),
|
||||||
|
.forwardOptions = {
|
||||||
|
.sendersCount = ItemsForwardSendersCount({ item }),
|
||||||
|
.captionsCount = ItemsForwardCaptionsCount({ item }),
|
||||||
|
.show = !hasOnlyForcedForwardedInfo,
|
||||||
|
},
|
||||||
|
.premiumRequiredError = SharePremiumRequiredError(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Media::Stories
|
} // namespace Media::Stories
|
||||||
|
|
|
@ -24,4 +24,11 @@ namespace Media::Stories {
|
||||||
FullStoryId id,
|
FullStoryId id,
|
||||||
bool viewerStyle = false);
|
bool viewerStyle = false);
|
||||||
|
|
||||||
|
[[nodiscard]] QString FormatShareAtTime(TimeId seconds);
|
||||||
|
|
||||||
|
[[nodiscard]] object_ptr<Ui::BoxContent> PrepareShareAtTimeBox(
|
||||||
|
std::shared_ptr<ChatHelpers::Show> show,
|
||||||
|
not_null<HistoryItem*> item,
|
||||||
|
TimeId videoTimestamp);
|
||||||
|
|
||||||
} // namespace Media::Stories
|
} // namespace Media::Stories
|
||||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "api/api_attached_stickers.h"
|
#include "api/api_attached_stickers.h"
|
||||||
#include "api/api_peer_photo.h"
|
#include "api/api_peer_photo.h"
|
||||||
#include "base/qt/qt_common_adapters.h"
|
#include "base/qt/qt_common_adapters.h"
|
||||||
|
#include "base/timer_rpl.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "menu/menu_sponsored.h"
|
#include "menu/menu_sponsored.h"
|
||||||
#include "boxes/premium_preview_box.h"
|
#include "boxes/premium_preview_box.h"
|
||||||
|
@ -50,6 +51,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "media/view/media_view_pip.h"
|
#include "media/view/media_view_pip.h"
|
||||||
#include "media/view/media_view_overlay_raster.h"
|
#include "media/view/media_view_overlay_raster.h"
|
||||||
#include "media/view/media_view_overlay_opengl.h"
|
#include "media/view/media_view_overlay_opengl.h"
|
||||||
|
#include "media/stories/media_stories_share.h"
|
||||||
#include "media/stories/media_stories_view.h"
|
#include "media/stories/media_stories_view.h"
|
||||||
#include "media/streaming/media_streaming_document.h"
|
#include "media/streaming/media_streaming_document.h"
|
||||||
#include "media/streaming/media_streaming_player.h"
|
#include "media/streaming/media_streaming_player.h"
|
||||||
|
@ -1646,7 +1648,9 @@ void OverlayWidget::fillContextMenuActions(
|
||||||
if (!hasCopyMediaRestriction()) {
|
if (!hasCopyMediaRestriction()) {
|
||||||
if ((_document && documentContentShown()) || (_photo && _photoMedia->loaded())) {
|
if ((_document && documentContentShown()) || (_photo && _photoMedia->loaded())) {
|
||||||
addAction(
|
addAction(
|
||||||
tr::lng_mediaview_copy(tr::now),
|
((_document && _streamed)
|
||||||
|
? tr::lng_mediaview_copy_frame(tr::now)
|
||||||
|
: tr::lng_mediaview_copy(tr::now)),
|
||||||
[=] { copyMedia(); },
|
[=] { copyMedia(); },
|
||||||
&st::mediaMenuIconCopy);
|
&st::mediaMenuIconCopy);
|
||||||
}
|
}
|
||||||
|
@ -1663,6 +1667,31 @@ void OverlayWidget::fillContextMenuActions(
|
||||||
tr::lng_mediaview_forward(tr::now),
|
tr::lng_mediaview_forward(tr::now),
|
||||||
[=] { forwardMedia(); },
|
[=] { forwardMedia(); },
|
||||||
&st::mediaMenuIconForward);
|
&st::mediaMenuIconForward);
|
||||||
|
if (canShareAtTime()) {
|
||||||
|
const auto now = [=] {
|
||||||
|
return tr::lng_mediaview_share_at_time(
|
||||||
|
tr::now,
|
||||||
|
lt_time,
|
||||||
|
Stories::FormatShareAtTime(shareAtVideoTimestamp()));
|
||||||
|
};
|
||||||
|
const auto action = addAction(
|
||||||
|
now(),
|
||||||
|
[=] { shareAtTime(); },
|
||||||
|
&st::mediaMenuIconShare);
|
||||||
|
struct State {
|
||||||
|
rpl::variable<QString> text;
|
||||||
|
rpl::lifetime lifetime;
|
||||||
|
};
|
||||||
|
const auto state = Ui::CreateChild<State>(action);
|
||||||
|
state->text = rpl::single(
|
||||||
|
rpl::empty
|
||||||
|
) | rpl::then(
|
||||||
|
base::timer_each(120)
|
||||||
|
) | rpl::map(now);
|
||||||
|
state->text.changes() | rpl::start_with_next([=](QString value) {
|
||||||
|
action->setText(value);
|
||||||
|
}, state->lifetime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (story && story->canShare()) {
|
if (story && story->canShare()) {
|
||||||
addAction(tr::lng_mediaview_forward(tr::now), [=] {
|
addAction(tr::lng_mediaview_forward(tr::now), [=] {
|
||||||
|
@ -2638,6 +2667,33 @@ void OverlayWidget::handleDocumentClick() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OverlayWidget::canShareAtTime() const {
|
||||||
|
const auto media = _message ? _message->media() : nullptr;
|
||||||
|
return _document
|
||||||
|
&& media
|
||||||
|
&& _streamed
|
||||||
|
&& (_document == media->document())
|
||||||
|
&& _document->isVideoFile()
|
||||||
|
&& !media->webpage();
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeId OverlayWidget::shareAtVideoTimestamp() const {
|
||||||
|
return _streamedPosition / crl::time(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OverlayWidget::shareAtTime() {
|
||||||
|
if (!canShareAtTime()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!_streamed->instance.player().paused()
|
||||||
|
&& !_streamed->instance.player().finished()) {
|
||||||
|
playbackPauseResume();
|
||||||
|
}
|
||||||
|
const auto show = uiShow();
|
||||||
|
const auto timestamp = shareAtVideoTimestamp();
|
||||||
|
show->show(Stories::PrepareShareAtTimeBox(show, _message, timestamp));
|
||||||
|
}
|
||||||
|
|
||||||
void OverlayWidget::downloadMedia() {
|
void OverlayWidget::downloadMedia() {
|
||||||
if (!_photo && !_document) {
|
if (!_photo && !_document) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -291,6 +291,10 @@ private:
|
||||||
void handleTouchTimer();
|
void handleTouchTimer();
|
||||||
void handleDocumentClick();
|
void handleDocumentClick();
|
||||||
|
|
||||||
|
[[nodiscard]] bool canShareAtTime() const;
|
||||||
|
[[nodiscard]] TimeId shareAtVideoTimestamp() const;
|
||||||
|
void shareAtTime();
|
||||||
|
|
||||||
void showSaveMsgToast(const QString &path, auto phrase);
|
void showSaveMsgToast(const QString &path, auto phrase);
|
||||||
void showSaveMsgToastWith(
|
void showSaveMsgToastWith(
|
||||||
const QString &path,
|
const QString &path,
|
||||||
|
|
|
@ -200,6 +200,7 @@ mediaMenuIconDownload: icon {{ "menu/download", mediaviewMenuFg }};
|
||||||
mediaMenuIconDownloadLocked: icon {{ "menu/download_locked", mediaviewMenuFg }};
|
mediaMenuIconDownloadLocked: icon {{ "menu/download_locked", mediaviewMenuFg }};
|
||||||
mediaMenuIconCopy: icon {{ "menu/copy", mediaviewMenuFg }};
|
mediaMenuIconCopy: icon {{ "menu/copy", mediaviewMenuFg }};
|
||||||
mediaMenuIconForward: icon {{ "menu/forward", mediaviewMenuFg }};
|
mediaMenuIconForward: icon {{ "menu/forward", mediaviewMenuFg }};
|
||||||
|
mediaMenuIconShare: icon {{ "menu/share2", mediaviewMenuFg }};
|
||||||
mediaMenuIconDelete: icon {{ "menu/delete", mediaviewMenuFg }};
|
mediaMenuIconDelete: icon {{ "menu/delete", mediaviewMenuFg }};
|
||||||
mediaMenuIconShowAll: icon {{ "menu/all_media", mediaviewMenuFg }};
|
mediaMenuIconShowAll: icon {{ "menu/all_media", mediaviewMenuFg }};
|
||||||
mediaMenuIconProfile: icon {{ "menu/profile", mediaviewMenuFg }};
|
mediaMenuIconProfile: icon {{ "menu/profile", mediaviewMenuFg }};
|
||||||
|
|
Loading…
Add table
Reference in a new issue