Compare commits

..

21 Commits

Author SHA1 Message Date
John Preston
f771ad8cb1 Beta version 3.0.4: Fix build for Windows. 2021-09-13 20:13:15 +03:00
John Preston
6a53fc7edc Beta version 3.0.4: Add some theme loading logging. 2021-09-13 20:09:55 +03:00
John Preston
889c3293e7 Fix PathShiftGradient colors with custom palettes. 2021-09-13 20:09:23 +03:00
23rd
fa4b7145f5 Added extra space to choosing sticker animation in left position. 2021-09-13 18:13:50 +03:00
23rd
a5be9d78d8 Fixed animation for grouped userpics in who read context menu item. 2021-09-13 18:13:50 +03:00
John Preston
21c562fcb7 Make "set_version.py" working with Python 2.7 as well. 2021-09-13 18:03:43 +03:00
John Preston
626c062bf0 Beta version 3.0.4.
- Fix a crash when joining video chat or live broadcast.
- Add a "Close to Taskbar" option when tray icon is disabled
(Windows and Linux).
2021-09-13 18:01:39 +03:00
Ilya Fedin
e92ae40ecb Implement close to taskbar option 2021-09-13 17:46:53 +03:00
John Preston
ce256161f1 Couple of crash fixes. 2021-09-13 17:39:17 +03:00
John Preston
3bf9a1c70b Build minidump_stackwalk as part of macOS prepare. 2021-09-13 16:59:10 +03:00
John Preston
3202a5f081 Fix prepare getch for macOS. 2021-09-13 16:50:44 +03:00
John Preston
e99f650eaa Change default autoupdate URL. 2021-09-13 16:33:31 +03:00
John Preston
c6097d3d11 Accept "livestream" and "videochat" link params. 2021-09-13 16:19:59 +03:00
John Preston
58b5b3deec Update main built-in palette values. 2021-09-13 15:40:02 +03:00
John Preston
5a63428093 Improve messages in preparep.py. 2021-09-13 15:39:44 +03:00
John Preston
0c42bca111 Ask before rebuilding in prepare.py. 2021-09-13 15:01:52 +03:00
John Preston
13bf089672 Update patches revision. 2021-09-13 14:21:56 +03:00
John Preston
f73264025d Fix a crash after joining broadcasts. 2021-09-13 14:21:01 +03:00
Ilya Fedin
0a6fb696a3 Build Qt without egl-extension-platform-wayland 2021-09-13 10:51:35 +03:00
John Preston
bc2e6c4fd1 Accept uppercase hex values in theme testing links. 2021-09-12 23:18:37 +03:00
John Preston
d822f8e9ff Improve colorizing more. 2021-09-12 23:16:23 +03:00
38 changed files with 451 additions and 83 deletions

View File

