mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Merge tag 'v5.12.3' into dev
This commit is contained in:
commit
b0a4d15d64
27 changed files with 316 additions and 61 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="5.12.1.0" />
|
Version="5.12.3.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 5,12,1,0
|
FILEVERSION 5,12,3,0
|
||||||
PRODUCTVERSION 5,12,1,0
|
PRODUCTVERSION 5,12,3,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", "5.12.1.0"
|
VALUE "FileVersion", "5.12.3.0"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2014-2025"
|
VALUE "LegalCopyright", "Copyright (C) 2014-2025"
|
||||||
VALUE "ProductName", "AyuGram Desktop"
|
VALUE "ProductName", "AyuGram Desktop"
|
||||||
VALUE "ProductVersion", "5.12.1.0"
|
VALUE "ProductVersion", "5.12.3.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 5,12,1,0
|
FILEVERSION 5,12,3,0
|
||||||
PRODUCTVERSION 5,12,1,0
|
PRODUCTVERSION 5,12,3,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", "5.12.1.0"
|
VALUE "FileVersion", "5.12.3.0"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2014-2025"
|
VALUE "LegalCopyright", "Copyright (C) 2014-2025"
|
||||||
VALUE "ProductName", "AyuGram Desktop"
|
VALUE "ProductName", "AyuGram Desktop"
|
||||||
VALUE "ProductVersion", "5.12.1.0"
|
VALUE "ProductVersion", "5.12.3.0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
@ -363,15 +363,17 @@ object_ptr<Ui::RpWidget> AddReactionsSelector(
|
||||||
const auto customEmojiPaused = [controller = args.controller] {
|
const auto customEmojiPaused = [controller = args.controller] {
|
||||||
return controller->isGifPausedAtLeastFor(PauseReason::Layer);
|
return controller->isGifPausedAtLeastFor(PauseReason::Layer);
|
||||||
};
|
};
|
||||||
auto context = Core::TextContext({
|
auto simpleContext = Core::TextContext({
|
||||||
.session = session,
|
.session = session,
|
||||||
|
.repaint = [=] { raw->update(); },
|
||||||
});
|
});
|
||||||
|
auto context = simpleContext;
|
||||||
context.customEmojiFactory = [=](
|
context.customEmojiFactory = [=](
|
||||||
QStringView data,
|
QStringView data,
|
||||||
const Ui::Text::MarkedContext &context
|
const Ui::Text::MarkedContext &context
|
||||||
) -> std::unique_ptr<Ui::Text::CustomEmoji> {
|
) -> std::unique_ptr<Ui::Text::CustomEmoji> {
|
||||||
const auto id = Data::ParseCustomEmojiData(data);
|
const auto id = Data::ParseCustomEmojiData(data);
|
||||||
auto result = Ui::Text::MakeCustomEmoji(data, context);
|
auto result = Ui::Text::MakeCustomEmoji(data, simpleContext);
|
||||||
if (state->unifiedFactoryOwner->lookupReactionId(id).custom()) {
|
if (state->unifiedFactoryOwner->lookupReactionId(id).custom()) {
|
||||||
return std::make_unique<MaybeDisabledEmoji>(
|
return std::make_unique<MaybeDisabledEmoji>(
|
||||||
std::move(result),
|
std::move(result),
|
||||||
|
|
|
@ -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 = 5012001;
|
constexpr auto AppVersion = 5012003;
|
||||||
constexpr auto AppVersionStr = "5.12.1";
|
constexpr auto AppVersionStr = "5.12.3";
|
||||||
constexpr auto AppBetaVersion = false;
|
constexpr auto AppBetaVersion = false;
|
||||||
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
||||||
|
|
|
@ -322,6 +322,9 @@ QString CountriesInstance::flagEmojiByISO2(const QString &iso) const {
|
||||||
|| iso.back() < 'A'
|
|| iso.back() < 'A'
|
||||||
|| iso.back() > 'Z') {
|
|| iso.back() > 'Z') {
|
||||||
return QString();
|
return QString();
|
||||||
|
} else if (iso == u"FT"_q) {
|
||||||
|
return QString::fromUtf8(
|
||||||
|
"\xF0\x9F\x8F\xB4\xE2\x80\x8D\xE2\x98\xA0\xEF\xB8\x8F");
|
||||||
}
|
}
|
||||||
auto result = QString(4, QChar(0xD83C));
|
auto result = QString(4, QChar(0xD83C));
|
||||||
result[1] = QChar(iso.front().unicode() - 'A' + 0xDDE6);
|
result[1] = QChar(iso.front().unicode() - 'A' + 0xDDE6);
|
||||||
|
|
|
@ -4905,33 +4905,14 @@ void InnerWidget::setupShortcuts() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto nearFolder = [=](bool isNext) {
|
|
||||||
const auto id = _controller->activeChatsFilterCurrent();
|
|
||||||
const auto list = &session().data().chatsFilters().list();
|
|
||||||
const auto index = int(ranges::find(
|
|
||||||
*list,
|
|
||||||
id,
|
|
||||||
&Data::ChatFilter::id
|
|
||||||
) - begin(*list));
|
|
||||||
if (index == list->size() && id != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const auto changed = index + (isNext ? 1 : -1);
|
|
||||||
if (changed >= int(list->size()) || changed < 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
_controller->setActiveChatsFilter((changed >= 0)
|
|
||||||
? (*list)[changed].id()
|
|
||||||
: 0);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
request->check(Command::FolderNext) && request->handle([=] {
|
request->check(Command::FolderNext) && request->handle([=] {
|
||||||
return nearFolder(true);
|
using namespace Window;
|
||||||
|
return CheckAndJumpToNearChatsFilter(_controller, true, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
request->check(Command::FolderPrevious) && request->handle([=] {
|
request->check(Command::FolderPrevious) && request->handle([=] {
|
||||||
return nearFolder(false);
|
using namespace Window;
|
||||||
|
return CheckAndJumpToNearChatsFilter(_controller, false, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
request->check(Command::ReadChat) && request->handle([=] {
|
request->check(Command::ReadChat) && request->handle([=] {
|
||||||
|
|
|
@ -1334,6 +1334,9 @@ void Widget::toggleFiltersMenu(bool enabled) {
|
||||||
if (_layout == Layout::Child) {
|
if (_layout == Layout::Child) {
|
||||||
enabled = false;
|
enabled = false;
|
||||||
}
|
}
|
||||||
|
if (const auto id = controller()->windowId(); id.forum() || id.folder()) {
|
||||||
|
enabled = false;
|
||||||
|
}
|
||||||
if (!enabled == !_chatFilters) {
|
if (!enabled == !_chatFilters) {
|
||||||
return;
|
return;
|
||||||
} else if (enabled) {
|
} else if (enabled) {
|
||||||
|
|
|
@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/layers/generic_box.h"
|
#include "ui/layers/generic_box.h"
|
||||||
#include "ui/text/text_utilities.h"
|
#include "ui/text/text_utilities.h"
|
||||||
#include "ui/boxes/calendar_box.h"
|
#include "ui/boxes/calendar_box.h"
|
||||||
|
#include "ui/boxes/choose_time.h"
|
||||||
#include "platform/platform_specific.h"
|
#include "platform/platform_specific.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
#include "core/file_utilities.h"
|
#include "core/file_utilities.h"
|
||||||
|
@ -388,7 +389,7 @@ void SettingsWidget::addFormatAndLocationLabel(
|
||||||
|
|
||||||
void SettingsWidget::addLimitsLabel(
|
void SettingsWidget::addLimitsLabel(
|
||||||
not_null<Ui::VerticalLayout*> container) {
|
not_null<Ui::VerticalLayout*> container) {
|
||||||
auto fromLink = value() | rpl::map([](const Settings &data) {
|
auto fromDateLink = value() | rpl::map([](const Settings &data) {
|
||||||
return data.singlePeerFrom;
|
return data.singlePeerFrom;
|
||||||
}) | rpl::distinct_until_changed(
|
}) | rpl::distinct_until_changed(
|
||||||
) | rpl::map([](TimeId from) {
|
) | rpl::map([](TimeId from) {
|
||||||
|
@ -399,7 +400,34 @@ void SettingsWidget::addLimitsLabel(
|
||||||
) | Ui::Text::ToLink(u"internal:edit_from"_q);
|
) | Ui::Text::ToLink(u"internal:edit_from"_q);
|
||||||
}) | rpl::flatten_latest();
|
}) | rpl::flatten_latest();
|
||||||
|
|
||||||
auto tillLink = value() | rpl::map([](const Settings &data) {
|
const auto mapToTime = [](TimeId id, const QString &link) {
|
||||||
|
return rpl::single(id
|
||||||
|
? QLocale().toString(
|
||||||
|
base::unixtime::parse(id).time(),
|
||||||
|
QLocale::ShortFormat)
|
||||||
|
: QString()
|
||||||
|
) | Ui::Text::ToLink(link);
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto concat = [](TextWithEntities date, TextWithEntities link) {
|
||||||
|
return link.text.isEmpty()
|
||||||
|
? date
|
||||||
|
: date.append(u", "_q).append(std::move(link));
|
||||||
|
};
|
||||||
|
|
||||||
|
auto fromTimeLink = value() | rpl::map([](const Settings &data) {
|
||||||
|
return data.singlePeerFrom;
|
||||||
|
}) | rpl::distinct_until_changed(
|
||||||
|
) | rpl::map([=](TimeId from) {
|
||||||
|
return mapToTime(from, u"internal:edit_from_time"_q);
|
||||||
|
}) | rpl::flatten_latest();
|
||||||
|
|
||||||
|
auto fromLink = rpl::combine(
|
||||||
|
std::move(fromDateLink),
|
||||||
|
std::move(fromTimeLink)
|
||||||
|
) | rpl::map(concat);
|
||||||
|
|
||||||
|
auto tillDateLink = value() | rpl::map([](const Settings &data) {
|
||||||
return data.singlePeerTill;
|
return data.singlePeerTill;
|
||||||
}) | rpl::distinct_until_changed(
|
}) | rpl::distinct_until_changed(
|
||||||
) | rpl::map([](TimeId till) {
|
) | rpl::map([](TimeId till) {
|
||||||
|
@ -410,6 +438,18 @@ void SettingsWidget::addLimitsLabel(
|
||||||
) | Ui::Text::ToLink(u"internal:edit_till"_q);
|
) | Ui::Text::ToLink(u"internal:edit_till"_q);
|
||||||
}) | rpl::flatten_latest();
|
}) | rpl::flatten_latest();
|
||||||
|
|
||||||
|
auto tillTimeLink = value() | rpl::map([](const Settings &data) {
|
||||||
|
return data.singlePeerTill;
|
||||||
|
}) | rpl::distinct_until_changed(
|
||||||
|
) | rpl::map([=](TimeId till) {
|
||||||
|
return mapToTime(till, u"internal:edit_till_time"_q);
|
||||||
|
}) | rpl::flatten_latest();
|
||||||
|
|
||||||
|
auto tillLink = rpl::combine(
|
||||||
|
std::move(tillDateLink),
|
||||||
|
std::move(tillTimeLink)
|
||||||
|
) | rpl::map(concat);
|
||||||
|
|
||||||
auto datesText = tr::lng_export_limits(
|
auto datesText = tr::lng_export_limits(
|
||||||
lt_from,
|
lt_from,
|
||||||
std::move(fromLink),
|
std::move(fromLink),
|
||||||
|
@ -424,8 +464,47 @@ void SettingsWidget::addLimitsLabel(
|
||||||
object_ptr<Ui::FlatLabel>(
|
object_ptr<Ui::FlatLabel>(
|
||||||
container,
|
container,
|
||||||
std::move(datesText),
|
std::move(datesText),
|
||||||
st::exportLocationLabel),
|
st::boxLabel),
|
||||||
st::exportLimitsPadding);
|
st::exportLimitsPadding);
|
||||||
|
|
||||||
|
const auto removeTime = [](TimeId dateTime) {
|
||||||
|
return base::unixtime::serialize(
|
||||||
|
QDateTime(
|
||||||
|
base::unixtime::parse(dateTime).date(),
|
||||||
|
QTime()));
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto editTimeLimit = [=](Fn<TimeId()> now, Fn<void(TimeId)> done) {
|
||||||
|
_showBoxCallback(Box([=](not_null<Ui::GenericBox*> box) {
|
||||||
|
auto result = Ui::ChooseTimeWidget(
|
||||||
|
box->verticalLayout(),
|
||||||
|
[&] {
|
||||||
|
const auto time = base::unixtime::parse(now()).time();
|
||||||
|
return time.hour() * 3600
|
||||||
|
+ time.minute() * 60
|
||||||
|
+ time.second();
|
||||||
|
}(),
|
||||||
|
true);
|
||||||
|
const auto widget = box->addRow(std::move(result.widget));
|
||||||
|
const auto toSave = widget->lifetime().make_state<TimeId>(0);
|
||||||
|
std::move(
|
||||||
|
result.secondsValue
|
||||||
|
) | rpl::start_with_next([=](TimeId t) {
|
||||||
|
*toSave = t;
|
||||||
|
}, box->lifetime());
|
||||||
|
box->addButton(tr::lng_settings_save(), [=] {
|
||||||
|
done(*toSave);
|
||||||
|
box->closeBox();
|
||||||
|
});
|
||||||
|
box->addButton(tr::lng_cancel(), [=] {
|
||||||
|
box->closeBox();
|
||||||
|
});
|
||||||
|
box->setTitle(tr::lng_settings_ttl_after_custom());
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr auto kOffset = 600;
|
||||||
|
|
||||||
label->overrideLinkClickHandler([=](const QString &url) {
|
label->overrideLinkClickHandler([=](const QString &url) {
|
||||||
if (url == u"internal:edit_from"_q) {
|
if (url == u"internal:edit_from"_q) {
|
||||||
const auto done = [=](TimeId limit) {
|
const auto done = [=](TimeId limit) {
|
||||||
|
@ -439,10 +518,38 @@ void SettingsWidget::addLimitsLabel(
|
||||||
readData().singlePeerTill,
|
readData().singlePeerTill,
|
||||||
tr::lng_export_from_beginning(),
|
tr::lng_export_from_beginning(),
|
||||||
done);
|
done);
|
||||||
|
} else if (url == u"internal:edit_from_time"_q) {
|
||||||
|
const auto now = [=] {
|
||||||
|
auto result = TimeId(0);
|
||||||
|
changeData([&](Settings &settings) {
|
||||||
|
result = settings.singlePeerFrom;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
const auto done = [=](TimeId time) {
|
||||||
|
changeData([&](Settings &settings) {
|
||||||
|
const auto result = time
|
||||||
|
+ removeTime(settings.singlePeerFrom);
|
||||||
|
if (result >= settings.singlePeerTill
|
||||||
|
&& settings.singlePeerTill) {
|
||||||
|
settings.singlePeerFrom = settings.singlePeerTill
|
||||||
|
- kOffset;
|
||||||
|
} else {
|
||||||
|
settings.singlePeerFrom = result;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
editTimeLimit(now, done);
|
||||||
} else if (url == u"internal:edit_till"_q) {
|
} else if (url == u"internal:edit_till"_q) {
|
||||||
const auto done = [=](TimeId limit) {
|
const auto done = [=](TimeId limit) {
|
||||||
changeData([&](Settings &settings) {
|
changeData([&](Settings &settings) {
|
||||||
settings.singlePeerTill = limit;
|
if (limit <= settings.singlePeerFrom
|
||||||
|
&& settings.singlePeerFrom) {
|
||||||
|
settings.singlePeerTill = settings.singlePeerFrom
|
||||||
|
+ kOffset;
|
||||||
|
} else {
|
||||||
|
settings.singlePeerTill = limit;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
editDateLimit(
|
editDateLimit(
|
||||||
|
@ -451,6 +558,28 @@ void SettingsWidget::addLimitsLabel(
|
||||||
0,
|
0,
|
||||||
tr::lng_export_till_end(),
|
tr::lng_export_till_end(),
|
||||||
done);
|
done);
|
||||||
|
} else if (url == u"internal:edit_till_time"_q) {
|
||||||
|
const auto now = [=] {
|
||||||
|
auto result = TimeId(0);
|
||||||
|
changeData([&](Settings &settings) {
|
||||||
|
result = settings.singlePeerTill;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
const auto done = [=](TimeId time) {
|
||||||
|
changeData([&](Settings &settings) {
|
||||||
|
const auto result = time
|
||||||
|
+ removeTime(settings.singlePeerTill);
|
||||||
|
if (result <= settings.singlePeerFrom
|
||||||
|
&& settings.singlePeerFrom) {
|
||||||
|
settings.singlePeerTill = settings.singlePeerFrom
|
||||||
|
+ kOffset;
|
||||||
|
} else {
|
||||||
|
settings.singlePeerTill = result;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
editTimeLimit(now, done);
|
||||||
} else {
|
} else {
|
||||||
Unexpected("Click handler URL in export limits edit.");
|
Unexpected("Click handler URL in export limits edit.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1567,7 +1567,7 @@ void VoiceRecordBar::init() {
|
||||||
if (value == 0. && !show) {
|
if (value == 0. && !show) {
|
||||||
_lock->hide();
|
_lock->hide();
|
||||||
} else if (value == 1. && show) {
|
} else if (value == 1. && show) {
|
||||||
computeAndSetLockProgress(QCursor::pos());
|
_lock->requestPaintProgress(calcLockProgress(QCursor::pos()));
|
||||||
}
|
}
|
||||||
if (_fullRecord && !show) {
|
if (_fullRecord && !show) {
|
||||||
updateTTLGeometry(TTLAnimationType::RightLeft, 1.);
|
updateTTLGeometry(TTLAnimationType::RightLeft, 1.);
|
||||||
|
@ -1872,6 +1872,52 @@ void VoiceRecordBar::startRecording() {
|
||||||
|
|
||||||
_inField = true;
|
_inField = true;
|
||||||
|
|
||||||
|
struct FloatingState {
|
||||||
|
Ui::Animations::Basic animation;
|
||||||
|
float64 animationProgress = 0;
|
||||||
|
float64 cursorProgress = 0;
|
||||||
|
bool lockCapturedByInput = false;
|
||||||
|
float64 frameCounter = 0;
|
||||||
|
rpl::lifetime lifetime;
|
||||||
|
};
|
||||||
|
const auto stateOwned
|
||||||
|
= _recordingLifetime.make_state<std::unique_ptr<FloatingState>>(
|
||||||
|
std::make_unique<FloatingState>());
|
||||||
|
const auto state = stateOwned->get();
|
||||||
|
|
||||||
|
_lock->locks() | rpl::start_with_next([=] {
|
||||||
|
stateOwned->reset();
|
||||||
|
}, state->lifetime);
|
||||||
|
|
||||||
|
constexpr auto kAnimationThreshold = 0.35;
|
||||||
|
const auto calcStateRatio = [=](float64 counter) {
|
||||||
|
return (1 - std::cos(std::fmod(counter, 2 * M_PI))) * 0.5;
|
||||||
|
};
|
||||||
|
state->animation.init([=](crl::time now) {
|
||||||
|
if (state->cursorProgress > kAnimationThreshold) {
|
||||||
|
state->lockCapturedByInput = true;
|
||||||
|
}
|
||||||
|
if (state->lockCapturedByInput) {
|
||||||
|
if (state->cursorProgress < 0.01) {
|
||||||
|
state->lockCapturedByInput = false;
|
||||||
|
state->frameCounter = 0;
|
||||||
|
} else {
|
||||||
|
_lock->requestPaintProgress(state->cursorProgress);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto progress = anim::interpolateF(
|
||||||
|
state->cursorProgress,
|
||||||
|
kAnimationThreshold,
|
||||||
|
calcStateRatio(state->frameCounter));
|
||||||
|
state->frameCounter += 0.01;
|
||||||
|
_lock->requestPaintProgress(progress);
|
||||||
|
});
|
||||||
|
state->animation.start();
|
||||||
|
if (hasDuration()) {
|
||||||
|
stateOwned->reset();
|
||||||
|
}
|
||||||
|
|
||||||
_send->events(
|
_send->events(
|
||||||
) | rpl::filter([=](not_null<QEvent*> e) {
|
) | rpl::filter([=](not_null<QEvent*> e) {
|
||||||
return (e->type() == QEvent::MouseMove
|
return (e->type() == QEvent::MouseMove
|
||||||
|
@ -1892,7 +1938,10 @@ void VoiceRecordBar::startRecording() {
|
||||||
if (_showLockAnimation.animating() || !hasDuration()) {
|
if (_showLockAnimation.animating() || !hasDuration()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
computeAndSetLockProgress(mouse->globalPos());
|
const auto inputProgress = calcLockProgress(mouse->globalPos());
|
||||||
|
if (inputProgress > state->animationProgress) {
|
||||||
|
state->cursorProgress = inputProgress;
|
||||||
|
}
|
||||||
} else if (type == QEvent::MouseButtonRelease) {
|
} else if (type == QEvent::MouseButtonRelease) {
|
||||||
checkTipRequired();
|
checkTipRequired();
|
||||||
stop(_inField.current());
|
stop(_inField.current());
|
||||||
|
@ -2328,10 +2377,14 @@ float64 VoiceRecordBar::showListenAnimationRatio() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceRecordBar::computeAndSetLockProgress(QPoint globalPos) {
|
void VoiceRecordBar::computeAndSetLockProgress(QPoint globalPos) {
|
||||||
|
_lock->requestPaintProgress(calcLockProgress(globalPos));
|
||||||
|
}
|
||||||
|
|
||||||
|
float64 VoiceRecordBar::calcLockProgress(QPoint globalPos) {
|
||||||
const auto localPos = mapFromGlobal(globalPos);
|
const auto localPos = mapFromGlobal(globalPos);
|
||||||
const auto lower = _lock->height();
|
const auto lower = _lock->height();
|
||||||
const auto higher = 0;
|
const auto higher = 0;
|
||||||
_lock->requestPaintProgress(Progress(localPos.y(), higher - lower));
|
return Progress(localPos.y(), higher - lower);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VoiceRecordBar::peekTTLState() const {
|
bool VoiceRecordBar::peekTTLState() const {
|
||||||
|
|
|
@ -156,6 +156,7 @@ private:
|
||||||
[[nodiscard]] float64 activeAnimationRatio() const;
|
[[nodiscard]] float64 activeAnimationRatio() const;
|
||||||
|
|
||||||
void computeAndSetLockProgress(QPoint globalPos);
|
void computeAndSetLockProgress(QPoint globalPos);
|
||||||
|
[[nodiscard]] float64 calcLockProgress(QPoint globalPos);
|
||||||
|
|
||||||
[[nodiscard]] bool peekTTLState() const;
|
[[nodiscard]] bool peekTTLState() const;
|
||||||
[[nodiscard]] bool takeTTLState() const;
|
[[nodiscard]] bool takeTTLState() const;
|
||||||
|
|
|
@ -748,6 +748,7 @@ AdminLog::OwnedItem AboutView::makeNewPeerInfo(not_null<UserData*> user) {
|
||||||
owned.get(),
|
owned.get(),
|
||||||
GenerateNewPeerInfo(owned.get(), _item.get(), user, _commonGroups),
|
GenerateNewPeerInfo(owned.get(), _item.get(), user, _commonGroups),
|
||||||
HistoryView::MediaGenericDescriptor{
|
HistoryView::MediaGenericDescriptor{
|
||||||
|
.maxWidth = st::newPeerWidth,
|
||||||
.service = true,
|
.service = true,
|
||||||
.hideServiceText = true,
|
.hideServiceText = true,
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -308,6 +308,9 @@ void ContactStatus::Bar::showState(
|
||||||
_emojiStatusInfo->entity()->overrideLinkClickHandler([=] {
|
_emojiStatusInfo->entity()->overrideLinkClickHandler([=] {
|
||||||
_emojiStatusClicks.fire({});
|
_emojiStatusClicks.fire({});
|
||||||
});
|
});
|
||||||
|
_emojiStatusInfo->entity()->setAnimationsPausedCallback([] {
|
||||||
|
return Ui::FlatLabel::WhichAnimationsPaused::CustomEmoji;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
_emojiStatusInfo->setVisible(has);
|
_emojiStatusInfo->setVisible(has);
|
||||||
_add->setText((type == Type::Add)
|
_add->setText((type == Type::Add)
|
||||||
|
|
|
@ -304,7 +304,7 @@ QSize MediaGenericTextPart::countCurrentSize(int newWidth) {
|
||||||
const auto size = CountOptimalTextSize(
|
const auto size = CountOptimalTextSize(
|
||||||
_text,
|
_text,
|
||||||
st::msgMinWidth,
|
st::msgMinWidth,
|
||||||
newWidth - skip);
|
std::max(st::msgMinWidth, newWidth - skip));
|
||||||
return {
|
return {
|
||||||
size.width() + skip,
|
size.width() + skip,
|
||||||
_margins.top() + size.height() + _margins.bottom(),
|
_margins.top() + size.height() + _margins.bottom(),
|
||||||
|
|
|
@ -274,7 +274,10 @@ void InnerWidget::markUnpinned(std::vector<Entry>::iterator i) {
|
||||||
}
|
}
|
||||||
++after;
|
++after;
|
||||||
}
|
}
|
||||||
if (after == _entries.size()) {
|
if (after == _entries.size() && !_allLoaded) {
|
||||||
|
// We don't know if the correct position is exactly in the end
|
||||||
|
// of the loaded part or later, so we hide it for now, let it
|
||||||
|
// be loaded later while scrolling.
|
||||||
_entries.erase(i);
|
_entries.erase(i);
|
||||||
} else if (after > index + 1) {
|
} else if (after > index + 1) {
|
||||||
std::rotate(i, i + 1, begin(_entries) + after);
|
std::rotate(i, i + 1, begin(_entries) + after);
|
||||||
|
|
|
@ -12,6 +12,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "base/platform/linux/base_linux_xdp_utilities.h"
|
#include "base/platform/linux/base_linux_xdp_utilities.h"
|
||||||
#include "core/sandbox.h"
|
#include "core/sandbox.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0)
|
||||||
|
#include "core/core_settings.h"
|
||||||
|
#endif
|
||||||
#include "base/random.h"
|
#include "base/random.h"
|
||||||
|
|
||||||
#include <QtCore/QAbstractEventDispatcher>
|
#include <QtCore/QAbstractEventDispatcher>
|
||||||
|
|
|
@ -423,7 +423,8 @@ void Manager::Private::init(XdgNotifications::NotificationsProxy proxy) {
|
||||||
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
||||||
for (const auto &[key, notifications] : _notifications) {
|
for (const auto &[key, notifications] : _notifications) {
|
||||||
for (const auto &[msgId, notification] : notifications) {
|
for (const auto &[msgId, notification] : notifications) {
|
||||||
if (id == v::get<uint>(notification->id)) {
|
const auto &nid = notification->id;
|
||||||
|
if (v::is<uint>(nid) && v::get<uint>(nid) == id) {
|
||||||
if (actionName == "default") {
|
if (actionName == "default") {
|
||||||
_manager->notificationActivated({ key, msgId });
|
_manager->notificationActivated({ key, msgId });
|
||||||
} else if (actionName == "mail-mark-read") {
|
} else if (actionName == "mail-mark-read") {
|
||||||
|
@ -447,7 +448,8 @@ void Manager::Private::init(XdgNotifications::NotificationsProxy proxy) {
|
||||||
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
||||||
for (const auto &[key, notifications] : _notifications) {
|
for (const auto &[key, notifications] : _notifications) {
|
||||||
for (const auto &[msgId, notification] : notifications) {
|
for (const auto &[msgId, notification] : notifications) {
|
||||||
if (id == v::get<uint>(notification->id)) {
|
const auto &nid = notification->id;
|
||||||
|
if (v::is<uint>(nid) && v::get<uint>(nid) == id) {
|
||||||
_manager->notificationReplied(
|
_manager->notificationReplied(
|
||||||
{ key, msgId },
|
{ key, msgId },
|
||||||
{ QString::fromStdString(text), {} });
|
{ QString::fromStdString(text), {} });
|
||||||
|
@ -468,7 +470,8 @@ void Manager::Private::init(XdgNotifications::NotificationsProxy proxy) {
|
||||||
std::string token) {
|
std::string token) {
|
||||||
for (const auto &[key, notifications] : _notifications) {
|
for (const auto &[key, notifications] : _notifications) {
|
||||||
for (const auto &[msgId, notification] : notifications) {
|
for (const auto &[msgId, notification] : notifications) {
|
||||||
if (id == v::get<uint>(notification->id)) {
|
const auto &nid = notification->id;
|
||||||
|
if (v::is<uint>(nid) && v::get<uint>(nid) == id) {
|
||||||
GLib::setenv("XDG_ACTIVATION_TOKEN", token, true);
|
GLib::setenv("XDG_ACTIVATION_TOKEN", token, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -501,7 +504,8 @@ void Manager::Private::init(XdgNotifications::NotificationsProxy proxy) {
|
||||||
* In all other cases we keep the notification reference so that we may clear the notification later from history,
|
* In all other cases we keep the notification reference so that we may clear the notification later from history,
|
||||||
* if the message for that notification is read (e.g. chat is opened or read from another device).
|
* if the message for that notification is read (e.g. chat is opened or read from another device).
|
||||||
*/
|
*/
|
||||||
if (id == v::get<uint>(notification->id) && reason == 2) {
|
const auto &nid = notification->id;
|
||||||
|
if (v::is<uint>(nid) && v::get<uint>(nid) == id && reason == 2) {
|
||||||
clearNotification({ key, msgId });
|
clearNotification({ key, msgId });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,8 @@ namespace Ui {
|
||||||
|
|
||||||
ChooseTimeResult ChooseTimeWidget(
|
ChooseTimeResult ChooseTimeWidget(
|
||||||
not_null<RpWidget*> parent,
|
not_null<RpWidget*> parent,
|
||||||
TimeId startSeconds) {
|
TimeId startSeconds,
|
||||||
|
bool hiddenDaysInput) {
|
||||||
using TimeField = Ui::TimePartWithPlaceholder;
|
using TimeField = Ui::TimePartWithPlaceholder;
|
||||||
const auto putNext = [](not_null<TimeField*> field, QChar ch) {
|
const auto putNext = [](not_null<TimeField*> field, QChar ch) {
|
||||||
field->setCursorPosition(0);
|
field->setCursorPosition(0);
|
||||||
|
@ -79,6 +80,10 @@ ChooseTimeResult ChooseTimeWidget(
|
||||||
const auto hour = Ui::MakeWeak(state->hour);
|
const auto hour = Ui::MakeWeak(state->hour);
|
||||||
const auto minute = Ui::MakeWeak(state->minute);
|
const auto minute = Ui::MakeWeak(state->minute);
|
||||||
|
|
||||||
|
if (hiddenDaysInput) {
|
||||||
|
day->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
day->setPhrase(tr::lng_days);
|
day->setPhrase(tr::lng_days);
|
||||||
day->setMaxValue(31);
|
day->setMaxValue(31);
|
||||||
day->setWheelStep(1);
|
day->setWheelStep(1);
|
||||||
|
@ -105,13 +110,16 @@ ChooseTimeResult ChooseTimeWidget(
|
||||||
|
|
||||||
content->sizeValue(
|
content->sizeValue(
|
||||||
) | rpl::start_with_next([=](const QSize &s) {
|
) | rpl::start_with_next([=](const QSize &s) {
|
||||||
const auto inputWidth = s.width() / 3;
|
const auto inputWidth = s.width() / (hiddenDaysInput ? 2 : 3);
|
||||||
auto rect = QRect(
|
auto rect = QRect(
|
||||||
0,
|
0,
|
||||||
(s.height() - day->height()) / 2,
|
(s.height() - day->height()) / 2,
|
||||||
inputWidth,
|
inputWidth,
|
||||||
day->height());
|
day->height());
|
||||||
for (const auto &input : { day, hour, minute }) {
|
for (const auto &input : { day, hour, minute }) {
|
||||||
|
if (input->isHidden()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
input->setGeometry(rect - st::muteBoxTimeFieldPadding);
|
input->setGeometry(rect - st::muteBoxTimeFieldPadding);
|
||||||
rect.translate(inputWidth, 0);
|
rect.translate(inputWidth, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ struct ChooseTimeResult {
|
||||||
|
|
||||||
ChooseTimeResult ChooseTimeWidget(
|
ChooseTimeResult ChooseTimeWidget(
|
||||||
not_null<RpWidget*> parent,
|
not_null<RpWidget*> parent,
|
||||||
TimeId startSeconds);
|
TimeId startSeconds,
|
||||||
|
bool hiddenDaysInput = false);
|
||||||
|
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
@ -1244,3 +1244,4 @@ newPeerUserpics: GroupCallUserpics {
|
||||||
align: align(left);
|
align: align(left);
|
||||||
}
|
}
|
||||||
newPeerUserpicsPadding: margins(0px, 3px, 0px, 0px);
|
newPeerUserpicsPadding: margins(0px, 3px, 0px, 0px);
|
||||||
|
newPeerWidth: 320px;
|
||||||
|
|
|
@ -72,8 +72,8 @@ void SendButton::setState(State state) {
|
||||||
st::universalDuration);
|
st::universalDuration);
|
||||||
setPointerCursor(_state.type != Type::Slowmode);
|
setPointerCursor(_state.type != Type::Slowmode);
|
||||||
updateSize();
|
updateSize();
|
||||||
update();
|
|
||||||
}
|
}
|
||||||
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendButton::finishAnimating() {
|
void SendButton::finishAnimating() {
|
||||||
|
|
|
@ -49,6 +49,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_chat_filters.h"
|
#include "data/data_chat_filters.h"
|
||||||
#include "data/data_replies_list.h"
|
#include "data/data_replies_list.h"
|
||||||
#include "data/data_peer_values.h"
|
#include "data/data_peer_values.h"
|
||||||
|
#include "data/data_premium_limits.h"
|
||||||
#include "data/data_web_page.h"
|
#include "data/data_web_page.h"
|
||||||
#include "passport/passport_form_controller.h"
|
#include "passport/passport_form_controller.h"
|
||||||
#include "chat_helpers/tabbed_selector.h"
|
#include "chat_helpers/tabbed_selector.h"
|
||||||
|
@ -3252,4 +3253,34 @@ SessionController::~SessionController() {
|
||||||
resetFakeUnreadWhileOpened();
|
resetFakeUnreadWhileOpened();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CheckAndJumpToNearChatsFilter(
|
||||||
|
not_null<SessionController*> controller,
|
||||||
|
bool isNext,
|
||||||
|
bool jump) {
|
||||||
|
const auto id = controller->activeChatsFilterCurrent();
|
||||||
|
const auto session = &controller->session();
|
||||||
|
const auto list = &session->data().chatsFilters().list();
|
||||||
|
const auto index = int(ranges::find(
|
||||||
|
*list,
|
||||||
|
id,
|
||||||
|
&Data::ChatFilter::id
|
||||||
|
) - begin(*list));
|
||||||
|
if (index == list->size() && id != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto changed = index + (isNext ? 1 : -1);
|
||||||
|
if (changed >= int(list->size()) || changed < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (changed > Data::PremiumLimits(session).dialogFiltersCurrent()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (jump) {
|
||||||
|
controller->setActiveChatsFilter((changed >= 0)
|
||||||
|
? (*list)[changed].id()
|
||||||
|
: 0);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Window
|
} // namespace Window
|
||||||
|
|
|
@ -757,4 +757,9 @@ void ActivateWindow(not_null<SessionController*> controller);
|
||||||
not_null<SessionController*> controller,
|
not_null<SessionController*> controller,
|
||||||
GifPauseReason level);
|
GifPauseReason level);
|
||||||
|
|
||||||
|
bool CheckAndJumpToNearChatsFilter(
|
||||||
|
not_null<SessionController*> controller,
|
||||||
|
bool isNext,
|
||||||
|
bool jump);
|
||||||
|
|
||||||
} // namespace Window
|
} // namespace Window
|
||||||
|
|
|
@ -1148,10 +1148,19 @@ depends:yasm/yasm
|
||||||
""")
|
""")
|
||||||
|
|
||||||
stage('liblcms2', """
|
stage('liblcms2', """
|
||||||
mac:
|
|
||||||
git clone -b lcms2.16 https://github.com/mm2/Little-CMS.git liblcms2
|
git clone -b lcms2.16 https://github.com/mm2/Little-CMS.git liblcms2
|
||||||
cd liblcms2
|
cd liblcms2
|
||||||
|
win:
|
||||||
|
depends:python/Scripts/activate.bat
|
||||||
|
%THIRDPARTY_DIR%\\python\\Scripts\\activate.bat
|
||||||
|
meson setup --default-library=static --buildtype=debug -Db_vscrt=mtd out/Debug
|
||||||
|
meson compile -C out/Debug
|
||||||
|
release:
|
||||||
|
meson setup --default-library=static --buildtype=release -Db_vscrt=mt out/Release
|
||||||
|
meson compile -C out/Release
|
||||||
|
win:
|
||||||
|
deactivate
|
||||||
|
mac:
|
||||||
buildOneArch() {
|
buildOneArch() {
|
||||||
arch=$1
|
arch=$1
|
||||||
folder=`pwd`/$2
|
folder=`pwd`/$2
|
||||||
|
@ -1689,6 +1698,7 @@ win:
|
||||||
SET OPENSSL_LIBS_DIR=%OPENSSL_DIR%\\out
|
SET OPENSSL_LIBS_DIR=%OPENSSL_DIR%\\out
|
||||||
SET ZLIB_LIBS_DIR=%LIBS_DIR%\\zlib
|
SET ZLIB_LIBS_DIR=%LIBS_DIR%\\zlib
|
||||||
SET WEBP_DIR=%LIBS_DIR%\\libwebp
|
SET WEBP_DIR=%LIBS_DIR%\\libwebp
|
||||||
|
SET LCMS2_DIR=%LIBS_DIR%\\liblcms2
|
||||||
configure -prefix "%LIBS_DIR%\\Qt-%QT%" ^
|
configure -prefix "%LIBS_DIR%\\Qt-%QT%" ^
|
||||||
%CONFIGURATIONS% ^
|
%CONFIGURATIONS% ^
|
||||||
-force-debug-info ^
|
-force-debug-info ^
|
||||||
|
@ -1726,7 +1736,10 @@ win:
|
||||||
-D WebP_mux_INCLUDE_DIR="%WEBP_DIR%\\src" ^
|
-D WebP_mux_INCLUDE_DIR="%WEBP_DIR%\\src" ^
|
||||||
-D WebP_LIBRARY="%WEBP_DIR%\\out\\release-static\\$X8664\\lib\\webp.lib" ^
|
-D WebP_LIBRARY="%WEBP_DIR%\\out\\release-static\\$X8664\\lib\\webp.lib" ^
|
||||||
-D WebP_demux_LIBRARY="%WEBP_DIR%\\out\\release-static\\$X8664\\lib\\webpdemux.lib" ^
|
-D WebP_demux_LIBRARY="%WEBP_DIR%\\out\\release-static\\$X8664\\lib\\webpdemux.lib" ^
|
||||||
-D WebP_mux_LIBRARY="%WEBP_DIR%\\out\\release-static\\$X8664\\lib\\webpmux.lib"
|
-D WebP_mux_LIBRARY="%WEBP_DIR%\\out\\release-static\\$X8664\\lib\\webpmux.lib" ^
|
||||||
|
-D LCMS2_FOUND=1 ^
|
||||||
|
-D LCMS2_INCLUDE_DIR="%LCMS2_DIR%\\include" ^
|
||||||
|
-D LCMS2_LIBRARIES="%LCMS2_DIR%\\out\Release\\src\\liblcms2.a"
|
||||||
|
|
||||||
cmake --build . --config Debug --parallel
|
cmake --build . --config Debug --parallel
|
||||||
cmake --install . --config Debug
|
cmake --install . --config Debug
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
AppVersion 5012001
|
AppVersion 5012003
|
||||||
AppVersionStrMajor 5.12
|
AppVersionStrMajor 5.12
|
||||||
AppVersionStrSmall 5.12.1
|
AppVersionStrSmall 5.12.3
|
||||||
AppVersionStr 5.12.1
|
AppVersionStr 5.12.3
|
||||||
BetaChannel 0
|
BetaChannel 0
|
||||||
AlphaVersion 0
|
AlphaVersion 0
|
||||||
AppVersionOriginal 5.12.1
|
AppVersionOriginal 5.12.3
|
||||||
|
|
|
@ -1,3 +1,13 @@
|
||||||
|
5.12.3 (10.03.25)
|
||||||
|
|
||||||
|
- Fix a couple more crashes.
|
||||||
|
- Fix gift disappearing on unpin.
|
||||||
|
- Fix country emoji for Fragment numbers.
|
||||||
|
|
||||||
|
5.12.2 (09.03.25)
|
||||||
|
|
||||||
|
- Fix some crashes.
|
||||||
|
|
||||||
5.12.1 (08.03.25)
|
5.12.1 (08.03.25)
|
||||||
|
|
||||||
- Fix a crash in some chat switchings.
|
- Fix a crash in some chat switchings.
|
||||||
|
|
2
cmake
2
cmake
|
@ -1 +1 @@
|
||||||
Subproject commit 8c146a3ec6f4475e5083eee84d126960495a7e1d
|
Subproject commit 90e6d73100a9fd2dc4c30a270c3bbc1d35924f32
|
Loading…
Add table
Reference in a new issue