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:
ZavaruKitsu 2023-09-27 20:38:30 +03:00
commit ad29ab0f51
36 changed files with 233 additions and 198 deletions

View file

@ -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>

View file

@ -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"

View file

@ -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"

View file

@ -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());

View file

@ -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();

View file

@ -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);
}

View file

@ -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;

View file

@ -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;

View file

@ -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(

View file

@ -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);

View file

@ -49,6 +49,7 @@ struct Element {
struct Content {
std::vector<Element> elements;
int total = 0;
friend inline bool operator==(
const Content &a,

View file

@ -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) {

View file

@ -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) {

View file

@ -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(

View file

@ -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) {

View file

@ -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;

View file

@ -279,7 +279,7 @@ namespace {
bool DebugModeEnabled = false;
void MoveOldDataFiles(const QString &wasDir) {
[[maybe_unused]] void MoveOldDataFiles(const QString &wasDir) {
if (wasDir.isEmpty()) {
return;
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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 {

View file

@ -1014,3 +1014,4 @@ storiesLikeCountStyle: TextStyle(defaultTextStyle) {
linkFont: font(32px semibold);
linkFontOver: font(32px semibold underline);
}
storiesChangelogFooterWidthMin: 240px;

View file

@ -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(

View file

@ -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

View 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) {
}

View file

@ -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;
}

View file

@ -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);
});

View file

@ -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);

View file

@ -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)) {

View file

@ -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

View file

@ -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
""")

View file

@ -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

View file

@ -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

@ -1 +1 @@
Subproject commit 0ae4e78a12d7fdea687ca52647465b9cf9ef95ee
Subproject commit 218a34d9b5e3267b86a938b48bd74c045455bd3c