@@ -357,6 +357,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_update_fail" = "Update check failed :(";
"lng_settings_workmode_tray" = "Show tray icon";
"lng_settings_workmode_window" = "Show taskbar icon";
"lng_settings_close_to_taskbar" = "Close to taskbar";
"lng_settings_native_frame" = "Use system window frame";
"lng_settings_auto_start" = "Launch Telegram when system starts";
"lng_settings_start_min" = "Launch minimized";

View File

@@ -9,7 +9,7 @@
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
ProcessorArchitecture="ARCHITECTURE"
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
Version="3.0.3.0" />
Version="3.0.4.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 3,0,3,0
PRODUCTVERSION 3,0,3,0
FILEVERSION 3,0,4,0
PRODUCTVERSION 3,0,4,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -62,10 +62,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram FZ-LLC"
VALUE "FileDescription", "Telegram Desktop"
VALUE "FileVersion", "3.0.3.0"
VALUE "FileVersion", "3.0.4.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2021"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "3.0.3.0"
VALUE "ProductVersion", "3.0.4.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,0,3,0
PRODUCTVERSION 3,0,3,0
FILEVERSION 3,0,4,0
PRODUCTVERSION 3,0,4,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -53,10 +53,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram FZ-LLC"
VALUE "FileDescription", "Telegram Desktop Updater"
VALUE "FileVersion", "3.0.3.0"
VALUE "FileVersion", "3.0.4.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2021"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "3.0.3.0"
VALUE "ProductVersion", "3.0.4.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -74,6 +74,11 @@ constexpr auto kMaxMediumQualities = 16; // 4 Fulls or 16 Mediums.
return msgId / double(1ULL << 32);
}
[[nodiscard]] int64 TimestampInMsFromMsgId(mtpMsgId msgId) {
// return (msgId * 1000) / (1ULL << 32); // Almost... But this overflows.
return ((msgId / (1ULL << 10)) * 1000) / (1ULL << 22);
}
[[nodiscard]] uint64 FindLocalRaisedHandRating(
const std::vector<Data::GroupCallParticipant> &list) {
const auto i = ranges::max_element(
@@ -95,6 +100,41 @@ using JoinClientFields = std::variant<
JoinVideoEndpoint,
JoinBroadcastStream>;
class RequestCurrentTimeTask final : public tgcalls::BroadcastPartTask {
public:
RequestCurrentTimeTask(
base::weak_ptr<GroupCall> call,
Fn<void(int64)> done);
void done(int64 value);
void cancel() override;
private:
const base::weak_ptr<GroupCall> _call;
Fn<void(int64)> _done;
QMutex _mutex;
};
RequestCurrentTimeTask::RequestCurrentTimeTask(
base::weak_ptr<GroupCall> call,
Fn<void(int64)> done)
: _call(call)
, _done(std::move(done)) {
}
void RequestCurrentTimeTask::done(int64 value) {
QMutexLocker lock(&_mutex);
if (_done) {
base::take(_done)(value);
}
}
void RequestCurrentTimeTask::cancel() {
QMutexLocker lock(&_mutex);
_done = nullptr;
}
[[nodiscard]] JoinClientFields ParseJoinResponse(const QByteArray &json) {
auto error = QJsonParseError{ 0, QJsonParseError::NoError };
const auto document = QJsonDocument::fromJson(json, &error);
@@ -1273,7 +1313,12 @@ void GroupCall::rejoin(not_null<PeerData*> as) {
joinAs()->input,
MTP_string(_joinHash),
MTP_dataJSON(MTP_bytes(json))
)).done([=](const MTPUpdates &updates) {
)).done([=](
const MTPUpdates &updates,
const MTP::Response &response) {
_serverTimeMs = TimestampInMsFromMsgId(response.outerMsgId);
_serverTimeMsGotAt = crl::now();
_joinState.finish(ssrc);
_mySsrcs.emplace(ssrc);
@@ -2253,6 +2298,16 @@ bool GroupCall::tryCreateController() {
.createAudioDeviceModule = Webrtc::AudioDeviceModuleCreator(
settings.callAudioBackend()),
.videoCapture = _cameraCapture,
.requestCurrentTime = [=, call = base::make_weak(this)](
std::function<void(int64_t)> done) {
auto result = std::make_shared<RequestCurrentTimeTask>(
call,
std::move(done));
crl::on_main(weak, [=] {
result->done(approximateServerTimeInMs());
});
return result;
},
.requestAudioBroadcastPart = [=, call = base::make_weak(this)](
int64_t time,
int64_t period,
@@ -2499,6 +2554,12 @@ void GroupCall::mediaChannelDescriptionsCancel(
}
}
int64 GroupCall::approximateServerTimeInMs() const {
Expects(_serverTimeMs != 0);
return _serverTimeMs + (crl::now() - _serverTimeMsGotAt);
}
void GroupCall::updateRequestedVideoChannels() {
_requestedVideoChannelsUpdateScheduled = false;
const auto real = lookupReal();

View File

@@ -406,16 +406,6 @@ public:
private:
class LoadPartTask;
class MediaChannelDescriptionsTask;
public:
void broadcastPartStart(std::shared_ptr<LoadPartTask> task);
void broadcastPartCancel(not_null<LoadPartTask*> task);
void mediaChannelDescriptionsStart(
std::shared_ptr<MediaChannelDescriptionsTask> task);
void mediaChannelDescriptionsCancel(
not_null<MediaChannelDescriptionsTask*> task);
private:
using GlobalShortcutValue = base::GlobalShortcutValue;
using Error = Group::Error;
struct SinkPointer;
@@ -464,6 +454,14 @@ private:
return true;
}
void broadcastPartStart(std::shared_ptr<LoadPartTask> task);
void broadcastPartCancel(not_null<LoadPartTask*> task);
void mediaChannelDescriptionsStart(
std::shared_ptr<MediaChannelDescriptionsTask> task);
void mediaChannelDescriptionsCancel(
not_null<MediaChannelDescriptionsTask*> task);
[[nodiscard]] int64 approximateServerTimeInMs() const;
[[nodiscard]] bool mediaChannelDescriptionsFill(
not_null<MediaChannelDescriptionsTask*> task,
Fn<bool(uint32)> resolved = nullptr);
@@ -571,11 +569,14 @@ private:
base::flat_set<
std::shared_ptr<
MediaChannelDescriptionsTask>,
base::pointer_comparator<MediaChannelDescriptionsTask>> _mediaChannelDescriptionses;
base::pointer_comparator<
MediaChannelDescriptionsTask>> _mediaChannelDescriptionses;
rpl::variable<not_null<PeerData*>> _joinAs;
std::vector<not_null<PeerData*>> _possibleJoinAs;
QString _joinHash;
int64 _serverTimeMs = 0;
crl::time _serverTimeMsGotAt = 0;
rpl::variable<MuteState> _muted = MuteState::Muted;
rpl::variable<bool> _canManage = false;

View File

@@ -35,6 +35,14 @@ Viewport::VideoTile::VideoTile(
Expects(track.track != nullptr);
Expects(track.row != nullptr);
using namespace rpl::mappers;
_track.track->stateValue(
) | rpl::filter(
_1 == Webrtc::VideoState::Paused
) | rpl::take(1) | rpl::start_with_next([=] {
_wasPaused = true;
}, _lifetime);
setup(std::move(pinned));
}
@@ -68,11 +76,8 @@ QSize Viewport::VideoTile::PausedVideoSize() {
QSize Viewport::VideoTile::trackOrUserpicSize() const {
if (const auto size = trackSize(); !size.isEmpty()) {
return size;
} else if (_userpicSize.isEmpty()
&& _track.track->state() == Webrtc::VideoState::Paused) {
_userpicSize = PausedVideoSize();
}
return _userpicSize;
return _wasPaused ? PausedVideoSize() : QSize();
}
bool Viewport::VideoTile::screencast() const {

View File

@@ -110,12 +110,12 @@ private:
QRect _geometry;
TileAnimation _animation;
rpl::variable<QSize> _trackSize;
mutable QSize _userpicSize;
QRect _pinOuter;
QRect _pinInner;
QRect _backOuter;
QRect _backInner;
Ui::Animations::Simple _topControlsShownAnimation;
bool _wasPaused = false;
bool _topControlsShown = false;
bool _pinned = false;
bool _hidden = true;

View File

@@ -47,6 +47,13 @@ std::map<int, const char*> BetaLogs() {
"from the context menu.\n"
"- Enable recording with video in live streams and video chats."
},
{
3000004,
"- Fix a crash when joining video chat or live broadcast.\n"
"- Add a \"Close to Taskbar\" option when tray icon is disabled "
"(Windows and Linux)."
}
};
};

View File

@@ -220,7 +220,8 @@ QByteArray Settings::serialize() const {
<< qint32(_disableOpenGL ? 1 : 0)
<< _photoEditorBrush
<< qint32(_groupCallNoiseSuppression ? 1 : 0)
<< qint32(_voicePlaybackSpeed * 100);
<< qint32(_voicePlaybackSpeed * 100)
<< qint32(_closeToTaskbar.current() ? 1 : 0);
}
return result;
}
@@ -303,6 +304,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
QByteArray proxy;
qint32 hiddenGroupCallTooltips = qint32(_hiddenGroupCallTooltips.value());
QByteArray photoEditorBrush = _photoEditorBrush;
qint32 closeToTaskbar = _closeToTaskbar.current() ? 1 : 0;
stream >> themesAccentColors;
if (!stream.atEnd()) {
@@ -460,6 +462,9 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
if (!stream.atEnd()) {
stream >> voicePlaybackSpeed;
}
if (!stream.atEnd()) {
stream >> closeToTaskbar;
}
if (stream.status() != QDataStream::Ok) {
LOG(("App Error: "
"Bad data for Core::Settings::constructFromSerialized()"));
@@ -600,6 +605,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
: Tooltip(0));
}();
_photoEditorBrush = photoEditorBrush;
_closeToTaskbar = (closeToTaskbar == 1);
}
QString Settings::getSoundPath(const QString &key) const {

View File

@@ -601,6 +601,19 @@ public:
_hiddenGroupCallTooltips |= value;
}
void setCloseToTaskbar(bool value) {
_closeToTaskbar = value;
}
[[nodiscard]] bool closeToTaskbar() const {
return _closeToTaskbar.current();
}
[[nodiscard]] rpl::producer<bool> closeToTaskbarValue() const {
return _closeToTaskbar.value();
}
[[nodiscard]] rpl::producer<bool> closeToTaskbarChanges() const {
return _closeToTaskbar.changes();
}
[[nodiscard]] static bool ThirdColumnByDefault();
[[nodiscard]] static float64 DefaultDialogsWidthRatio();
[[nodiscard]] static qint32 SerializePlaybackSpeed(float64 speed) {
@@ -700,6 +713,7 @@ private:
bool _disableOpenGL = false;
rpl::variable<WorkMode> _workMode = WorkMode::WindowAndTray;
base::flags<Calls::Group::StickedTooltip> _hiddenGroupCallTooltips;
rpl::variable<bool> _closeToTaskbar = false;
bool _tabbedReplacedWithInfo = false; // per-window
rpl::event_stream<bool> _tabbedReplacedWithInfoValue; // per-window

View File

@@ -464,6 +464,7 @@ void Launcher::processArguments() {
{ "-noupdate" , KeyFormat::NoValues },
{ "-tosettings" , KeyFormat::NoValues },
{ "-startintray" , KeyFormat::NoValues },
{ "-quit" , KeyFormat::NoValues },
{ "-sendpath" , KeyFormat::AllLeftValues },
{ "-workdir" , KeyFormat::OneValue },
{ "--" , KeyFormat::OneValue },
@@ -504,6 +505,7 @@ void Launcher::processArguments() {
gNoStartUpdate = parseResult.contains("-noupdate");
gStartToSettings = parseResult.contains("-tosettings");
gStartInTray = parseResult.contains("-startintray");
gQuit = parseResult.contains("-quit");
gSendPaths = parseResult.value("-sendpath", {});
gWorkingDir = parseResult.value("-workdir", {}).join(QString());
if (!gWorkingDir.isEmpty()) {

View File

@@ -308,7 +308,11 @@ bool ResolveUsername(
}
: Navigation::RepliesByLinkInfo{ v::null },
.startToken = startToken,
.voicechatHash = (params.contains(u"voicechat"_q)
.voicechatHash = (params.contains(u"livestream"_q)
? std::make_optional(params.value(u"livestream"_q))
: params.contains(u"videochat"_q)
? std::make_optional(params.value(u"videochat"_q))
: params.contains(u"voicechat"_q)
? std::make_optional(params.value(u"voicechat"_q))
: std::nullopt),
.clickFromMessageId = fromMessageId,

View File

@@ -237,6 +237,8 @@ void Sandbox::socketConnected() {
}
if (!cStartUrl().isEmpty()) {
commands += qsl("OPEN:") + _escapeTo7bit(cStartUrl()) + ';';
} else if (cQuit()) {
commands += qsl("CMD:quit;");
} else {
commands += qsl("CMD:show;");
}
@@ -305,6 +307,10 @@ void Sandbox::socketError(QLocalSocket::LocalSocketError e) {
return App::quit();
}
if (cQuit()) {
return App::quit();
}
singleInstanceChecked();
}
@@ -605,6 +611,8 @@ void Sandbox::execExternal(const QString &cmd) {
} else if (PreLaunchWindow::instance()) {
PreLaunchWindow::instance()->activate();
}
} else if (cmd == "quit") {
App::quit();
}
}

View File

@@ -22,7 +22,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D1ED}"_cs;
constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs;
constexpr auto AppName = "Telegram Desktop"_cs;
constexpr auto AppFile = "Telegram"_cs;
constexpr auto AppVersion = 3000003;
constexpr auto AppVersionStr = "3.0.3";
constexpr auto AppVersion = 3000004;
constexpr auto AppVersionStr = "3.0.4";
constexpr auto AppBetaVersion = true;
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;

View File

@@ -486,6 +486,8 @@ std::optional<CloudTheme> CloudThemes::updateThemeFromLink(
? std::nullopt
: (value[0] >= 'a' && value[0] <= 'f')
? std::make_optional(10 + int(value[0].unicode() - 'a'))
: (value[0] >= 'A' && value[0] <= 'F')
? std::make_optional(10 + int(value[0].unicode() - 'A'))
: (value[0] >= '0' && value[0] <= '9')
? std::make_optional(int(value[0].unicode() - '0'))
: std::nullopt;

View File

@@ -67,7 +67,8 @@ std::unique_ptr<Ui::PathShiftGradient> MakePathShiftGradient(
return std::make_unique<Ui::PathShiftGradient>(
st->msgServiceBg(),
st->msgServiceBgSelected(),
std::move(update));
std::move(update),
st->paletteChanged());
}
SimpleElementDelegate::SimpleElementDelegate(

View File

@@ -309,7 +309,7 @@ bool SendActionPainter::updateNeedsAnimating(crl::time now, bool force) {
// FontData::spacew for more precise calculation.
const auto mf = QFontMetricsF(_st.font->f);
_spacesCount = std::round(
_sendActionAnimation.width()
_sendActionAnimation.widthNoMargins()
/ mf.horizontalAdvance(' '));
}
newTypingString = newTypingString.replace(

View File

@@ -315,12 +315,18 @@ bool GenerateDesktopFile(
fileText = fileText.replace(
QRegularExpression(
qsl("^Exec=.*$"),
qsl("^Exec=telegram-desktop(.*)$"),
QRegularExpression::MultilineOption),
qsl("Exec=%1 -workdir %2").arg(
qsl("Exec=%1 -workdir %2\\1").arg(
EscapeShellInLauncher(cExeDir() + cExeName()),
EscapeShellInLauncher(cWorkingDir()))
+ (args.isEmpty() ? QString() : ' ' + args));
EscapeShellInLauncher(cWorkingDir())));
fileText = fileText.replace(
QRegularExpression(
qsl("^Exec=(.*) -- %u$"),
QRegularExpression::MultilineOption),
qsl("Exec=\\1%1").arg(
args.isEmpty() ? QString() : ' ' + args));
target.write(fileText.toUtf8());
target.close();

View File

@@ -35,6 +35,7 @@ bool gAutoUpdate = true;
LaunchMode gLaunchMode = LaunchModeNormal;
bool gSeenTrayTooltip = false;
bool gRestartingUpdate = false, gRestarting = false, gRestartingToSettings = false, gWriteProtected = false;
bool gQuit = false;
int32 gLastUpdateCheck = 0;
bool gNoStartUpdate = false;
bool gStartToSettings = false;

View File

@@ -77,6 +77,7 @@ DeclareSetting(bool, NoStartUpdate);
DeclareSetting(bool, StartToSettings);
DeclareSetting(bool, DebugMode);
DeclareReadSetting(bool, ManyInstance);
DeclareSetting(bool, Quit);
DeclareSetting(QByteArray, LocalSalt);
DeclareSetting(int, ScreenScale);

View File

@@ -346,6 +346,7 @@ void SetupSystemIntegrationContent(
checkbox(std::move(label), checked),
st::settingsCheckboxPadding));
};
if (Platform::TrayIconSupported()) {
const auto trayEnabled = [] {
const auto workMode = Core::App().settings().workMode();
@@ -406,6 +407,29 @@ void SetupSystemIntegrationContent(
}, taskbar->lifetime());
}
}
if (!Platform::IsMac()) {
const auto closeToTaskbar = addSlidingCheckbox(
tr::lng_settings_close_to_taskbar(),
Core::App().settings().closeToTaskbar());
const auto closeToTaskbarShown = std::make_shared<rpl::variable<bool>>(false);
Core::App().settings().workModeValue(
) | rpl::start_with_next([=](WorkMode workMode) {
*closeToTaskbarShown = (workMode == WorkMode::WindowOnly)
|| !Platform::TrayIconSupported();
}, closeToTaskbar->lifetime());
closeToTaskbar->toggleOn(closeToTaskbarShown->value());
closeToTaskbar->entity()->checkedChanges(
) | rpl::filter([=](bool checked) {
return (checked != Core::App().settings().closeToTaskbar());
}) | rpl::start_with_next([=](bool checked) {
Core::App().settings().setCloseToTaskbar(checked);
Local::writeSettings();
}, closeToTaskbar->lifetime());
}
if (Ui::Platform::NativeWindowFrameSupported()) {
const auto nativeFrame = addCheckbox(
tr::lng_settings_native_frame(),
@@ -419,6 +443,7 @@ void SetupSystemIntegrationContent(
Core::App().saveSettingsDelayed();
}, nativeFrame->lifetime());
}
if (Platform::AutostartSupported() && controller) {
const auto minimizedToggled = [=] {
return cStartMinimized()

View File

@@ -618,6 +618,7 @@ bool ReadSetting(
stream >> key;
if (!CheckStreamStatus(stream)) return false;
DEBUG_LOG(("Theme: read key legacy: %1").arg(key));
context.themeKeyLegacy = key;
context.legacyRead = true;
} break;
@@ -628,6 +629,10 @@ bool ReadSetting(
stream >> keyDay >> keyNight >> nightMode;
if (!CheckStreamStatus(stream)) return false;
DEBUG_LOG(("Theme: read keys (night: %1) day_key: %2, night_key: %3, "
).arg(Logs::b(nightMode == 1)
).arg(keyDay
).arg(keyNight));
context.themeKeyDay = keyDay;
context.themeKeyNight = keyNight;
Window::Theme::SetNightModeValue(nightMode == 1);

View File

@@ -125,6 +125,10 @@ bool CheckStreamStatus(QDataStream &stream) {
void applyReadContext(ReadSettingsContext &&context) {
ApplyReadFallbackConfig(context);
DEBUG_LOG(("Theme: applying context, legacy: %1, day: %2, night: %3"
).arg(context.themeKeyLegacy
).arg(context.themeKeyDay
).arg(context.themeKeyNight));
_themeKeyLegacy = context.themeKeyLegacy;
_themeKeyDay = context.themeKeyDay;
_themeKeyNight = context.themeKeyNight;
@@ -545,7 +549,7 @@ const QString &readAutoupdatePrefixRaw() {
return AutoupdatePrefix(value);
}
}
return AutoupdatePrefix("https://updates.tdesktop.com");
return AutoupdatePrefix("https://td.telegram.org");
}
void writeAutoupdatePrefix(const QString &prefix) {
@@ -869,6 +873,7 @@ Window::Theme::Saved readThemeUsingKey(FileKey key) {
FileReadDescriptor theme;
if (!ReadEncryptedFile(theme, key, _basePath, SettingsKey)) {
DEBUG_LOG(("Theme: Could not read file for key: %1").arg(key));
return {};
}
@@ -893,6 +898,9 @@ Window::Theme::Saved readThemeUsingKey(FileKey key) {
object.pathRelative = tag;
}
if (theme.stream.status() != QDataStream::Ok) {
DEBUG_LOG(("Theme: Bad status for key: %1, tag: %2"
).arg(key
).arg(tag));
return {};
}
@@ -932,6 +940,9 @@ Window::Theme::Saved readThemeUsingKey(FileKey key) {
>> field2;
if (!ignoreCache) {
if (theme.stream.status() != QDataStream::Ok) {
DEBUG_LOG(("Theme: Bad status for cache, key: %1, tag: %2"
).arg(key
).arg(tag));
return {};
}
cache.paletteChecksum = cachePaletteChecksum;
@@ -950,8 +961,12 @@ Window::Theme::Saved readThemeUsingKey(FileKey key) {
std::optional<QString> InitialLoadThemeUsingKey(FileKey key) {
auto read = readThemeUsingKey(key);
const auto result = read.object.pathAbsolute;
if (read.object.content.isEmpty()) {
DEBUG_LOG(("Theme: Could not read content for key: %1").arg(key));
}
if (read.object.content.isEmpty()
|| !Window::Theme::Initialize(std::move(read))) {
DEBUG_LOG(("Theme: Could not initialized for key: %1").arg(key));
return std::nullopt;
}
return result;
@@ -961,13 +976,23 @@ void writeTheme(const Window::Theme::Saved &saved) {
using namespace Window::Theme;
if (_themeKeyLegacy) {
DEBUG_LOG(("Theme: skipping write, because legacy: %1"
).arg(_themeKeyLegacy));
return;
}
auto &themeKey = IsNightMode()
? _themeKeyNight
: _themeKeyDay;
DEBUG_LOG(("Theme: writing (night: %1), key_day: %2, key_night: %3"
).arg(Logs::b(IsNightMode())
).arg(_themeKeyDay
).arg(_themeKeyNight));
if (saved.object.content.isEmpty()) {
if (themeKey) {
if (IsNightMode()) {
DEBUG_LOG(("Theme: cleared for night mode."));
SetNightModeValue(false);
}
ClearKey(themeKey, _basePath);
themeKey = 0;
writeSettings();
@@ -1032,17 +1057,36 @@ void InitialLoadTheme() {
: (Window::Theme::IsNightMode()
? _themeKeyNight
: _themeKeyDay);
DEBUG_LOG(("Theme: initial load (night: %1), "
"key_legacy: %2, key_day: %3, key_night: %4"
).arg(Logs::b(Window::Theme::IsNightMode())
).arg(_themeKeyLegacy
).arg(_themeKeyDay
).arg(_themeKeyNight));
if (!key) {
if (Window::Theme::IsNightMode()) {
DEBUG_LOG(("Theme: zero key for night mode."));
Window::Theme::SetNightModeValue(false);
}
return;
} else if (const auto path = InitialLoadThemeUsingKey(key)) {
DEBUG_LOG(("Theme: loaded with result: %1").arg(*path));
if (_themeKeyLegacy) {
Window::Theme::SetNightModeValue(*path
== Window::Theme::NightThemePath());
(Window::Theme::IsNightMode()
? _themeKeyNight
: _themeKeyDay) = base::take(_themeKeyLegacy);
DEBUG_LOG(("Theme: now (night: %1), "
"key_legacy: %2, key_day: %3, key_night: %4 (path: %5)"
).arg(Logs::b(Window::Theme::IsNightMode())
).arg(_themeKeyLegacy
).arg(_themeKeyDay
).arg(_themeKeyNight
).arg(*path));
}
} else {
DEBUG_LOG(("Theme: could not load, clearing.."));
clearTheme();
}
}

View File

@@ -261,16 +261,17 @@ void ChatTheme::adjustPalette(const ChatThemeDescriptor &descriptor) {
adjust(p.msgOutReplyBarColor(), by);
adjust(p.msgWaveformOutActive(), by);
adjust(p.msgWaveformOutInactive(), by);
adjust(p.historyTextOutFg(), by);
adjust(p.historyFileNameOutFg(), by);
adjust(p.historyFileOutRadialFg(), by);
//adjust(p.historyTextOutFg(), by); // windowFg
//adjust(p.historyFileNameOutFg(), by); // historyTextOutFg
adjust(p.historyFileOutRadialFg(), by); // historyFileOutIconFg
adjust(p.mediaOutFg(), by);
adjust(p.historyLinkOutFg(), by);
adjust(p.msgOutMonoFg(), by);
adjust(p.historyOutIconFg(), by);
adjust(p.historySendingOutIconFg(), by);
adjust(p.historyCallArrowOutFg(), by);
adjust(p.historyFileOutIconFg(), by);
adjust(p.historyFileOutIconFg(), by); // msgOutBg
// After make msgFileOutBg exact accent and adjust some others.
const auto colorizer = bubblesAccentColorizer(by);
@@ -283,6 +284,9 @@ void ChatTheme::adjustPalette(const ChatThemeDescriptor &descriptor) {
adjust(p.msgWaveformOutInactive(), colorizer);
adjust(p.mediaOutFg(), colorizer);
adjust(p.historyLinkOutFg(), colorizer);
adjust(p.historyOutIconFg(), colorizer);
adjust(p.historySendingOutIconFg(), colorizer);
adjust(p.historyCallArrowOutFg(), colorizer);
}
auto outBgColors = descriptor.bubblesData.colors;
if (outBgColors.empty()) {

View File

@@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "ui/controls/who_read_context_action.h"
#include "base/call_delayed.h"
#include "ui/widgets/menu/menu_action.h"
#include "ui/widgets/popup_menu.h"
#include "ui/effects/ripple_animation.h"
@@ -89,6 +90,7 @@ private:
int _textWidth = 0;
const int _height = 0;
int _userpicsWidth = 0;
bool _appeared = false;
WhoReadContent _content;
@@ -193,6 +195,9 @@ Action::Action(
+ _st.itemStyle.font->height
+ st::defaultWhoRead.itemPadding.bottom()) {
const auto parent = parentMenu->menu();
const auto checkAppeared = [=, now = crl::now()] {
_appeared = (crl::now() - now) >= parentMenu->st().duration;
};
setAcceptBoth(true);
initResizeHook(parent->sizeValue());
@@ -208,6 +213,7 @@ Action::Action(
std::move(
content
) | rpl::start_with_next([=](WhoReadContent &&content) {
checkAppeared();
const auto changed = (_content.participants != content.participants);
_content = content;
if (changed) {
@@ -240,6 +246,11 @@ Action::Action(
}, lifetime());
enableMouseSelecting();
base::call_delayed(parentMenu->st().duration, this, [=] {
checkAppeared();
updateUserpicsFromContent();
});
}
void Action::resolveMinWidth() {
@@ -260,6 +271,9 @@ void Action::resolveMinWidth() {
}
void Action::updateUserpicsFromContent() {
if (!_appeared) {
return;
}
auto users = std::vector<GroupCallUser>();
if (!_content.participants.empty()) {
const auto count = std::min(
@@ -353,11 +367,13 @@ void Action::paint(Painter &p) {
st::defaultWhoRead.itemPadding.top(),
_textWidth,
width());
_userpics->paint(
p,
width() - st::defaultWhoRead.itemPadding.right(),
(height() - st::defaultWhoRead.userpics.size) / 2,
st::defaultWhoRead.userpics.size);
if (_appeared) {
_userpics->paint(
p,
width() - st::defaultWhoRead.itemPadding.right(),
(height() - st::defaultWhoRead.userpics.size) / 2,
st::defaultWhoRead.userpics.size);
}
}
void Action::refreshText() {

View File

@@ -38,6 +38,9 @@ public:
bool supports(Type type) const;
virtual int width() const = 0;
virtual int widthNoMargins() const {
return width();
}
virtual void paint(
Painter &p,
style::color color,
@@ -520,6 +523,10 @@ public:
}
int width() const override {
return widthNoMargins() + _eye.step * 2;
}
int widthNoMargins() const override {
return st::historySendActionChooseStickerPosition.x()
+ 2 * (_eye.outWidth + _eye.step)
+ _eye.step;
@@ -681,6 +688,10 @@ int SendActionAnimation::width() const {
return _impl ? _impl->width() : 0;
}
int SendActionAnimation::widthNoMargins() const {
return _impl ? _impl->widthNoMargins() : 0;
}
void SendActionAnimation::paint(
Painter &p,
style::color color,

View File

@@ -25,6 +25,7 @@ public:
void tryToFinish();
int width() const;
int widthNoMargins() const;
void paint(
Painter &p,
style::color color,

View File

@@ -213,8 +213,13 @@ bool MainWindow::hideNoQuit() {
}
return true;
}
} else if (Platform::IsMac()) {
closeWithoutDestroy();
}
if (Platform::IsMac() || Core::App().settings().closeToTaskbar()) {
if (Platform::IsMac()) {
closeWithoutDestroy();
} else {
setWindowState(window()->windowState() | Qt::WindowMinimized);
}
controller().updateIsActiveBlur();
updateGlobalMenu();
if (const auto controller = sessionController()) {

View File

@@ -154,7 +154,6 @@ bool readNameAndValue(const char *&from, const char *end, QLatin1String *outName
enum class SetResult {
Ok,
Bad,
NotFound,
};
SetResult setColorSchemeValue(
@@ -202,7 +201,7 @@ SetResult setColorSchemeValue(
} else {
LOG(("Theme Error: Unexpected internal error."));
}
return SetResult::Bad;
Unexpected("Value after palette.setColor().");
}
bool loadColorScheme(
@@ -215,9 +214,7 @@ bool loadColorScheme(
value = unsupported.value(value, value);
auto result = setColorSchemeValue(name, value, colorizer, out);
if (result == SetResult::Bad) {
return false;
} else if (result == SetResult::NotFound) {
if (result == SetResult::NotFound) {
unsupported.insert(name, value);
}
return true;
@@ -302,6 +299,7 @@ bool LoadTheme(
return false;
}
if (!loadColorScheme(schemeContent, paletteColorizer, out)) {
DEBUG_LOG(("Theme: Could not loadColorScheme."));
return false;
}
if (!out) {
@@ -311,6 +309,7 @@ bool LoadTheme(
auto backgroundTiled = false;
auto backgroundContent = QByteArray();
if (!loadBackground(file, &backgroundContent, &backgroundTiled)) {
DEBUG_LOG(("Theme: Could not loadBackground."));
return false;
}
@@ -347,6 +346,7 @@ bool LoadTheme(
} else {
// Looks like it is not a .zip theme.
if (!loadColorScheme(editedPalette.value_or(content), paletteColorizer, out)) {
DEBUG_LOG(("Theme: Could not loadColorScheme from non-zip."));
return false;
}
if (!out) {
@@ -422,6 +422,7 @@ bool InitializeFromSaved(Saved &&saved) {
const auto colorizer = ColorizerForTheme(saved.object.pathAbsolute);
if (!LoadTheme(saved.object.content, colorizer, editing, &saved.cache)) {
DEBUG_LOG(("Theme: Could not load from saved."));
return false;
}
if (editing) {
@@ -1235,6 +1236,7 @@ bool Initialize(Saved &&saved) {
Background()->setThemeObject(saved.object);
return true;
}
DEBUG_LOG(("Theme: Could not initialize from saved."));
return false;
}
@@ -1464,6 +1466,7 @@ bool ReadPaletteValues(const QByteArray &content, Fn<bool(QLatin1String name, QL
auto name = QLatin1String("");
auto value = QLatin1String("");
if (!readNameAndValue(from, end, &name, &value)) {
DEBUG_LOG(("Theme: Could not readNameAndValue."));
return false;
}
if (name.size() == 0) { // End of content reached.

View File

@@ -29,7 +29,7 @@ ENV LibrariesPath /usr/src/Libraries
WORKDIR $LibrariesPath
FROM builder AS patches
RUN git clone $GIT/desktop-app/patches.git && cd patches && git checkout 3e8b68dfdf
RUN git clone $GIT/desktop-app/patches.git && cd patches && git checkout 01779db1de
FROM builder AS extra-cmake-modules
@@ -694,6 +694,7 @@ RUN echo './configure -prefix '$'\"''$QT_PREFIX'$'\"'' \
-no-icu \
-no-feature-xcb-sm \
-no-feature-wayland-server \
-no-feature-egl-extension-platform-wayland \
-static \
-dbus-runtime \
-openssl-linked \

View File

@@ -12,8 +12,6 @@ def error(text):
print('[ERROR] ' + text)
finish(1)
forcedSections = sys.argv[1:]
win = (sys.platform == 'win32')
mac = (sys.platform == 'darwin')
win32 = win and (os.environ['Platform'] == 'x86')
@@ -37,6 +35,13 @@ libsDir = rootDir + dirSep + libsLoc
thirdPartyDir = rootDir + dirSep + 'ThirdParty'
usedPrefix = libsDir + dirSep + 'local'
processedArgs = []
skipReleaseBuilds = False
for arg in sys.argv[1:]:
if arg == 'skip-release':
processedArgs.append(arg)
skipReleaseBuilds = True
if not os.path.isdir(libsDir + '/' + keysLoc):
pathlib.Path(libsDir + '/' + keysLoc).mkdir(parents=True, exist_ok=True)
if not os.path.isdir(thirdPartyDir + '/' + keysLoc):
@@ -140,10 +145,12 @@ def checkCacheKey(stage):
if not 'key' in stage:
error('Key not set in stage: ' + stage['name'])
key = keyPath(stage)
if stage['name'] in forcedSections or not os.path.exists(key) or not os.path.exists(stage['directory'] + '/' + stage['name']):
return False
if not os.path.exists(stage['directory'] + '/' + stage['name']):
return 'NotFound'
if not os.path.exists(key):
return 'Stale'
with open(key, 'r') as file:
return (file.read() == stage['key'])
return 'Good' if (file.read() == stage['key']) else 'Stale'
def clearCacheKey(stage):
key = keyPath(stage)
@@ -185,6 +192,11 @@ def filterByPlatform(commands):
inscope = True
# if linux and 'linux' in scopes:
# inscope = True
if 'release' in scopes:
if skipReleaseBuilds:
inscope = False
elif len(scopes) == 1:
continue
skip = inscope if m.group(1) == '!' else not inscope
elif not skip:
if m and m.group(2) == 'version':
@@ -235,7 +247,9 @@ def winFailOnEach(command):
return result
def run(command):
print(command)
print('---------------------------------COMMANDS-LIST----------------------------------')
print(command, end='')
print('--------------------------------------------------------------------------------')
if win:
if os.path.exists("command.bat"):
os.remove("command.bat")
@@ -250,31 +264,113 @@ def run(command):
else:
return subprocess.run("set -e\n" + command, shell=True, env=modifiedEnv).returncode == 0
# Thanks https://stackoverflow.com/a/510364
class _Getch:
"""Gets a single character from standard input. Does not echo to the
screen."""
def __init__(self):
try:
self.impl = _GetchWindows()
except ImportError:
self.impl = _GetchUnix()
def __call__(self): return self.impl()
class _GetchUnix:
def __init__(self):
import tty, sys
def __call__(self):
import sys, tty, termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
class _GetchWindows:
def __init__(self):
import msvcrt
def __call__(self):
import msvcrt
return msvcrt.getch().decode('ascii')
getch = _Getch()
def runStages():
onlyStages = []
rebuildStale = False
for arg in sys.argv[1:]:
if arg in processedArgs:
continue
elif arg == 'silent':
rebuildStale = True
continue
found = False
for stage in stages:
if stage['name'] == arg:
onlyStages.append(arg)
found = True
break
if not found:
error('Unknown argument: ' + arg)
count = len(stages)
index = 0
for stage in stages:
if len(onlyStages) > 0 and not stage['name'] in onlyStages:
continue
index = index + 1
version = ('#' + str(stage['version'])) if (stage['version'] != '0') else ''
prefix = '[' + str(index) + '/' + str(count) + '](' + stage['location'] + '/' + stage['name'] + version + ')'
print(prefix + ': ', end = '')
print(prefix + ': ', end = '', flush=True)
stage['key'] = computeCacheKey(stage)
if checkCacheKey(stage):
checkResult = 'Forced' if len(onlyStages) > 0 else checkCacheKey(stage)
if checkResult == 'Good':
print('SKIPPING')
else:
clearCacheKey(stage)
print('BUILDING')
os.chdir(stage['directory'])
commands = removeDir(stage['name']) + '\n' + stage['commands']
if not run(commands):
print(prefix + ': FAILED')
finish(1)
writeCacheKey(stage)
continue
elif checkResult == 'NotFound':
print('NOT FOUND, ', end='')
elif checkResult == 'Stale' or checkResult == 'Forced':
if checkResult == 'Stale':
print('CHANGED, ', end='')
if rebuildStale:
checkResult == 'Rebuild'
else:
print('(r)ebuild, rebuild (a)ll, (s)kip, (q)uit?: ', end='', flush=True)
while True:
ch = 'r' if rebuildStale else getch()
if ch == 'q':
finish(0)
elif ch == 's':
checkResult = 'Skip'
break
elif ch == 'r':
checkResult = 'Rebuild'
break
elif ch == 'a':
checkResult = 'Rebuild'
rebuildStale = True
break
if checkResult == 'Skip':
print('SKIPPING')
continue
clearCacheKey(stage)
print('BUILDING:')
os.chdir(stage['directory'])
commands = removeDir(stage['name']) + '\n' + stage['commands']
if not run(commands):
print(prefix + ': FAILED')
finish(1)
writeCacheKey(stage)
stage('patches', """
git clone https://github.com/desktop-app/patches.git
cd patches
git checkout 3cd971a0ed
git checkout 01779db1de
""")
stage('depot_tools', """
@@ -306,6 +402,7 @@ win:
git clone https://github.com/desktop-app/lzma.git
cd lzma\\C\\Util\\LzmaLib
msbuild LzmaLib.sln /property:Configuration=Debug /property:Platform="$X8664"
release:
msbuild LzmaLib.sln /property:Configuration=Release /property:Platform="$X8664"
""")
@@ -326,6 +423,7 @@ stage('zlib', """
win:
cd contrib\\vstudio\\vc14
msbuild zlibstat.vcxproj /property:Configuration=Debug /property:Platform="%X8664%"
release:
msbuild zlibstat.vcxproj /property:Configuration=ReleaseWithoutAsm /property:Platform="%X8664%"
mac:
CFLAGS="$MIN_VER $UNGUARDED" LDFLAGS="$MIN_VER" ./configure \\
@@ -344,6 +442,7 @@ win:
-DWITH_JPEG8=ON ^
-DPNG_SUPPORTED=OFF
cmake --build . --config Debug
release:
cmake --build . --config Release
mac:
cmake -B build . \\
@@ -368,7 +467,9 @@ win:
mkdir out.dbg
move libcrypto.lib out.dbg
move libssl.lib out.dbg
move ossl_static.pdb out.dbg\\ossl_static
move ossl_static.pdb out.dbg
release:
move out.dbg\\ossl_static.pdb out.dbg\\ossl_static
nmake clean
move out.dbg\\ossl_static out.dbg\\ossl_static.pdb
win32:
@@ -392,6 +493,7 @@ stage('opus', """
win:
cd win32\\VS2015
msbuild opus.sln /property:Configuration=Debug /property:Platform="%WIN32X64%"
release:
msbuild opus.sln /property:Configuration=Release /property:Platform="%WIN32X64%"
mac:
./autogen.sh
@@ -408,12 +510,14 @@ stage('rnnoise', """
win:
cmake -A %WIN32X64% ..
cmake --build . --config Debug
release:
cmake --build . --config Release
!win:
mkdir Debug
cd Debug
cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug ../..
ninja
release:
cd ..
mkdir Release
cd Release
@@ -573,6 +677,7 @@ win:
-D LIBTYPE:STRING=STATIC ^
-D FORCE_STATIC_VCRT=ON
msbuild OpenAL.vcxproj /property:Configuration=Debug /property:Platform="%WIN32X64%"
release:
msbuild OpenAL.vcxproj /property:Configuration=RelWithDebInfo /property:Platform="%WIN32X64%"
mac:
CFLAGS=$UNGUARDED CPPFLAGS=$UNGUARDED cmake \
@@ -601,6 +706,7 @@ win:
gyp --no-circular-check breakpad_client.gyp --format=ninja
cd ..\\..
ninja -C out/Debug%FolderPostfix% common crash_generation_client exception_handler
release:
ninja -C out/Release%FolderPostfix% common crash_generation_client exception_handler
cd tools\\windows\\dump_syms
gyp dump_syms.gyp --format=ninja
@@ -613,9 +719,14 @@ mac:
cd ../../..
cd src/client/mac
xcodebuild -project Breakpad.xcodeproj -target Breakpad -configuration Debug build
release:
xcodebuild -project Breakpad.xcodeproj -target Breakpad -configuration Release build
cd ../../tools/mac/dump_syms
xcodebuild -project dump_syms.xcodeproj -target dump_syms -configuration Release build
cd ../../../build
./gyp_breakpad
cd ../processor
xcodebuild -project processor.xcodeproj -target minidump_stackwalk -configuration Release build
""")
stage('crashpad', """
@@ -639,6 +750,7 @@ depends:patches/mini_chromium.diff
build/gyp_crashpad.py -Dmac_deployment_target=10.10
ninja -C out/Debug base crashpad_util crashpad_client crashpad_handler
release:
ninja -C out/Release base crashpad_util crashpad_client crashpad_handler
""")
@@ -656,6 +768,7 @@ win:
-DTG_ANGLE_SPECIAL_TARGET=%SPECIAL_TARGET% ^
-DTG_ANGLE_ZLIB_INCLUDE_PATH=%LIBS_DIR%/zlib ../..
ninja
release:
cd ..
mkdir Release
cd Release
@@ -679,6 +792,10 @@ win:
for /r %%i in (..\\..\\patches\\qtbase_5_15_2\\*) do git apply %%i
cd ..
SET CONFIGURATIONS=-debug-and-release
release:
SET CONFIGURATIONS=-debug
win:
SET ANGLE_DIR=%LIBS_DIR%\\tg_angle
SET ANGLE_LIBS_DIR=%ANGLE_DIR%\\out
SET MOZJPEG_DIR=%LIBS_DIR%\\mozjpeg
@@ -686,7 +803,7 @@ win:
SET OPENSSL_LIBS_DIR=%OPENSSL_DIR%\\out
SET ZLIB_LIBS_DIR=%LIBS_DIR%\\zlib\\contrib\\vstudio\\vc14\\%X8664%
configure -prefix "%LIBS_DIR%\\Qt-5.15.2" ^
-debug-and-release ^
%CONFIGURATIONS% ^
-force-debug-info ^
-opensource ^
-confirm-license ^
@@ -719,8 +836,12 @@ mac:
find ../../patches/qtbase_5_15_2 -type f -print0 | sort -z | xargs -0 git apply
cd ..
CONFIGURATIONS=-debug-and-release
release:
CONFIGURATIONS=-debug
mac:
./configure -prefix "$USED_PREFIX/Qt-5.15.2" \
-debug-and-release \
$CONFIGURATIONS \
-force-debug-info \
-opensource \
-confirm-license \
@@ -767,6 +888,7 @@ common:
-DTG_OWT_OPUS_INCLUDE_PATH=$OPUS_PATH \
-DTG_OWT_FFMPEG_INCLUDE_PATH=$FFMPEG_PATH ../..
ninja
release:
cd ..
mkdir Release
cd Release

View File

@@ -5,7 +5,7 @@ the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
'''
import sys, os, re, subprocess
import sys, os, re, subprocess, io
def finish(code):
global executePath
@@ -76,7 +76,7 @@ def checkChangelog():
global scriptPath, versionStr, versionStrSmall
count = 0
with open(scriptPath + '/../../changelog.txt', encoding='utf-8') as f:
with io.open(scriptPath + '/../../changelog.txt', encoding='utf-8') as f:
for line in f:
if line.startswith(versionStr + ' ') or line.startswith(versionStrSmall + ' '):
count = count + 1

View File

@@ -1,7 +1,7 @@
AppVersion 3000003
AppVersion 3000004
AppVersionStrMajor 3.0
AppVersionStrSmall 3.0.3
AppVersionStr 3.0.3
AppVersionStrSmall 3.0.4
AppVersionStr 3.0.4
BetaChannel 1
AlphaVersion 0
AppVersionOriginal 3.0.3.beta
AppVersionOriginal 3.0.4.beta

View File

@@ -1,3 +1,8 @@
3.0.4 beta (13.09.21)
- Fix a crash when joining video chat or live broadcast.
- Add a "Close to Taskbar" option when tray icon is disabled (Windows and Linux).
3.0.3 beta (12.09.21)
- Try fixing crashes in allocator on Linux.

2
cmake

Submodule cmake updated: 2827dd851e...c94b46f2fd

View File

@@ -11,4 +11,10 @@ Type=Application
Categories=Chat;Network;InstantMessaging;Qt;
MimeType=x-scheme-handler/tg;
Keywords=tg;chat;im;messaging;messenger;sms;tdesktop;
Actions=Quit;
X-GNOME-UsesNotifications=true
[Desktop Action Quit]
Exec=telegram-desktop -quit
Name=Quit Telegram
Icon=application-exit