mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Merge remote-tracking branch 'upstream-main/dev' into dev
# Conflicts: # Telegram/Resources/winrc/Telegram.rc # Telegram/Resources/winrc/Updater.rc # Telegram/SourceFiles/core/version.h # Telegram/lib_ui # snap/snapcraft.yaml
This commit is contained in:
commit
ad29ab0f51
36 changed files with 233 additions and 198 deletions
|
@ -10,7 +10,7 @@
|
|||
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
|
||||
ProcessorArchitecture="ARCHITECTURE"
|
||||
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
|
||||
Version="4.10.0.0" />
|
||||
Version="4.10.1.0" />
|
||||
<Properties>
|
||||
<DisplayName>Telegram Desktop</DisplayName>
|
||||
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>
|
||||
|
|
|
@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,10,0,0
|
||||
PRODUCTVERSION 4,10,0,0
|
||||
FILEVERSION 4,10,1,0
|
||||
PRODUCTVERSION 4,10,1,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -62,10 +62,10 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "Radolyn Labs"
|
||||
VALUE "FileDescription", "AyuGram Desktop"
|
||||
VALUE "FileVersion", "4.10.0.0"
|
||||
VALUE "FileVersion", "4.10.1.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2023"
|
||||
VALUE "ProductName", "AyuGram Desktop"
|
||||
VALUE "ProductVersion", "4.10.0.0"
|
||||
VALUE "ProductVersion", "4.10.1.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,10,0,0
|
||||
PRODUCTVERSION 4,10,0,0
|
||||
FILEVERSION 4,10,1,0
|
||||
PRODUCTVERSION 4,10,1,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -53,10 +53,10 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "Radolyn Labs"
|
||||
VALUE "FileDescription", "AyuGram Desktop Updater"
|
||||
VALUE "FileVersion", "4.10.0.0"
|
||||
VALUE "FileVersion", "4.10.1.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2023"
|
||||
VALUE "ProductName", "AyuGram Desktop"
|
||||
VALUE "ProductVersion", "4.10.0.0"
|
||||
VALUE "ProductVersion", "4.10.1.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -780,10 +780,9 @@ QString ApiWrap::exportDirectMessageLink(
|
|||
|
||||
QString ApiWrap::exportDirectStoryLink(not_null<Data::Story*> story) {
|
||||
const auto storyId = story->fullId();
|
||||
const auto user = story->peer()->asUser();
|
||||
Assert(user != nullptr);
|
||||
const auto peer = story->peer();
|
||||
const auto fallback = [&] {
|
||||
const auto base = user->username();
|
||||
const auto base = peer->userName();
|
||||
const auto story = QString::number(storyId.story);
|
||||
const auto query = base + "/s/" + story;
|
||||
return session().createInternalLinkFull(query);
|
||||
|
@ -793,7 +792,7 @@ QString ApiWrap::exportDirectStoryLink(not_null<Data::Story*> story) {
|
|||
? i->second
|
||||
: fallback();
|
||||
request(MTPstories_ExportStoryLink(
|
||||
story->peer()->input,
|
||||
peer->input,
|
||||
MTP_int(story->id())
|
||||
)).done([=](const MTPExportedStoryLink &result) {
|
||||
const auto link = qs(result.data().vlink());
|
||||
|
|
|
@ -855,7 +855,9 @@ bool ResolveBoost(
|
|||
match->captured(1),
|
||||
qthelp::UrlParamNameTransform::ToLower);
|
||||
const auto domainParam = params.value(u"domain"_q);
|
||||
const auto channelParam = params.value(u"channel"_q);
|
||||
const auto channelParam = params.contains(u"c"_q)
|
||||
? params.value(u"c"_q)
|
||||
: params.value(u"channel"_q);
|
||||
|
||||
const auto myContext = context.value<ClickHandlerContext>();
|
||||
using Navigation = Window::SessionNavigation;
|
||||
|
@ -1086,6 +1088,12 @@ QString TryConvertUrlToLocal(QString url) {
|
|||
if (params.indexOf("boost", 0, Qt::CaseInsensitive) >= 0
|
||||
&& params.toLower().split('&').contains(u"boost"_q)) {
|
||||
return u"tg://boost?domain="_q + domain;
|
||||
} else if (domain == u"boost"_q) {
|
||||
if (const auto domainMatch = regex_match(u"^/([a-zA-Z0-9\\.\\_]+)(/?\\?|/?$)"_q, usernameMatch->captured(2))) {
|
||||
return u"tg://boost?domain="_q + domainMatch->captured(1);
|
||||
} else if (params.indexOf("c=", 0, Qt::CaseInsensitive) >= 0) {
|
||||
return u"tg://boost?"_q + params;
|
||||
}
|
||||
}
|
||||
const auto base = u"tg://resolve?domain="_q + url_encode(usernameMatch->captured(1));
|
||||
auto added = QString();
|
||||
|
|
|
@ -28,7 +28,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "base/qthelp_regex.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "ui/effects/animations.h"
|
||||
#include "ui/platform/ui_platform_utility.h"
|
||||
|
||||
#include <QtCore/QLockFile>
|
||||
#include <QtGui/QSessionManager>
|
||||
|
@ -593,18 +592,9 @@ void Sandbox::registerEnterFromEventLoop() {
|
|||
}
|
||||
|
||||
bool Sandbox::notifyOrInvoke(QObject *receiver, QEvent *e) {
|
||||
const auto type = e->type();
|
||||
if (type == base::InvokeQueuedEvent::Type()) {
|
||||
if (e->type() == base::InvokeQueuedEvent::Type()) {
|
||||
static_cast<base::InvokeQueuedEvent*>(e)->invoke();
|
||||
return true;
|
||||
} else if (receiver == this) {
|
||||
if (type == QEvent::ApplicationDeactivate) {
|
||||
if (Ui::Platform::SkipApplicationDeactivateEvent()) {
|
||||
return true;
|
||||
}
|
||||
} else if (type == QEvent::ApplicationActivate) {
|
||||
Ui::Platform::GotApplicationActivateEvent();
|
||||
}
|
||||
}
|
||||
return QApplication::notify(receiver, e);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D666}"_cs;
|
|||
constexpr auto AppNameOld = "AyuGram for Windows"_cs;
|
||||
constexpr auto AppName = "AyuGram Desktop"_cs;
|
||||
constexpr auto AppFile = "AyuGram"_cs;
|
||||
constexpr auto AppVersion = 4010000;
|
||||
constexpr auto AppVersionStr = "4.10";
|
||||
constexpr auto AppVersion = 4010001;
|
||||
constexpr auto AppVersionStr = "4.10.1";
|
||||
constexpr auto AppBetaVersion = false;
|
||||
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
||||
|
|
|
@ -1217,8 +1217,11 @@ void Stories::toggleHidden(
|
|||
bool hidden,
|
||||
std::shared_ptr<Ui::Show> show) {
|
||||
const auto peer = _owner->peer(peerId);
|
||||
const auto justRemove = peer->isServiceUser() && hidden;
|
||||
if (peer->hasStoriesHidden() != hidden) {
|
||||
peer->setStoriesHidden(hidden);
|
||||
if (!justRemove) {
|
||||
peer->setStoriesHidden(hidden);
|
||||
}
|
||||
session().api().request(MTPstories_TogglePeerStoriesHidden(
|
||||
peer->input,
|
||||
MTP_bool(hidden)
|
||||
|
@ -1239,6 +1242,11 @@ void Stories::toggleHidden(
|
|||
}
|
||||
});
|
||||
|
||||
if (justRemove) {
|
||||
apply(peer, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto i = _all.find(peerId);
|
||||
if (i == end(_all)) {
|
||||
return;
|
||||
|
|
|
@ -370,8 +370,7 @@ bool Story::hasDirectLink() const {
|
|||
if (!_privacyPublic || (!_pinned && expired())) {
|
||||
return false;
|
||||
}
|
||||
const auto user = _peer->asUser();
|
||||
return user && !user->username().isEmpty();
|
||||
return !_peer->userName().isEmpty();
|
||||
}
|
||||
|
||||
std::optional<QString> Story::errorTextForForward(
|
||||
|
|
|
@ -330,8 +330,8 @@ State::State(not_null<Data::Stories*> data, Data::StorySourcesList list)
|
|||
}
|
||||
|
||||
Content State::next() {
|
||||
auto result = Content();
|
||||
const auto &sources = _data->sources(_list);
|
||||
auto result = Content{ .total = int(sources.size()) };
|
||||
result.elements.reserve(sources.size());
|
||||
for (const auto &info : sources) {
|
||||
const auto source = _data->source(info.id);
|
||||
|
@ -390,8 +390,10 @@ rpl::producer<Content> LastForPeer(not_null<PeerData*> peer) {
|
|||
) | rpl::map([=] {
|
||||
auto ids = std::vector<StoryId>();
|
||||
auto readTill = StoryId();
|
||||
auto total = 0;
|
||||
if (const auto source = stories->source(peerId)) {
|
||||
readTill = source->readTill;
|
||||
total = int(source->ids.size());
|
||||
ids = ranges::views::all(source->ids)
|
||||
| ranges::views::reverse
|
||||
| ranges::views::take(kShownLastCount)
|
||||
|
@ -420,7 +422,7 @@ rpl::producer<Content> LastForPeer(not_null<PeerData*> peer) {
|
|||
}
|
||||
auto done = true;
|
||||
auto resolving = false;
|
||||
auto result = Content{};
|
||||
auto result = Content{ .total = total };
|
||||
for (const auto id : ids) {
|
||||
const auto storyId = FullStoryId{ peerId, id };
|
||||
const auto maybe = stories->lookup(storyId);
|
||||
|
|
|
@ -49,6 +49,7 @@ struct Element {
|
|||
|
||||
struct Content {
|
||||
std::vector<Element> elements;
|
||||
int total = 0;
|
||||
|
||||
friend inline bool operator==(
|
||||
const Content &a,
|
||||
|
|
|
@ -254,7 +254,9 @@ FrameGenerator::Frame FrameGenerator::Impl::renderNext(
|
|||
QImage storage,
|
||||
QSize size,
|
||||
Qt::AspectRatioMode mode) {
|
||||
if (!_current.frame) {
|
||||
if (!_codec) {
|
||||
return {};
|
||||
} else if (!_current.frame) {
|
||||
readNextFrame();
|
||||
}
|
||||
std::swap(_current, _next);
|
||||
|
@ -266,6 +268,9 @@ FrameGenerator::Frame FrameGenerator::Impl::renderNext(
|
|||
}
|
||||
|
||||
void FrameGenerator::Impl::jumpToStart() {
|
||||
if (!_codec) {
|
||||
return;
|
||||
}
|
||||
auto result = 0;
|
||||
if ((result = avformat_seek_file(_format.get(), _streamId, std::numeric_limits<int64_t>::min(), 0, std::numeric_limits<int64_t>::max(), 0)) < 0) {
|
||||
if ((result = av_seek_frame(_format.get(), _streamId, 0, AVSEEK_FLAG_BYTE)) < 0) {
|
||||
|
|
|
@ -1738,16 +1738,16 @@ std::unique_ptr<QMimeData> HistoryInner::prepareDrag() {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
const auto mouseActionView = viewByItem(_mouseActionItem);
|
||||
const auto pressedView = viewByItem(_mouseActionItem);
|
||||
bool uponSelected = false;
|
||||
if (mouseActionView) {
|
||||
if (pressedView) {
|
||||
if (!_selected.empty() && _selected.cbegin()->second == FullSelection) {
|
||||
uponSelected = _dragStateItem
|
||||
&& (_selected.find(_dragStateItem) != _selected.cend());
|
||||
uponSelected = _mouseActionItem
|
||||
&& (_selected.find(_mouseActionItem) != _selected.cend());
|
||||
} else {
|
||||
StateRequest request;
|
||||
request.flags |= Ui::Text::StateRequest::Flag::LookupSymbol;
|
||||
auto dragState = mouseActionView->textState(_dragStartPosition, request);
|
||||
auto dragState = pressedView->textState(_dragStartPosition, request);
|
||||
uponSelected = (dragState.cursor == CursorState::Text);
|
||||
if (uponSelected) {
|
||||
if (_selected.empty()
|
||||
|
@ -1788,19 +1788,15 @@ std::unique_ptr<QMimeData> HistoryInner::prepareDrag() {
|
|||
}
|
||||
}
|
||||
return mimeData;
|
||||
} else if (_dragStateItem) {
|
||||
const auto view = viewByItem(_dragStateItem);
|
||||
if (!view) {
|
||||
return nullptr;
|
||||
}
|
||||
} else if (pressedView) {
|
||||
auto forwardIds = MessageIdsList();
|
||||
if (_mouseCursorState == CursorState::Date) {
|
||||
forwardIds = session().data().itemOrItsGroup(_dragStateItem);
|
||||
} else if (view->isHiddenByGroup() && pressedHandler) {
|
||||
forwardIds = MessageIdsList(1, _dragStateItem->fullId());
|
||||
} else if (const auto media = view->media()) {
|
||||
forwardIds = session().data().itemOrItsGroup(_mouseActionItem);
|
||||
} else if (pressedView->isHiddenByGroup() && pressedHandler) {
|
||||
forwardIds = MessageIdsList(1, _mouseActionItem->fullId());
|
||||
} else if (const auto media = pressedView->media()) {
|
||||
if (media->dragItemByHandler(pressedHandler)) {
|
||||
forwardIds = MessageIdsList(1, _dragStateItem->fullId());
|
||||
forwardIds = MessageIdsList(1, _mouseActionItem->fullId());
|
||||
}
|
||||
}
|
||||
if (forwardIds.empty()) {
|
||||
|
@ -1809,7 +1805,7 @@ std::unique_ptr<QMimeData> HistoryInner::prepareDrag() {
|
|||
session().data().setMimeForwardIds(std::move(forwardIds));
|
||||
auto result = std::make_unique<QMimeData>();
|
||||
result->setData(u"application/x-td-forward"_q, "1");
|
||||
if (const auto media = view->media()) {
|
||||
if (const auto media = pressedView->media()) {
|
||||
if (const auto document = media->getDocument()) {
|
||||
const auto filepath = document->filepath(true);
|
||||
if (!filepath.isEmpty()) {
|
||||
|
@ -2384,7 +2380,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
_widget->confirmDeleteSelected();
|
||||
}, &st::menuIconDelete);
|
||||
}
|
||||
if (selectedState.count > 0) {
|
||||
if (selectedState.count > 0 && !hasCopyRestrictionForSelected()) {
|
||||
Menu::AddDownloadFilesAction(_menu, controller, _selected, this);
|
||||
}
|
||||
_menu->addAction(tr::lng_context_clear_selection(tr::now), [=] {
|
||||
|
@ -2582,7 +2578,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
_widget->confirmDeleteSelected();
|
||||
}, &st::menuIconDelete);
|
||||
}
|
||||
if (selectedState.count > 0) {
|
||||
if (selectedState.count > 0 && !hasCopyRestrictionForSelected()) {
|
||||
Menu::AddDownloadFilesAction(_menu, controller, _selected, this);
|
||||
}
|
||||
_menu->addAction(tr::lng_context_clear_selection(tr::now), [=] {
|
||||
|
@ -2921,7 +2917,7 @@ void HistoryInner::keyPressEvent(QKeyEvent *e) {
|
|||
&& !showCopyRestrictionForSelected()) {
|
||||
TextUtilities::SetClipboardText(getSelectedText(), QClipboard::FindBuffer);
|
||||
#endif // Q_OS_MAC
|
||||
} else if (e == QKeySequence::Delete) {
|
||||
} else if (e == QKeySequence::Delete || e->key() == Qt::Key_Backspace) {
|
||||
auto selectedState = getSelectionState();
|
||||
if (selectedState.count > 0
|
||||
&& selectedState.canDeleteCount == selectedState.count) {
|
||||
|
|
|
@ -839,7 +839,9 @@ void AddDownloadFilesAction(
|
|||
not_null<Ui::PopupMenu*> menu,
|
||||
const ContextMenuRequest &request,
|
||||
not_null<ListWidget*> list) {
|
||||
if (!request.overSelection || request.selectedItems.empty()) {
|
||||
if (!request.overSelection
|
||||
|| request.selectedItems.empty()
|
||||
|| list->hasCopyRestrictionForSelected()) {
|
||||
return;
|
||||
}
|
||||
Menu::AddDownloadFilesAction(
|
||||
|
|
|
@ -2451,7 +2451,7 @@ void ListWidget::keyPressEvent(QKeyEvent *e) {
|
|||
&& !hasCopyRestrictionForSelected()) {
|
||||
TextUtilities::SetClipboardText(getSelectedText(), QClipboard::FindBuffer);
|
||||
#endif // Q_OS_MAC
|
||||
} else if (e == QKeySequence::Delete) {
|
||||
} else if (e == QKeySequence::Delete || e->key() == Qt::Key_Backspace) {
|
||||
_delegate->listDeleteRequest();
|
||||
} else if (!(e->modifiers() & ~Qt::ShiftModifier)
|
||||
&& e->key() != Qt::Key_Shift) {
|
||||
|
|
|
@ -525,7 +525,7 @@ void TopBar::setStories(rpl::producer<Dialogs::Stories::Content> content) {
|
|||
rpl::duplicate(
|
||||
last
|
||||
) | rpl::start_with_next([=](const Content &content) {
|
||||
const auto count = int(content.elements.size());
|
||||
const auto count = content.total;
|
||||
if (_storiesCount != count) {
|
||||
const auto was = (_storiesCount > 0);
|
||||
_storiesCount = count;
|
||||
|
|
|
@ -279,7 +279,7 @@ namespace {
|
|||
|
||||
bool DebugModeEnabled = false;
|
||||
|
||||
void MoveOldDataFiles(const QString &wasDir) {
|
||||
[[maybe_unused]] void MoveOldDataFiles(const QString &wasDir) {
|
||||
if (wasDir.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -866,8 +866,7 @@ void Controller::show(
|
|||
.list = story->recentViewers(),
|
||||
.reactions = story->reactions(),
|
||||
.total = story->views(),
|
||||
.self = peer->isSelf(),
|
||||
.channel = peer->isChannel(),
|
||||
.type = RecentViewsTypeFor(peer),
|
||||
}, _reactions->likedValue());
|
||||
if (const auto nowLikeButton = _recentViews->likeButton()) {
|
||||
if (wasLikeButton != nowLikeButton) {
|
||||
|
@ -875,7 +874,7 @@ void Controller::show(
|
|||
}
|
||||
}
|
||||
|
||||
if (peer->isSelf() || peer->isChannel()) {
|
||||
if (peer->isSelf() || peer->isChannel() || peer->isServiceUser()) {
|
||||
_reactions->setReactionIconWidget(_recentViews->likeIconWidget());
|
||||
} else if (const auto like = _replyArea->likeAnimationTarget()) {
|
||||
_reactions->setReactionIconWidget(like);
|
||||
|
@ -963,8 +962,7 @@ void Controller::subscribeToSession() {
|
|||
.list = update.story->recentViewers(),
|
||||
.reactions = update.story->reactions(),
|
||||
.total = update.story->views(),
|
||||
.self = update.story->peer()->isSelf(),
|
||||
.channel = update.story->peer()->isChannel(),
|
||||
.type = RecentViewsTypeFor(update.story->peer()),
|
||||
});
|
||||
updateAreas(update.story);
|
||||
}
|
||||
|
|
|
@ -123,6 +123,16 @@ constexpr auto kLoadViewsPages = 2;
|
|||
|
||||
} // namespace
|
||||
|
||||
RecentViewsType RecentViewsTypeFor(not_null<PeerData*> peer) {
|
||||
return peer->isSelf()
|
||||
? RecentViewsType::Self
|
||||
: peer->isChannel()
|
||||
? RecentViewsType::Channel
|
||||
: peer->isServiceUser()
|
||||
? RecentViewsType::Changelog
|
||||
: RecentViewsType::Other;
|
||||
}
|
||||
|
||||
RecentViews::RecentViews(not_null<Controller*> controller)
|
||||
: _controller(controller) {
|
||||
}
|
||||
|
@ -155,7 +165,7 @@ void RecentViews::show(
|
|||
|| (_data.reactions != data.reactions);
|
||||
const auto usersChanged = !_userpics || (_data.list != data.list);
|
||||
_data = data;
|
||||
if (!_data.self) {
|
||||
if (_data.type != RecentViewsType::Self) {
|
||||
_text = {};
|
||||
_clickHandlerLifetime.destroy();
|
||||
_userpicsLifetime.destroy();
|
||||
|
@ -177,13 +187,17 @@ void RecentViews::show(
|
|||
refreshClickHandler();
|
||||
}
|
||||
|
||||
if (!_data.channel) {
|
||||
if (_data.type != RecentViewsType::Channel
|
||||
&& _data.type != RecentViewsType::Changelog) {
|
||||
_likeIcon = nullptr;
|
||||
_likeWrap = nullptr;
|
||||
_viewsWrap = nullptr;
|
||||
} else {
|
||||
_viewsCounter = Lang::FormatCountDecimal(std::max(_data.total, 1));
|
||||
_likesCounter = _data.reactions
|
||||
_viewsCounter = (_data.type == RecentViewsType::Channel)
|
||||
? Lang::FormatCountDecimal(std::max(_data.total, 1))
|
||||
: tr::lng_stories_cant_reply(tr::now);
|
||||
_likesCounter = ((_data.type == RecentViewsType::Channel)
|
||||
&& _data.reactions)
|
||||
? Lang::FormatCountDecimal(_data.reactions)
|
||||
: QString();
|
||||
if (!_likeWrap || !_likeIcon || !_viewsWrap) {
|
||||
|
@ -300,14 +314,19 @@ void RecentViews::setupViewsReactions() {
|
|||
st::storiesViewsText);
|
||||
views->show();
|
||||
views->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
views->move(st::storiesViewsTextPosition);
|
||||
|
||||
views->widthValue(
|
||||
) | rpl::start_with_next([=](int width) {
|
||||
_viewsWrap->resize(views->x() + width, _likeIcon->height());
|
||||
const auto left = (_data.type == RecentViewsType::Changelog)
|
||||
? st::mediaviewCaptionPadding.left()
|
||||
: st::storiesViewsTextPosition.x();
|
||||
views->move(left, st::storiesViewsTextPosition.y());
|
||||
_viewsWrap->resize(left + width, _likeIcon->height());
|
||||
updateViewsReactionsGeometry();
|
||||
}, _viewsWrap->lifetime());
|
||||
_viewsWrap->paintRequest() | rpl::start_with_next([=] {
|
||||
_viewsWrap->paintRequest() | rpl::filter([=] {
|
||||
return (_data.type != RecentViewsType::Changelog);
|
||||
}) | rpl::start_with_next([=] {
|
||||
auto p = QPainter(_viewsWrap.get());
|
||||
const auto &icon = st::storiesViewsIcon;
|
||||
const auto top = (_viewsWrap->height() - icon.height()) / 2;
|
||||
|
@ -342,9 +361,14 @@ void RecentViews::setupViewsReactions() {
|
|||
}
|
||||
|
||||
void RecentViews::updateViewsReactionsGeometry() {
|
||||
_viewsWrap->move(_outer.topLeft() + st::storiesViewsPosition);
|
||||
_likeWrap->move(_outer.topLeft()
|
||||
+ QPoint(_outer.width() - _likeWrap->width(), 0)
|
||||
const auto outerWidth = (_data.type == RecentViewsType::Changelog)
|
||||
? std::max(_outer.width(), st::storiesChangelogFooterWidthMin)
|
||||
: _outer.width();
|
||||
const auto outerOrigin = _outer.topLeft()
|
||||
+ QPoint((_outer.width() - outerWidth) / 2, 0);
|
||||
_viewsWrap->move(outerOrigin + st::storiesViewsPosition);
|
||||
_likeWrap->move(outerOrigin
|
||||
+ QPoint(outerWidth - _likeWrap->width(), 0)
|
||||
+ st::storiesLikesPosition);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,12 +33,18 @@ namespace Media::Stories {
|
|||
|
||||
class Controller;
|
||||
|
||||
enum class RecentViewsType {
|
||||
Other,
|
||||
Self,
|
||||
Channel,
|
||||
Changelog,
|
||||
};
|
||||
|
||||
struct RecentViewsData {
|
||||
std::vector<not_null<PeerData*>> list;
|
||||
int reactions = 0;
|
||||
int total = 0;
|
||||
bool self = false;
|
||||
bool channel = false;
|
||||
RecentViewsType type = RecentViewsType::Other;
|
||||
|
||||
friend inline auto operator<=>(
|
||||
const RecentViewsData &,
|
||||
|
@ -48,6 +54,8 @@ struct RecentViewsData {
|
|||
const RecentViewsData &) = default;
|
||||
};
|
||||
|
||||
[[nodiscard]] RecentViewsType RecentViewsTypeFor(not_null<PeerData*> peer);
|
||||
|
||||
class RecentViews final {
|
||||
public:
|
||||
explicit RecentViews(not_null<Controller*> controller);
|
||||
|
|
|
@ -675,8 +675,9 @@ void ReplyArea::show(
|
|||
}),
|
||||
});
|
||||
_controls->clear();
|
||||
const auto hidden = peer && (!peer->isUser() || peer->isSelf());
|
||||
const auto cant = !peer || peer->isServiceUser();
|
||||
const auto hidden = peer
|
||||
&& (!peer->isUser() || peer->isSelf() || peer->isServiceUser());
|
||||
const auto cant = !peer;
|
||||
if (!hidden && !cant) {
|
||||
_controls->show();
|
||||
} else {
|
||||
|
|
|
@ -1014,3 +1014,4 @@ storiesLikeCountStyle: TextStyle(defaultTextStyle) {
|
|||
linkFont: font(32px semibold);
|
||||
linkFontOver: font(32px semibold underline);
|
||||
}
|
||||
storiesChangelogFooterWidthMin: 240px;
|
||||
|
|
|
@ -255,6 +255,18 @@ void OverlayWidget::RendererGL::deinit(
|
|||
_fillProgram = std::nullopt;
|
||||
_controlsProgram = std::nullopt;
|
||||
_contentBuffer = std::nullopt;
|
||||
_controlsFadeImage.destroy(f);
|
||||
_radialImage.destroy(f);
|
||||
_documentBubbleImage.destroy(f);
|
||||
_themePreviewImage.destroy(f);
|
||||
_saveMsgImage.destroy(f);
|
||||
_footerImage.destroy(f);
|
||||
_captionImage.destroy(f);
|
||||
_groupThumbsImage.destroy(f);
|
||||
_controlsImage.destroy(f);
|
||||
for (auto &part : _storiesSiblingParts) {
|
||||
part.destroy(f);
|
||||
}
|
||||
}
|
||||
|
||||
void OverlayWidget::RendererGL::paint(
|
||||
|
|
|
@ -7,75 +7,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "platform/linux/file_utilities_linux.h"
|
||||
|
||||
#include "base/platform/linux/base_linux_app_launch_context.h"
|
||||
#include "platform/linux/linux_xdp_open_with_dialog.h"
|
||||
|
||||
#include <QtGui/QDesktopServices>
|
||||
|
||||
#include <gio/gio.hpp>
|
||||
|
||||
using namespace gi::repository;
|
||||
|
||||
namespace Platform {
|
||||
namespace File {
|
||||
|
||||
void UnsafeOpenUrl(const QString &url) {
|
||||
{
|
||||
const auto result = Gio::AppInfo::launch_default_for_uri(
|
||||
url.toStdString(),
|
||||
base::Platform::AppLaunchContext());
|
||||
|
||||
if (!result) {
|
||||
LOG(("App Error: %1").arg(result.error().what()));
|
||||
} else if (*result) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QDesktopServices::openUrl(url);
|
||||
}
|
||||
|
||||
void UnsafeOpenEmailLink(const QString &email) {
|
||||
UnsafeOpenUrl(u"mailto:"_q + email);
|
||||
}
|
||||
|
||||
bool UnsafeShowOpenWith(const QString &filepath) {
|
||||
if (internal::ShowXDPOpenWithDialog(filepath)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void UnsafeLaunch(const QString &filepath) {
|
||||
if ([&] {
|
||||
const auto filename = GLib::filename_to_uri(filepath.toStdString());
|
||||
if (!filename) {
|
||||
LOG(("App Error: %1").arg(filename.error().what()));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto result = Gio::AppInfo::launch_default_for_uri(
|
||||
*filename,
|
||||
base::Platform::AppLaunchContext());
|
||||
|
||||
if (!result) {
|
||||
LOG(("App Error: %1").arg(result.error().what()));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return *result;
|
||||
}()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (UnsafeShowOpenWith(filepath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(filepath));
|
||||
return internal::ShowXDPOpenWithDialog(filepath);
|
||||
}
|
||||
|
||||
} // namespace File
|
||||
|
|
|
@ -16,10 +16,22 @@ inline QString UrlToLocal(const QUrl &url) {
|
|||
return ::File::internal::UrlToLocalDefault(url);
|
||||
}
|
||||
|
||||
inline void UnsafeOpenUrl(const QString &url) {
|
||||
return ::File::internal::UnsafeOpenUrlDefault(url);
|
||||
}
|
||||
|
||||
inline void UnsafeOpenEmailLink(const QString &email) {
|
||||
return ::File::internal::UnsafeOpenEmailLinkDefault(email);
|
||||
}
|
||||
|
||||
inline bool UnsafeShowOpenWithDropdown(const QString &filepath) {
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void UnsafeLaunch(const QString &filepath) {
|
||||
return ::File::internal::UnsafeLaunchDefault(filepath);
|
||||
}
|
||||
|
||||
inline void PostprocessDownloaded(const QString &filepath) {
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "platform/linux/linux_wayland_integration.h"
|
||||
|
||||
#include "base/platform/linux/base_linux_wayland_utilities.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "base/qt_signal_producer.h"
|
||||
#include "base/flat_map.h"
|
||||
|
||||
|
@ -20,7 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include <qwayland-wayland.h>
|
||||
#include <qwayland-plasma-shell.h>
|
||||
|
||||
using namespace QNativeInterface;
|
||||
using QWlApp = QNativeInterface::QWaylandApplication;
|
||||
using namespace QNativeInterface::Private;
|
||||
using namespace base::Platform::Wayland;
|
||||
|
||||
|
@ -38,9 +37,17 @@ public:
|
|||
|
||||
} // namespace
|
||||
|
||||
struct WaylandIntegration::Private : public AutoDestroyer<QtWayland::wl_registry> {
|
||||
struct WaylandIntegration::Private
|
||||
: public AutoDestroyer<QtWayland::wl_registry> {
|
||||
Private(not_null<QWlApp*> native)
|
||||
: AutoDestroyer(wl_display_get_registry(native->display()))
|
||||
, display(native->display()) {
|
||||
wl_display_roundtrip(display);
|
||||
}
|
||||
|
||||
QtWayland::org_kde_plasma_surface plasmaSurface(QWindow *window);
|
||||
|
||||
const not_null<wl_display*> display;
|
||||
std::optional<PlasmaShell> plasmaShell;
|
||||
|
||||
protected:
|
||||
|
@ -102,36 +109,27 @@ QtWayland::org_kde_plasma_surface WaylandIntegration::Private::plasmaSurface(
|
|||
}
|
||||
|
||||
WaylandIntegration::WaylandIntegration()
|
||||
: _private(std::make_unique<Private>()) {
|
||||
const auto native = qApp->nativeInterface<QWaylandApplication>();
|
||||
if (!native) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto display = native->display();
|
||||
if (!display) {
|
||||
return;
|
||||
}
|
||||
|
||||
_private->init(wl_display_get_registry(display));
|
||||
wl_display_roundtrip(display);
|
||||
: _private(std::make_unique<Private>(qApp->nativeInterface<QWlApp>())) {
|
||||
}
|
||||
|
||||
WaylandIntegration::~WaylandIntegration() = default;
|
||||
|
||||
WaylandIntegration *WaylandIntegration::Instance() {
|
||||
if (!IsWayland()) return nullptr;
|
||||
static std::optional<WaylandIntegration> instance(std::in_place);
|
||||
[[maybe_unused]] static const auto Inited = [] {
|
||||
const auto native = qApp->nativeInterface<QWlApp>();
|
||||
if (!native) return nullptr;
|
||||
static std::optional<WaylandIntegration> instance;
|
||||
if (instance && native->display() != instance->_private->display) {
|
||||
instance.reset();
|
||||
}
|
||||
if (!instance) {
|
||||
instance.emplace();
|
||||
base::qt_signal_producer(
|
||||
QGuiApplication::platformNativeInterface(),
|
||||
&QObject::destroyed
|
||||
) | rpl::start_with_next([] {
|
||||
instance = std::nullopt;
|
||||
}, instance->_private->lifetime());
|
||||
return true;
|
||||
}();
|
||||
if (!instance) return nullptr;
|
||||
}
|
||||
return &*instance;
|
||||
}
|
||||
|
||||
|
|
|
@ -274,14 +274,14 @@ void GetInhibited(Fn<void(bool)> callback) {
|
|||
[=](const Glib::RefPtr<Gio::AsyncResult> &result) {
|
||||
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
||||
Noexcept([&] {
|
||||
const auto value = connection->call_finish(
|
||||
result
|
||||
).get_child(
|
||||
0
|
||||
).get_dynamic<Glib::Variant<bool>>(
|
||||
).get();
|
||||
|
||||
callback(value);
|
||||
callback(
|
||||
connection->call_finish(
|
||||
result
|
||||
).get_child(
|
||||
0
|
||||
).get_dynamic<Glib::Variant<bool>>(
|
||||
).get()
|
||||
);
|
||||
}, [&] {
|
||||
callback(false);
|
||||
});
|
||||
|
|
|
@ -399,6 +399,15 @@ protected:
|
|||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private:
|
||||
struct GradientParams {
|
||||
int left = 0;
|
||||
int width = 0;
|
||||
int outer = 0;
|
||||
|
||||
friend inline constexpr bool operator==(
|
||||
GradientParams,
|
||||
GradientParams) = default;
|
||||
};
|
||||
void animateTo(BubbleRowState state);
|
||||
|
||||
const style::PremiumBubble &_st;
|
||||
|
@ -414,6 +423,7 @@ private:
|
|||
QSize _spaceForDeflection;
|
||||
|
||||
QLinearGradient _cachedGradient;
|
||||
std::optional<GradientParams> _cachedGradientParams;
|
||||
|
||||
float64 _deflection;
|
||||
|
||||
|
@ -580,13 +590,19 @@ void BubbleWidget::paintEvent(QPaintEvent *e) {
|
|||
0);
|
||||
const auto bubbleRect = rect() - padding;
|
||||
|
||||
if (_appearanceAnimation.animating()) {
|
||||
auto gradient = ComputeGradient(
|
||||
const auto params = GradientParams{
|
||||
.left = x(),
|
||||
.width = bubbleRect.width(),
|
||||
.outer = parentWidget()->parentWidget()->width(),
|
||||
};
|
||||
if (_cachedGradientParams != params) {
|
||||
_cachedGradient = ComputeGradient(
|
||||
parentWidget(),
|
||||
x(),
|
||||
bubbleRect.width());
|
||||
_cachedGradient = std::move(gradient);
|
||||
|
||||
params.left,
|
||||
params.width);
|
||||
_cachedGradientParams = params;
|
||||
}
|
||||
if (_appearanceAnimation.animating()) {
|
||||
const auto progress = _appearanceAnimation.value(1.);
|
||||
const auto finalScale = (_animatingFromResultRatio > 0.)
|
||||
|| (_state.current().ratio < 0.001);
|
||||
|
|
|
@ -506,7 +506,7 @@ void SessionNavigation::showPeerByLinkResolved(
|
|||
info.messageId,
|
||||
callback);
|
||||
}
|
||||
} else if (peer->isUser() && info.storyId) {
|
||||
} else if (info.storyId) {
|
||||
const auto storyId = FullStoryId{ peer->id, info.storyId };
|
||||
peer->owner().stories().resolve(storyId, crl::guard(this, [=] {
|
||||
if (peer->owner().stories().lookup(storyId)) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{%- set GIT = "https://github.com" -%}
|
||||
{%- set GIT_FREEDESKTOP = GIT ~ "/gitlab-freedesktop-mirrors" -%}
|
||||
{%- set QT = "6.5.2" -%}
|
||||
{%- set QT_TAG = "v" ~ QT -%}
|
||||
{%- set QT = "6.6.0" -%}
|
||||
{%- set QT_TAG = "v" ~ QT ~ "-rc1" -%}
|
||||
{%- set QT_PREFIX = "/usr/local/desktop-app/Qt-" ~ QT -%}
|
||||
{%- set OPENSSL_VER = "1_1_1" -%}
|
||||
{%- set OPENSSL_PREFIX = "/usr/local/desktop-app/openssl-1.1.1" -%}
|
||||
|
@ -54,7 +54,7 @@ FROM builder AS patches
|
|||
RUN git init patches \
|
||||
&& cd patches \
|
||||
&& git remote add origin {{ GIT }}/desktop-app/patches.git \
|
||||
&& git fetch --depth=1 origin 2c464cfbd9fa3c1d88335cf9462c8ef96542f87c \
|
||||
&& git fetch --depth=1 origin 6442ae042bb6d43391747f7413c7a88a6a37c7ef \
|
||||
&& git reset --hard FETCH_HEAD \
|
||||
&& rm -rf .git
|
||||
|
||||
|
|
|
@ -82,19 +82,33 @@ for singlePrefix in pathPrefixes:
|
|||
pathPrefix = pathPrefix + os.path.join(rootDir, singlePrefix) + pathSep
|
||||
|
||||
environment = {
|
||||
'MAKE_THREADS_CNT': '-j8',
|
||||
'MACOSX_DEPLOYMENT_TARGET': '10.13',
|
||||
'UNGUARDED': '-Werror=unguarded-availability-new',
|
||||
'MIN_VER': '-mmacosx-version-min=10.13',
|
||||
'USED_PREFIX': usedPrefix,
|
||||
'ROOT_DIR': rootDir,
|
||||
'LIBS_DIR': libsDir,
|
||||
'THIRDPARTY_DIR': thirdPartyDir,
|
||||
'SPECIAL_TARGET': 'win' if win32 else 'win64' if win64 else 'mac',
|
||||
'X8664': 'x86' if win32 else 'x64',
|
||||
'WIN32X64': 'Win32' if win32 else 'x64',
|
||||
'PATH_PREFIX': pathPrefix,
|
||||
}
|
||||
if (win32):
|
||||
environment.update({
|
||||
'SPECIAL_TARGET': 'win',
|
||||
'X8664': 'x86',
|
||||
'WIN32X64': 'Win32',
|
||||
})
|
||||
elif (win64):
|
||||
environment.update({
|
||||
'SPECIAL_TARGET': 'win64',
|
||||
'X8664': 'x64',
|
||||
'WIN32X64': 'x64',
|
||||
})
|
||||
elif (mac):
|
||||
environment.update({
|
||||
'SPECIAL_TARGET': 'mac',
|
||||
'MAKE_THREADS_CNT': '-j8',
|
||||
'MACOSX_DEPLOYMENT_TARGET': '10.13',
|
||||
'UNGUARDED': '-Werror=unguarded-availability-new',
|
||||
'MIN_VER': '-mmacosx-version-min=10.13',
|
||||
})
|
||||
|
||||
ignoreInCacheForThirdParty = [
|
||||
'USED_PREFIX',
|
||||
'LIBS_DIR',
|
||||
|
@ -404,7 +418,7 @@ if customRunCommand:
|
|||
stage('patches', """
|
||||
git clone https://github.com/desktop-app/patches.git
|
||||
cd patches
|
||||
git checkout b1907e1250
|
||||
git checkout 81a81ffb5a
|
||||
""")
|
||||
|
||||
stage('msys64', """
|
||||
|
@ -461,9 +475,9 @@ win:
|
|||
cd gyp
|
||||
git checkout 9d09418933
|
||||
mac:
|
||||
python3 -m pip install ^
|
||||
--ignore-installed ^
|
||||
--target=$THIRDPARTY_DIR/gyp ^
|
||||
python3 -m pip install \\
|
||||
--ignore-installed \\
|
||||
--target=$THIRDPARTY_DIR/gyp \\
|
||||
git+https://chromium.googlesource.com/external/gyp@master
|
||||
""", 'ThirdParty')
|
||||
|
||||
|
@ -1144,8 +1158,7 @@ depends:patches/breakpad.diff
|
|||
cd src/third_party/lss
|
||||
git checkout e1e7b0ad8e
|
||||
cd ../../build
|
||||
PYTHONPATH=$THIRDPARTY_DIR/gyp
|
||||
python3 gyp_breakpad
|
||||
PYTHONPATH=$THIRDPARTY_DIR/gyp python3 gyp_breakpad
|
||||
cd ../processor
|
||||
xcodebuild -project processor.xcodeproj -target minidump_stackwalk -configuration Release build
|
||||
""")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
AppVersion 4010000
|
||||
AppVersion 4010001
|
||||
AppVersionStrMajor 4.10
|
||||
AppVersionStrSmall 4.10
|
||||
AppVersionStr 4.10.0
|
||||
AppVersionStrSmall 4.10.1
|
||||
AppVersionStr 4.10.1
|
||||
BetaChannel 0
|
||||
AlphaVersion 0
|
||||
AppVersionOriginal 4.10
|
||||
AppVersionOriginal 4.10.1
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 6de11e6ab705f27158f338e3e17c8b0767750721
|
||||
Subproject commit d67a11776ad720a718bae026b78ddd150f13fac5
|
|
@ -1 +1 @@
|
|||
Subproject commit cea8958ca2007192dbd6ce14967f74484d1fcc6f
|
||||
Subproject commit 5c4f890f356f1ccb1401581b2a960b35455a7488
|
|
@ -1,3 +1,7 @@
|
|||
4.10.1 (23.09.23)
|
||||
|
||||
- Rebuild macOS version with Xcode 14.0.1.
|
||||
|
||||
4.10 (22.09.23)
|
||||
|
||||
- Stories for Channels.
|
||||
|
|
2
cmake
2
cmake
|
@ -1 +1 @@
|
|||
Subproject commit 0ae4e78a12d7fdea687ca52647465b9cf9ef95ee
|
||||
Subproject commit 218a34d9b5e3267b86a938b48bd74c045455bd3c
|
Loading…
Add table
Reference in a new issue