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