Merge branch 'telegramdesktop-dev2' into dev

This commit is contained in:
ZavaruKitsu 2023-07-18 11:37:33 +00:00
commit 34ace2862c
45 changed files with 489 additions and 403 deletions

View file

@ -25,7 +25,12 @@ jobs:
submodules: recursive submodules: recursive
- name: First set up. - name: First set up.
run: curl -sSL https://install.python-poetry.org | python3 - run: |
sudo apt update
curl -sSL https://install.python-poetry.org | python3 -
- name: Free up some disk space.
uses: jlumbroso/free-disk-space@76866dbe54312617f00798d1762df7f43def6e5c
- name: Docker image build. - name: Docker image build.
run: | run: |

View file

@ -60,6 +60,9 @@ jobs:
sudo snap run lxd init --auto sudo snap run lxd init --auto
sudo snap run lxd waitready sudo snap run lxd waitready
- name: Free up some disk space.
uses: jlumbroso/free-disk-space@76866dbe54312617f00798d1762df7f43def6e5c
- name: Telegram Desktop snap build. - name: Telegram Desktop snap build.
run: sg lxd -c 'snap run snapcraft -v' run: sg lxd -c 'snap run snapcraft -v'

View file

@ -1774,5 +1774,6 @@ if (LINUX AND DESKTOP_APP_USE_PACKAGED)
install(FILES "Resources/art/icon256.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/256x256/apps" RENAME "telegram.png") install(FILES "Resources/art/icon256.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/256x256/apps" RENAME "telegram.png")
install(FILES "Resources/art/icon512.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/512x512/apps" RENAME "telegram.png") install(FILES "Resources/art/icon512.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/512x512/apps" RENAME "telegram.png")
install(FILES "../lib/xdg/org.ayugram.desktop.desktop" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications") install(FILES "../lib/xdg/org.ayugram.desktop.desktop" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications")
install(FILES "../lib/xdg/org.telegram.desktop.service" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/dbus-1/services")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/org.ayugram.desktop.metainfo.xml" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/metainfo") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/org.ayugram.desktop.metainfo.xml" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/metainfo")
endif() endif()

View file

@ -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.8.3.0" /> Version="4.8.4.0" />
<Properties> <Properties>
<DisplayName>Telegram Desktop</DisplayName> <DisplayName>Telegram Desktop</DisplayName>
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName> <PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>

View file

@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,8,3,0 FILEVERSION 4,8,4,0
PRODUCTVERSION 4,8,3,0 PRODUCTVERSION 4,8,4,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.8.3.0" VALUE "FileVersion", "4.8.4.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2023" VALUE "LegalCopyright", "Copyright (C) 2014-2023"
VALUE "ProductName", "AyuGram Desktop" VALUE "ProductName", "AyuGram Desktop"
VALUE "ProductVersion", "4.8.3.0" VALUE "ProductVersion", "4.8.4.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,8,3,0 FILEVERSION 4,8,4,0
PRODUCTVERSION 4,8,3,0 PRODUCTVERSION 4,8,4,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.8.3.0" VALUE "FileVersion", "4.8.4.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2023" VALUE "LegalCopyright", "Copyright (C) 2014-2023"
VALUE "ProductName", "AyuGram Desktop" VALUE "ProductName", "AyuGram Desktop"
VALUE "ProductVersion", "4.8.3.0" VALUE "ProductVersion", "4.8.4.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -7,12 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "packer.h" #include "packer.h"
#include <QtCore/QtPlugin>
#ifdef Q_OS_MAC
//Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin)
#endif
bool BetaChannel = false; bool BetaChannel = false;
quint64 AlphaVersion = 0; quint64 AlphaVersion = 0;
bool OnlyAlphaKey = false; bool OnlyAlphaKey = false;

View file

@ -46,6 +46,7 @@ string updaterName;
string workDir; string workDir;
string exeName; string exeName;
string exePath; string exePath;
string argv0;
FILE *_logFile = 0; FILE *_logFile = 0;
void openLog() { void openLog() {
@ -388,6 +389,8 @@ int main(int argc, char *argv[]) {
exeName = argv[i]; exeName = argv[i];
} else if (equal(argv[i], "-exepath") && ++i < argc) { } else if (equal(argv[i], "-exepath") && ++i < argc) {
exePath = argv[i]; exePath = argv[i];
} else if (equal(argv[i], "-argv0") && ++i < argc) {
argv0 = argv[i];
} }
} }
if (exeName.empty() || exeName.find('/') != string::npos) { if (exeName.empty() || exeName.find('/') != string::npos) {
@ -461,15 +464,14 @@ int main(int argc, char *argv[]) {
writeLog("Error: short exe name!"); writeLog("Error: short exe name!");
} }
auto fullBinaryPath = exePath + exeName; const auto fullBinaryPath = exePath + exeName;
const auto path = fullBinaryPath.c_str();
auto values = vector<string>(); auto values = vector<string>();
const auto push = [&](string arg) { const auto push = [&](string arg) {
// Force null-terminated .data() call result. // Force null-terminated .data() call result.
values.push_back(arg + char(0)); values.push_back(arg + char(0));
}; };
push(path); push(!argv0.empty() ? argv0 : fullBinaryPath);
push("-noupdate"); push("-noupdate");
if (autostart) push("-autostart"); if (autostart) push("-autostart");
if (debug) push("-debug"); if (debug) push("-debug");
@ -498,7 +500,7 @@ int main(int argc, char *argv[]) {
writeLog("fork() failed!"); writeLog("fork() failed!");
return 1; return 1;
case 0: case 0:
execv(args[0], args.data()); execv(fullBinaryPath.c_str(), args.data());
return 1; return 1;
} }
} }

View file

@ -143,9 +143,8 @@ struct Application::Private {
Settings settings; Settings settings;
}; };
Application::Application(not_null<Launcher*> launcher) Application::Application()
: QObject() : QObject()
, _launcher(launcher)
, _private(std::make_unique<Private>()) , _private(std::make_unique<Private>())
, _platformIntegration(Platform::Integration::Create()) , _platformIntegration(Platform::Integration::Create())
, _batterySaving(std::make_unique<base::BatterySaving>()) , _batterySaving(std::make_unique<base::BatterySaving>())
@ -945,11 +944,11 @@ rpl::producer<> Application::materializeLocalDraftsRequests() const {
void Application::switchDebugMode() { void Application::switchDebugMode() {
if (Logs::DebugEnabled()) { if (Logs::DebugEnabled()) {
Logs::SetDebugEnabled(false); Logs::SetDebugEnabled(false);
_launcher->writeDebugModeSetting(); Launcher::Instance().writeDebugModeSetting();
Restart(); Restart();
} else { } else {
Logs::SetDebugEnabled(true); Logs::SetDebugEnabled(true);
_launcher->writeDebugModeSetting(); Launcher::Instance().writeDebugModeSetting();
DEBUG_LOG(("Debug logs started.")); DEBUG_LOG(("Debug logs started."));
if (_lastActivePrimaryWindow) { if (_lastActivePrimaryWindow) {
_lastActivePrimaryWindow->hideLayer(); _lastActivePrimaryWindow->hideLayer();
@ -957,10 +956,6 @@ void Application::switchDebugMode() {
} }
} }
void Application::writeInstallBetaVersionsSetting() {
_launcher->writeInstallBetaVersionsSetting();
}
Main::Account &Application::activeAccount() const { Main::Account &Application::activeAccount() const {
return _domain->active(); return _domain->active();
} }
@ -1767,10 +1762,8 @@ void Application::startShortcuts() {
void Application::RegisterUrlScheme() { void Application::RegisterUrlScheme() {
base::Platform::RegisterUrlScheme(base::Platform::UrlSchemeDescriptor{ base::Platform::RegisterUrlScheme(base::Platform::UrlSchemeDescriptor{
.executable = (!Platform::IsLinux() || !Core::UpdaterDisabled()) .executable = Platform::ExecutablePathForShortcuts(),
? (cExeDir() + cExeName()) .arguments = Launcher::Instance().customWorkingDir()
: cExeName(),
.arguments = Sandbox::Instance().customWorkingDir()
? u"-workdir \"%1\""_q.arg(cWorkingDir()) ? u"-workdir \"%1\""_q.arg(cWorkingDir())
: QString(), : QString(),
.protocol = u"tg"_q, .protocol = u"tg"_q,

View file

@ -103,7 +103,6 @@ class Instance;
namespace Core { namespace Core {
class Launcher;
struct LocalUrlHandler; struct LocalUrlHandler;
class Settings; class Settings;
class Tray; class Tray;
@ -126,16 +125,13 @@ public:
MTP::ProxyData now; MTP::ProxyData now;
}; };
Application(not_null<Launcher*> launcher); Application();
Application(const Application &other) = delete; Application(const Application &other) = delete;
Application &operator=(const Application &other) = delete; Application &operator=(const Application &other) = delete;
~Application(); ~Application();
void run(); void run();
[[nodiscard]] Launcher &launcher() const {
return *_launcher;
}
[[nodiscard]] Platform::Integration &platformIntegration() const { [[nodiscard]] Platform::Integration &platformIntegration() const {
return *_platformIntegration; return *_platformIntegration;
} }
@ -319,7 +315,6 @@ public:
[[nodiscard]] rpl::producer<> materializeLocalDraftsRequests() const; [[nodiscard]] rpl::producer<> materializeLocalDraftsRequests() const;
void switchDebugMode(); void switchDebugMode();
void writeInstallBetaVersionsSetting();
void preventOrInvoke(Fn<void()> &&callback); void preventOrInvoke(Fn<void()> &&callback);
@ -381,7 +376,6 @@ private:
}; };
InstanceSetter _setter = { this }; InstanceSetter _setter = { this };
const not_null<Launcher*> _launcher;
rpl::event_stream<ProxyChange> _proxyChanges; rpl::event_stream<ProxyChange> _proxyChanges;
// Some fields are just moved from the declaration. // Some fields are just moved from the declaration.

View file

@ -9,7 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/crash_reports.h" #include "core/crash_reports.h"
#include "core/application.h" #include "core/application.h"
#include "core/launcher.h"
#include "core/sandbox.h" #include "core/sandbox.h"
#include "core/update_checker.h" #include "core/update_checker.h"
#include "core/ui_integration.h" #include "core/ui_integration.h"
@ -250,7 +249,6 @@ LastCrashedWindow::UpdaterData::UpdaterData(QWidget *buttonParent)
} }
LastCrashedWindow::LastCrashedWindow( LastCrashedWindow::LastCrashedWindow(
not_null<Core::Launcher*> launcher,
const QByteArray &crashdump, const QByteArray &crashdump,
Fn<void()> launch) Fn<void()> launch)
: _dumpraw(crashdump) : _dumpraw(crashdump)

View file

@ -20,10 +20,6 @@ namespace MTP {
struct ProxyData; struct ProxyData;
} // namespace MTP } // namespace MTP
namespace Core {
class Launcher;
} // namespace Core
class PreLaunchWindow : public QWidget { class PreLaunchWindow : public QWidget {
public: public:
PreLaunchWindow(QString title = QString()); PreLaunchWindow(QString title = QString());
@ -94,10 +90,7 @@ private:
class LastCrashedWindow : public PreLaunchWindow { class LastCrashedWindow : public PreLaunchWindow {
public: public:
LastCrashedWindow( LastCrashedWindow(const QByteArray &crashdump, Fn<void()> launch);
not_null<Core::Launcher*> launcher,
const QByteArray &crashdump,
Fn<void()> launch);
rpl::producer<MTP::ProxyData> proxyChanges() const; rpl::producer<MTP::ProxyData> proxyChanges() const;

View file

@ -313,7 +313,7 @@ QString PlatformString() {
Unexpected("Platform in CrashReports::PlatformString."); Unexpected("Platform in CrashReports::PlatformString.");
} }
void StartCatching(not_null<Core::Launcher*> launcher) { void StartCatching() {
#ifndef DESKTOP_APP_DISABLE_CRASH_REPORTS #ifndef DESKTOP_APP_DISABLE_CRASH_REPORTS
ProcessAnnotations["Binary"] = cExeName().toUtf8().constData(); ProcessAnnotations["Binary"] = cExeName().toUtf8().constData();
ProcessAnnotations["ApiId"] = QString::number(ApiId).toUtf8().constData(); ProcessAnnotations["ApiId"] = QString::number(ApiId).toUtf8().constData();
@ -324,7 +324,7 @@ void StartCatching(not_null<Core::Launcher*> launcher) {
: u"%1"_q).arg(AppVersion)).toUtf8().constData(); : u"%1"_q).arg(AppVersion)).toUtf8().constData();
ProcessAnnotations["Launched"] = QDateTime::currentDateTime().toString("dd.MM.yyyy hh:mm:ss").toUtf8().constData(); ProcessAnnotations["Launched"] = QDateTime::currentDateTime().toString("dd.MM.yyyy hh:mm:ss").toUtf8().constData();
ProcessAnnotations["Platform"] = PlatformString().toUtf8().constData(); ProcessAnnotations["Platform"] = PlatformString().toUtf8().constData();
ProcessAnnotations["UserTag"] = QString::number(launcher->installationTag(), 16).toUtf8().constData(); ProcessAnnotations["UserTag"] = QString::number(Core::Launcher::Instance().installationTag(), 16).toUtf8().constData();
QString dumpspath = cWorkingDir() + u"tdata/dumps"_q; QString dumpspath = cWorkingDir() + u"tdata/dumps"_q;
QDir().mkpath(dumpspath); QDir().mkpath(dumpspath);

View file

@ -7,10 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
namespace Core {
class Launcher;
} // namespace Core
namespace CrashReports { namespace CrashReports {
QString PlatformString(); QString PlatformString();
@ -53,7 +49,7 @@ inline void ClearAnnotationRef(const std::string &key) {
SetAnnotationRef(key, nullptr); SetAnnotationRef(key, nullptr);
} }
void StartCatching(not_null<Core::Launcher*> launcher); void StartCatching();
void FinishCatching(); void FinishCatching();
} // namespace CrashReports } // namespace CrashReports

View file

@ -281,6 +281,8 @@ base::options::toggle OptionFractionalScalingEnabled({
const char kOptionFractionalScalingEnabled[] = "fractional-scaling-enabled"; const char kOptionFractionalScalingEnabled[] = "fractional-scaling-enabled";
const char kOptionFreeType[] = "freetype"; const char kOptionFreeType[] = "freetype";
Launcher *Launcher::InstanceSetter::Instance = nullptr;
std::unique_ptr<Launcher> Launcher::Create(int argc, char *argv[]) { std::unique_ptr<Launcher> Launcher::Create(int argc, char *argv[]) {
return std::make_unique<Platform::Launcher>(argc, argv); return std::make_unique<Platform::Launcher>(argc, argv);
} }
@ -288,15 +290,18 @@ std::unique_ptr<Launcher> Launcher::Create(int argc, char *argv[]) {
Launcher::Launcher(int argc, char *argv[]) Launcher::Launcher(int argc, char *argv[])
: _argc(argc) : _argc(argc)
, _argv(argv) , _argv(argv)
, _arguments(readArguments(_argc, _argv))
, _baseIntegration(_argc, _argv) { , _baseIntegration(_argc, _argv) {
crl::toggle_fp_exceptions(true); crl::toggle_fp_exceptions(true);
base::Integration::Set(&_baseIntegration); base::Integration::Set(&_baseIntegration);
} }
void Launcher::init() { Launcher::~Launcher() {
_arguments = readArguments(_argc, _argv); InstanceSetter::Instance = nullptr;
}
void Launcher::init() {
prepareSettings(); prepareSettings();
initQtMessageLogging(); initQtMessageLogging();
@ -343,7 +348,7 @@ int Launcher::exec() {
} }
// Must be started before Platform is started. // Must be started before Platform is started.
Logs::start(this); Logs::start();
base::options::init(cWorkingDir() + "tdata/experimental_options.json"); base::options::init(cWorkingDir() + "tdata/experimental_options.json");
// Must be called after options are inited. // Must be called after options are inited.
@ -425,8 +430,8 @@ QStringList Launcher::readArguments(int argc, char *argv[]) const {
return result; return result;
} }
QString Launcher::argumentsString() const { const QStringList &Launcher::arguments() const {
return _arguments.join(' '); return _arguments;
} }
bool Launcher::customWorkingDir() const { bool Launcher::customWorkingDir() const {
@ -436,17 +441,6 @@ bool Launcher::customWorkingDir() const {
void Launcher::prepareSettings() { void Launcher::prepareSettings() {
auto path = base::Platform::CurrentExecutablePath(_argc, _argv); auto path = base::Platform::CurrentExecutablePath(_argc, _argv);
LOG(("Executable path before check: %1").arg(path)); LOG(("Executable path before check: %1").arg(path));
if (!path.isEmpty()) {
auto info = QFileInfo(path);
if (info.isSymLink()) {
info = QFileInfo(info.symLinkTarget());
}
if (info.exists()) {
const auto dir = info.absoluteDir().absolutePath();
gExeDir = (dir.endsWith('/') ? dir : (dir + '/'));
gExeName = info.fileName();
}
}
if (cExeName().isEmpty()) { if (cExeName().isEmpty()) {
LOG(("WARNING: Could not compute executable path, some features will be disabled.")); LOG(("WARNING: Could not compute executable path, some features will be disabled."));
} }
@ -558,7 +552,7 @@ void Launcher::processArguments() {
int Launcher::executeApplication() { int Launcher::executeApplication() {
FilteredCommandLineArguments arguments(_argc, _argv); FilteredCommandLineArguments arguments(_argc, _argv);
Sandbox sandbox(this, arguments.count(), arguments.values()); Sandbox sandbox(arguments.count(), arguments.values());
Ui::MainQueueProcessor processor; Ui::MainQueueProcessor processor;
base::ConcurrentTimerEnvironment environment; base::ConcurrentTimerEnvironment environment;
return sandbox.start(); return sandbox.start();

View file

@ -20,9 +20,15 @@ public:
static std::unique_ptr<Launcher> Create(int argc, char *argv[]); static std::unique_ptr<Launcher> Create(int argc, char *argv[]);
static Launcher &Instance() {
Expects(InstanceSetter::Instance != nullptr);
return *InstanceSetter::Instance;
}
virtual int exec(); virtual int exec();
QString argumentsString() const; const QStringList &arguments() const;
bool customWorkingDir() const; bool customWorkingDir() const;
uint64 installationTag() const; uint64 installationTag() const;
@ -32,7 +38,7 @@ public:
void writeDebugModeSetting(); void writeDebugModeSetting();
void writeInstallBetaVersionsSetting(); void writeInstallBetaVersionsSetting();
virtual ~Launcher() = default; virtual ~Launcher();
protected: protected:
enum class UpdaterLaunch { enum class UpdaterLaunch {
@ -61,6 +67,17 @@ private:
int executeApplication(); int executeApplication();
struct InstanceSetter {
InstanceSetter(not_null<Launcher*> instance) {
Expects(Instance == nullptr);
Instance = instance;
}
static Launcher *Instance;
};
InstanceSetter _setter = { this };
int _argc; int _argc;
char **_argv; char **_argv;
QStringList _arguments; QStringList _arguments;

View file

@ -80,13 +80,9 @@ QString _escapeFrom7bit(const QString &str) {
bool Sandbox::QuitOnStartRequested = false; bool Sandbox::QuitOnStartRequested = false;
Sandbox::Sandbox( Sandbox::Sandbox(int &argc, char **argv)
not_null<Core::Launcher*> launcher,
int &argc,
char **argv)
: QApplication(argc, argv) : QApplication(argc, argv)
, _mainThreadId(QThread::currentThreadId()) , _mainThreadId(QThread::currentThreadId()) {
, _launcher(launcher) {
setQuitOnLastWindowClosed(false); setQuitOnLastWindowClosed(false);
} }
@ -109,7 +105,8 @@ int Sandbox::start() {
hashMd5Hex(d.constData(), d.size(), h.data()); hashMd5Hex(d.constData(), d.size(), h.data());
_lockFile = std::make_unique<QLockFile>(QDir::tempPath() + '/' + h + '-' + cGUIDStr()); _lockFile = std::make_unique<QLockFile>(QDir::tempPath() + '/' + h + '-' + cGUIDStr());
_lockFile->setStaleLockTime(0); _lockFile->setStaleLockTime(0);
if (!_lockFile->tryLock() && _launcher->customWorkingDir()) { if (!_lockFile->tryLock()
&& Launcher::Instance().customWorkingDir()) {
// On Windows, QLockFile has problems detecting a stale lock // On Windows, QLockFile has problems detecting a stale lock
// if the machine's hostname contains characters outside the US-ASCII character set. // if the machine's hostname contains characters outside the US-ASCII character set.
if constexpr (Platform::IsWindows()) { if constexpr (Platform::IsWindows()) {
@ -204,7 +201,7 @@ void Sandbox::launchApplication() {
} }
setupScreenScale(); setupScreenScale();
_application = std::make_unique<Application>(_launcher); _application = std::make_unique<Application>();
// Ideally this should go to constructor. // Ideally this should go to constructor.
// But we want to catch all native events and Application installs // But we want to catch all native events and Application installs
@ -405,7 +402,6 @@ void Sandbox::singleInstanceChecked() {
} }
_lastCrashDump = crashdump; _lastCrashDump = crashdump;
auto window = new LastCrashedWindow( auto window = new LastCrashedWindow(
_launcher,
_lastCrashDump, _lastCrashDump,
[=] { launchApplication(); }); [=] { launchApplication(); });
window->proxyChanges( window->proxyChanges(
@ -533,14 +529,6 @@ void Sandbox::refreshGlobalProxy() {
} }
} }
bool Sandbox::customWorkingDir() const {
return _launcher->customWorkingDir();
}
uint64 Sandbox::installationTag() const {
return _launcher->installationTag();
}
void Sandbox::checkForEmptyLoopNestingLevel() { void Sandbox::checkForEmptyLoopNestingLevel() {
// _loopNestingLevel == _eventNestingLevel means that we had a // _loopNestingLevel == _eventNestingLevel means that we had a
// native event in a nesting loop that didn't get a notify() call // native event in a nesting loop that didn't get a notify() call

View file

@ -19,7 +19,6 @@ class QLockFile;
namespace Core { namespace Core {
class Launcher;
class UpdateChecker; class UpdateChecker;
class Application; class Application;
@ -33,7 +32,7 @@ private:
} }
public: public:
Sandbox(not_null<Launcher*> launcher, int &argc, char **argv); Sandbox(int &argc, char **argv);
Sandbox(const Sandbox &other) = delete; Sandbox(const Sandbox &other) = delete;
Sandbox &operator=(const Sandbox &other) = delete; Sandbox &operator=(const Sandbox &other) = delete;
@ -41,8 +40,6 @@ public:
int start(); int start();
void refreshGlobalProxy(); void refreshGlobalProxy();
bool customWorkingDir() const;
uint64 installationTag() const;
void postponeCall(FnMut<void()> &&callable); void postponeCall(FnMut<void()> &&callable);
bool notify(QObject *receiver, QEvent *e) override; bool notify(QObject *receiver, QEvent *e) override;
@ -116,7 +113,6 @@ private:
std::vector<int> _previousLoopNestingLevels; std::vector<int> _previousLoopNestingLevels;
std::vector<PostponedCall> _postponedCalls; std::vector<PostponedCall> _postponedCalls;
not_null<Launcher*> _launcher;
std::unique_ptr<Application> _application; std::unique_ptr<Application> _application;
QString _localServerName, _localSocketReadData; QString _localServerName, _localSocketReadData;

View file

@ -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 = 4008003; constexpr auto AppVersion = 4008004;
constexpr auto AppVersionStr = "4.8.3"; constexpr auto AppVersionStr = "4.8.4";
constexpr auto AppBetaVersion = false; constexpr auto AppBetaVersion = false;
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION; constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;

View file

@ -343,10 +343,10 @@ bool WritingEntry() {
return WritingEntryFlag; return WritingEntryFlag;
} }
void start(not_null<Core::Launcher*> launcher) { void start() {
Assert(LogsData == nullptr); Assert(LogsData == nullptr);
if (!launcher->checkPortableVersionFolder()) { if (!Core::Launcher::Instance().checkPortableVersionFolder()) {
return; return;
} }
@ -414,8 +414,8 @@ void start(not_null<Core::Launcher*> launcher) {
QDir().mkpath(cWorkingDir() + u"tdata"_q); QDir().mkpath(cWorkingDir() + u"tdata"_q);
launcher->workingFolderReady(); Core::Launcher::Instance().workingFolderReady();
CrashReports::StartCatching(launcher); CrashReports::StartCatching();
if (!LogsData->openMain()) { if (!LogsData->openMain()) {
delete LogsData; delete LogsData;
@ -430,7 +430,7 @@ void start(not_null<Core::Launcher*> launcher) {
LOG(("Executable dir: %1, name: %2").arg(cExeDir(), cExeName())); LOG(("Executable dir: %1, name: %2").arg(cExeDir(), cExeName()));
LOG(("Initial working dir: %1").arg(initialWorkingDir)); LOG(("Initial working dir: %1").arg(initialWorkingDir));
LOG(("Working dir: %1").arg(cWorkingDir())); LOG(("Working dir: %1").arg(cWorkingDir()));
LOG(("Command line: %1").arg(launcher->argumentsString())); LOG(("Command line: %1").arg(Core::Launcher::Instance().arguments().join(' ')));
if (!LogsData) { if (!LogsData) {
LOG(("FATAL: Could not open '%1' for writing log!" LOG(("FATAL: Could not open '%1' for writing log!"

View file

@ -11,17 +11,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/assertion.h" #include "base/assertion.h"
#include "base/debug_log.h" #include "base/debug_log.h"
namespace Core {
class Launcher;
} // namespace Core
namespace Logs { namespace Logs {
void SetDebugEnabled(bool enabled); void SetDebugEnabled(bool enabled);
bool DebugEnabled(); bool DebugEnabled();
[[nodiscard]] bool WritingEntry(); [[nodiscard]] bool WritingEntry();
void start(not_null<Core::Launcher*> launcher); void start();
bool started(); bool started();
void finish(); void finish();

View file

@ -65,7 +65,7 @@ QByteArray DnsUserAgent() {
static const auto kResult = QByteArray( static const auto kResult = QByteArray(
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) " "AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/113.0.5672.63 Safari/537.36"); "Chrome/114.0.5735.133 Safari/537.36");
return kResult; return kResult;
} }

View file

@ -8,20 +8,89 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "platform/linux/integration_linux.h" #include "platform/linux/integration_linux.h"
#include "platform/platform_integration.h" #include "platform/platform_integration.h"
#include "base/platform/base_platform_info.h"
#include "base/platform/linux/base_linux_glibmm_helper.h" #include "base/platform/linux/base_linux_glibmm_helper.h"
#include "base/platform/linux/base_linux_xdp_utilities.h" #include "base/platform/linux/base_linux_xdp_utilities.h"
#include "core/sandbox.h"
#include "core/application.h" #include "core/application.h"
#include "core/core_settings.h" #include "core/core_settings.h"
#include "base/random.h" #include "base/random.h"
#include <xdpinhibit/xdpinhibit.hpp> #include <QtCore/QAbstractEventDispatcher>
#include <glibmm.h>
using namespace gi::repository; #include <xdpinhibit/xdpinhibit.hpp>
#include <giomm.h>
typedef GApplication TDesktopApplication;
typedef GApplicationClass TDesktopApplicationClass;
G_DEFINE_TYPE(
TDesktopApplication,
t_desktop_application,
G_TYPE_APPLICATION)
static void t_desktop_application_class_init(
TDesktopApplicationClass *klass) {
const auto application_class = G_APPLICATION_CLASS(klass);
application_class->local_command_line = [](
GApplication *application,
char ***arguments,
int *exit_status) -> gboolean {
return false;
};
application_class->command_line = [](
GApplication *application,
GApplicationCommandLine *cmdline) {
return 0;
};
application_class->before_emit = [](
GApplication *application,
GVariant *platformData) {
if (Platform::IsWayland()) {
static const auto keys = {
"activation-token",
"desktop-startup-id",
};
for (const auto &key : keys) {
const char *token = nullptr;
g_variant_lookup(platformData, key, "&s", &token);
if (token) {
qputenv("XDG_ACTIVATION_TOKEN", token);
break;
}
}
}
};
application_class->add_platform_data = [](
GApplication *application,
GVariantBuilder *builder) {
if (Platform::IsWayland()) {
const auto token = qgetenv("XDG_ACTIVATION_TOKEN");
if (!token.isEmpty()) {
g_variant_builder_add(
builder,
"{sv}",
"activation-token",
g_variant_new_string(token.constData()));
qunsetenv("XDG_ACTIVATION_TOKEN");
}
}
};
}
static void t_desktop_application_init(TDesktopApplication *application) {
}
namespace Platform { namespace Platform {
namespace { namespace {
using namespace gi::repository;
namespace Gio = gi::repository::Gio;
class LinuxIntegration final : public Integration { class LinuxIntegration final : public Integration {
public: public:
LinuxIntegration(); LinuxIntegration();
@ -33,6 +102,10 @@ private:
return _inhibitProxy; return _inhibitProxy;
} }
void initInhibit();
static void LaunchNativeApplication();
XdpInhibit::InhibitProxy _inhibitProxy; XdpInhibit::InhibitProxy _inhibitProxy;
base::Platform::XDP::SettingWatcher _darkModeWatcher; base::Platform::XDP::SettingWatcher _darkModeWatcher;
}; };
@ -61,9 +134,25 @@ LinuxIntegration::LinuxIntegration()
} }
} }
}) { }) {
LOG(("Icon theme: %1").arg(QIcon::themeName()));
LOG(("Fallback icon theme: %1").arg(QIcon::fallbackThemeName()));
if (!QCoreApplication::eventDispatcher()->inherits(
"QEventDispatcherGlib")) {
g_warning("Qt is running without GLib event loop integration, "
"except various functionality to not to work.");
}
} }
void LinuxIntegration::init() { void LinuxIntegration::init() {
initInhibit();
Glib::signal_idle().connect_once([] {
LaunchNativeApplication();
});
}
void LinuxIntegration::initInhibit() {
if (!_inhibitProxy) { if (!_inhibitProxy) {
return; return;
} }
@ -119,6 +208,111 @@ void LinuxIntegration::init() {
nullptr); nullptr);
} }
void LinuxIntegration::LaunchNativeApplication() {
const auto appId = QGuiApplication::desktopFileName()
.chopped(8)
.toStdString();
const auto app = Glib::wrap(
G_APPLICATION(
g_object_new(
t_desktop_application_get_type(),
"application-id",
::Gio::Application::id_is_valid(appId)
? appId.c_str()
: nullptr,
"flags",
G_APPLICATION_HANDLES_OPEN,
nullptr)));
app->signal_startup().connect([=] {
// GNotification
InvokeQueued(qApp, [] {
Core::App().notifications().createManager();
});
QEventLoop().exec();
app->quit();
}, true);
app->signal_activate().connect([] {
Core::Sandbox::Instance().customEnterFromEventLoop([] {
Core::App().activate();
});
}, true);
app->signal_open().connect([](
const ::Gio::Application::type_vec_files &files,
const Glib::ustring &hint) {
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
for (const auto &file : files) {
QFileOpenEvent e(
QUrl(QString::fromStdString(file->get_uri())));
QGuiApplication::sendEvent(qApp, &e);
}
});
}, true);
app->add_action("quit", [] {
Core::Sandbox::Instance().customEnterFromEventLoop([] {
Core::Quit();
});
});
using Window::Notifications::Manager;
using NotificationId = Manager::NotificationId;
using NotificationIdTuple = std::invoke_result_t<
decltype(&NotificationId::toTuple),
NotificationId*
>;
const auto notificationIdVariantType = [] {
try {
return base::Platform::MakeGlibVariant(
NotificationId().toTuple()).get_type();
} catch (...) {
return Glib::VariantType();
}
}();
app->add_action_with_parameter(
"notification-activate",
notificationIdVariantType,
[](const Glib::VariantBase &parameter) {
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
try {
const auto &app = Core::App();
app.notifications().manager().notificationActivated(
NotificationId::FromTuple(
base::Platform::GlibVariantCast<
NotificationIdTuple
>(parameter)));
} catch (...) {
}
});
});
app->add_action_with_parameter(
"notification-mark-as-read",
notificationIdVariantType,
[](const Glib::VariantBase &parameter) {
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
try {
const auto &app = Core::App();
app.notifications().manager().notificationReplied(
NotificationId::FromTuple(
base::Platform::GlibVariantCast<
NotificationIdTuple
>(parameter)),
{});
} catch (...) {
}
});
});
app->run(0, nullptr);
}
} // namespace } // namespace
std::unique_ptr<Integration> CreateIntegration() { std::unique_ptr<Integration> CreateIntegration() {

View file

@ -24,8 +24,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Platform { namespace Platform {
namespace { namespace {
Launcher *LauncherInstance = nullptr;
class Arguments { class Arguments {
public: public:
void push(QByteArray argument) { void push(QByteArray argument) {
@ -48,23 +46,13 @@ private:
} // namespace } // namespace
Launcher::Launcher(int argc, char *argv[]) Launcher::Launcher(int argc, char *argv[])
: Core::Launcher(argc, argv) : Core::Launcher(argc, argv) {
, _arguments(argv, argv + argc) {
Expects(LauncherInstance == nullptr);
LauncherInstance = this;
}
Launcher &Launcher::Instance() {
Expects(LauncherInstance != nullptr);
return *LauncherInstance;
} }
int Launcher::exec() { int Launcher::exec() {
for (auto i = begin(_arguments), e = end(_arguments); i != e; ++i) { for (auto i = arguments().begin(), e = arguments().end(); i != e; ++i) {
if (*i == "-webviewhelper" && std::distance(i, e) > 1) { if (*i == u"-webviewhelper"_q && std::distance(i, e) > 1) {
Webview::WebKitGTK::SetSocketPath(*(i + 1)); Webview::WebKitGTK::SetSocketPath((i + 1)->toStdString());
return Webview::WebKitGTK::Exec(); return Webview::WebKitGTK::Exec();
} }
} }
@ -81,17 +69,23 @@ bool Launcher::launchUpdater(UpdaterLaunch action) {
return false; return false;
} }
const auto binaryPath = (action == UpdaterLaunch::JustRelaunch) const auto justRelaunch = action == UpdaterLaunch::JustRelaunch;
? (cExeDir() + cExeName()) const auto writeProtectedUpdate = action == UpdaterLaunch::PerformUpdate
: (cWriteProtected() && cWriteProtected();
const auto binaryPath = justRelaunch
? QFile::encodeName(cExeDir() + cExeName())
: QFile::encodeName(cWriteProtected()
? (cWorkingDir() + u"tupdates/temp/Updater"_q) ? (cWorkingDir() + u"tupdates/temp/Updater"_q)
: (cExeDir() + u"Updater"_q)); : (cExeDir() + u"Updater"_q));
auto argumentsList = Arguments(); auto argumentsList = Arguments();
if (action == UpdaterLaunch::PerformUpdate && cWriteProtected()) { if (writeProtectedUpdate) {
argumentsList.push("pkexec"); argumentsList.push("pkexec");
} }
argumentsList.push(QFile::encodeName(binaryPath)); argumentsList.push((justRelaunch && !arguments().isEmpty())
? QFile::encodeName(arguments().first())
: binaryPath);
if (cLaunchMode() == LaunchModeAutoStart) { if (cLaunchMode() == LaunchModeAutoStart) {
argumentsList.push("-autostart"); argumentsList.push("-autostart");
@ -107,7 +101,7 @@ bool Launcher::launchUpdater(UpdaterLaunch action) {
argumentsList.push(QFile::encodeName(cDataFile())); argumentsList.push(QFile::encodeName(cDataFile()));
} }
if (action == UpdaterLaunch::JustRelaunch) { if (justRelaunch) {
argumentsList.push("-noupdate"); argumentsList.push("-noupdate");
argumentsList.push("-tosettings"); argumentsList.push("-tosettings");
if (customWorkingDir()) { if (customWorkingDir()) {
@ -121,6 +115,10 @@ bool Launcher::launchUpdater(UpdaterLaunch action) {
argumentsList.push(QFile::encodeName(cExeName())); argumentsList.push(QFile::encodeName(cExeName()));
argumentsList.push("-exepath"); argumentsList.push("-exepath");
argumentsList.push(QFile::encodeName(cExeDir())); argumentsList.push(QFile::encodeName(cExeDir()));
if (!arguments().isEmpty()) {
argumentsList.push("-argv0");
argumentsList.push(QFile::encodeName(arguments().first()));
}
if (customWorkingDir()) { if (customWorkingDir()) {
argumentsList.push("-workdir_custom"); argumentsList.push("-workdir_custom");
} }
@ -137,11 +135,15 @@ bool Launcher::launchUpdater(UpdaterLaunch action) {
pid_t pid = fork(); pid_t pid = fork();
switch (pid) { switch (pid) {
case -1: return false; case -1: return false;
case 0: execvp(args[0], args); return false; case 0:
execvp(
writeProtectedUpdate ? args[0] : binaryPath.constData(),
args);
return false;
} }
// pkexec needs an alive parent // pkexec needs an alive parent
if (action == UpdaterLaunch::PerformUpdate && cWriteProtected()) { if (writeProtectedUpdate) {
waitpid(pid, nullptr, 0); waitpid(pid, nullptr, 0);
// launch new version in the same environment // launch new version in the same environment
return launchUpdater(UpdaterLaunch::JustRelaunch); return launchUpdater(UpdaterLaunch::JustRelaunch);

View file

@ -15,16 +15,12 @@ class Launcher : public Core::Launcher {
public: public:
Launcher(int argc, char *argv[]); Launcher(int argc, char *argv[]);
static Launcher &Instance();
int exec() override; int exec() override;
private: private:
void initHook() override; void initHook() override;
bool launchUpdater(UpdaterLaunch action) override; bool launchUpdater(UpdaterLaunch action) override;
std::vector<std::string> _arguments;
}; };
} // namespace Platform } // namespace Platform

View file

@ -123,12 +123,15 @@ WaylandIntegration::~WaylandIntegration() = default;
WaylandIntegration *WaylandIntegration::Instance() { WaylandIntegration *WaylandIntegration::Instance() {
if (!IsWayland()) return nullptr; if (!IsWayland()) return nullptr;
static std::optional<WaylandIntegration> instance(std::in_place); static std::optional<WaylandIntegration> instance(std::in_place);
base::qt_signal_producer( [[maybe_unused]] static const auto Inited = [] {
QGuiApplication::platformNativeInterface(), base::qt_signal_producer(
&QObject::destroyed QGuiApplication::platformNativeInterface(),
) | rpl::start_with_next([&] { &QObject::destroyed
instance = std::nullopt; ) | rpl::start_with_next([] {
}, instance->_private->lifetime); instance = std::nullopt;
}, instance->_private->lifetime);
return true;
}();
if (!instance) return nullptr; if (!instance) return nullptr;
return &*instance; return &*instance;
} }

View file

@ -8,20 +8,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "platform/linux/specific_linux.h" #include "platform/linux/specific_linux.h"
#include "base/random.h" #include "base/random.h"
#include "base/options.h"
#include "base/platform/base_platform_info.h" #include "base/platform/base_platform_info.h"
#include "base/platform/linux/base_linux_glibmm_helper.h" #include "base/platform/linux/base_linux_glibmm_helper.h"
#include "base/platform/linux/base_linux_dbus_utilities.h" #include "base/platform/linux/base_linux_dbus_utilities.h"
#include "base/platform/linux/base_linux_xdp_utilities.h" #include "base/platform/linux/base_linux_xdp_utilities.h"
#include "platform/linux/linux_desktop_environment.h" #include "platform/linux/linux_desktop_environment.h"
#include "platform/linux/linux_wayland_integration.h" #include "platform/linux/linux_wayland_integration.h"
#include "platform/platform_launcher.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "core/sandbox.h" #include "core/launcher.h"
#include "core/application.h" #include "core/application.h"
#include "core/local_url_handlers.h"
#include "core/core_settings.h" #include "core/core_settings.h"
#include "core/update_checker.h" #include "core/update_checker.h"
#include "window/window_controller.h" #include "window/window_controller.h"
@ -35,7 +32,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtWidgets/QSystemTrayIcon> #include <QtWidgets/QSystemTrayIcon>
#include <QtCore/QStandardPaths> #include <QtCore/QStandardPaths>
#include <QtCore/QProcess> #include <QtCore/QProcess>
#include <QtCore/QAbstractEventDispatcher>
#include <kshell.h> #include <kshell.h>
#include <ksandbox.h> #include <ksandbox.h>
@ -56,57 +52,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
using namespace Platform; using namespace Platform;
using Platform::internal::WaylandIntegration; using Platform::internal::WaylandIntegration;
typedef GApplication TDesktopApplication;
typedef GApplicationClass TDesktopApplicationClass;
G_DEFINE_TYPE(
TDesktopApplication,
t_desktop_application,
G_TYPE_APPLICATION)
static void t_desktop_application_class_init(
TDesktopApplicationClass *klass) {
const auto application_class = G_APPLICATION_CLASS(klass);
application_class->before_emit = [](
GApplication *application,
GVariant *platformData) {
if (Platform::IsWayland()) {
static const auto keys = {
"activation-token",
"desktop-startup-id",
};
for (const auto &key : keys) {
const char *token = nullptr;
g_variant_lookup(platformData, key, "&s", &token);
if (token) {
qputenv("XDG_ACTIVATION_TOKEN", token);
break;
}
}
}
};
application_class->add_platform_data = [](
GApplication *application,
GVariantBuilder *builder) {
if (Platform::IsWayland()) {
const auto token = qgetenv("XDG_ACTIVATION_TOKEN");
if (!token.isEmpty()) {
g_variant_builder_add(
builder,
"{sv}",
"activation-token",
g_variant_new_string(token.constData()));
qunsetenv("XDG_ACTIVATION_TOKEN");
}
}
};
}
static void t_desktop_application_init(TDesktopApplication *application) {
}
namespace Platform { namespace Platform {
namespace { namespace {
@ -138,7 +83,7 @@ bool PortalAutostart(bool start, bool silent) {
std::vector<Glib::ustring> commandline; std::vector<Glib::ustring> commandline;
commandline.push_back(cExeName().toStdString()); commandline.push_back(cExeName().toStdString());
if (Core::Sandbox::Instance().customWorkingDir()) { if (Core::Launcher::Instance().customWorkingDir()) {
commandline.push_back("-workdir"); commandline.push_back("-workdir");
commandline.push_back(cWorkingDir().toStdString()); commandline.push_back(cWorkingDir().toStdString());
} }
@ -232,121 +177,13 @@ bool PortalAutostart(bool start, bool silent) {
return !error; return !error;
} }
void LaunchGApplication() {
Glib::signal_idle().connect_once([] {
const auto appId = QGuiApplication::desktopFileName()
.chopped(8)
.toStdString();
const auto app = Glib::wrap(
G_APPLICATION(
g_object_new(
t_desktop_application_get_type(),
"application-id",
Gio::Application::id_is_valid(appId)
? appId.c_str()
: nullptr,
"flags",
G_APPLICATION_HANDLES_OPEN,
nullptr)));
app->signal_startup().connect([=] {
// GNotification
InvokeQueued(qApp, [] {
Core::App().notifications().createManager();
});
QEventLoop().exec();
app->quit();
}, true);
app->signal_activate().connect([] {
Core::Sandbox::Instance().customEnterFromEventLoop([] {
if (Core::IsAppLaunched()) {
Core::App().activate();
}
});
}, true);
app->signal_open().connect([](
const Gio::Application::type_vec_files &files,
const Glib::ustring &hint) {
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
for (const auto &file : files) {
QFileOpenEvent e(
QUrl(QString::fromStdString(file->get_uri())));
QGuiApplication::sendEvent(qApp, &e);
}
});
}, true);
app->add_action("quit", [] {
Core::Sandbox::Instance().customEnterFromEventLoop([] {
Core::Quit();
});
});
using Window::Notifications::Manager;
using NotificationId = Manager::NotificationId;
using NotificationIdTuple = std::invoke_result_t<
decltype(&NotificationId::toTuple),
NotificationId*
>;
const auto notificationIdVariantType = [] {
try {
return base::Platform::MakeGlibVariant(
NotificationId().toTuple()).get_type();
} catch (...) {
return Glib::VariantType();
}
}();
app->add_action_with_parameter(
"notification-activate",
notificationIdVariantType,
[](const Glib::VariantBase &parameter) {
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
try {
const auto &app = Core::App();
app.notifications().manager().notificationActivated(
NotificationId::FromTuple(
base::Platform::GlibVariantCast<
NotificationIdTuple
>(parameter)));
} catch (...) {
}
});
});
app->add_action_with_parameter(
"notification-mark-as-read",
notificationIdVariantType,
[](const Glib::VariantBase &parameter) {
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
try {
const auto &app = Core::App();
app.notifications().manager().notificationReplied(
NotificationId::FromTuple(
base::Platform::GlibVariantCast<
NotificationIdTuple
>(parameter)),
{});
} catch (...) {
}
});
});
app->run(0, nullptr);
});
}
bool GenerateDesktopFile( bool GenerateDesktopFile(
const QString &targetPath, const QString &targetPath,
const QStringList &args = {}, const QStringList &args = {},
bool onlyMainGroup = false, bool onlyMainGroup = false,
bool silent = false) { bool silent = false) {
if (targetPath.isEmpty() || cExeName().isEmpty()) { const auto executable = ExecutablePathForShortcuts();
if (targetPath.isEmpty() || executable.isEmpty()) {
return false; return false;
} }
@ -388,11 +225,7 @@ bool GenerateDesktopFile(
target->set_string( target->set_string(
group, group,
"TryExec", "TryExec",
KShell::joinArgs({ KShell::joinArgs({ executable }).replace(
!Core::UpdaterDisabled()
? (cExeDir() + cExeName())
: cExeName()
}).replace(
'\\', '\\',
qstr("\\\\")).toStdString()); qstr("\\\\")).toStdString());
} }
@ -400,10 +233,8 @@ bool GenerateDesktopFile(
if (target->has_key(group, "Exec")) { if (target->has_key(group, "Exec")) {
if (group == "Desktop Entry" && !args.isEmpty()) { if (group == "Desktop Entry" && !args.isEmpty()) {
QStringList exec; QStringList exec;
exec.append(!Core::UpdaterDisabled() exec.append(executable);
? (cExeDir() + cExeName()) if (Core::Launcher::Instance().customWorkingDir()) {
: cExeName());
if (Core::Sandbox::Instance().customWorkingDir()) {
exec.append(u"-workdir"_q); exec.append(u"-workdir"_q);
exec.append(cWorkingDir()); exec.append(cWorkingDir());
} }
@ -423,10 +254,8 @@ bool GenerateDesktopFile(
qstr("\\"))); qstr("\\")));
if (!exec.isEmpty()) { if (!exec.isEmpty()) {
exec[0] = !Core::UpdaterDisabled() exec[0] = executable;
? (cExeDir() + cExeName()) if (Core::Launcher::Instance().customWorkingDir()) {
: cExeName();
if (Core::Sandbox::Instance().customWorkingDir()) {
exec.insert(1, u"-workdir"_q); exec.insert(1, u"-workdir"_q);
exec.insert(2, cWorkingDir()); exec.insert(2, cWorkingDir());
} }
@ -479,7 +308,7 @@ bool GenerateDesktopFile(
const auto d = QFile::encodeName(QDir(cWorkingDir()).absolutePath()); const auto d = QFile::encodeName(QDir(cWorkingDir()).absolutePath());
hashMd5Hex(d.constData(), d.size(), md5Hash); hashMd5Hex(d.constData(), d.size(), md5Hash);
if (!Core::Sandbox::Instance().customWorkingDir()) { if (!Core::Launcher::Instance().customWorkingDir()) {
const auto exePath = QFile::encodeName( const auto exePath = QFile::encodeName(
cExeDir() + cExeName()); cExeDir() + cExeName());
hashMd5Hex(exePath.constData(), exePath.size(), md5Hash); hashMd5Hex(exePath.constData(), exePath.size(), md5Hash);
@ -493,6 +322,55 @@ bool GenerateDesktopFile(
return true; return true;
} }
bool GenerateServiceFile(bool silent = false) {
const auto executable = ExecutablePathForShortcuts();
if (executable.isEmpty()) {
return false;
}
const auto targetPath = QStandardPaths::writableLocation(
QStandardPaths::GenericDataLocation) + u"/dbus-1/services/"_q;
const auto targetFile = targetPath
+ QGuiApplication::desktopFileName().chopped(8)
+ u".service"_q;
DEBUG_LOG(("App Info: placing .service file to %1").arg(targetPath));
if (!QDir(targetPath).exists()) QDir().mkpath(targetPath);
const auto target = Glib::KeyFile::create();
constexpr auto group = "D-BUS Service";
target->set_string(
group,
"Name",
QGuiApplication::desktopFileName().chopped(8).toStdString());
target->set_string(
group,
"Exec",
KShell::joinArgs({ executable }).replace(
'\\',
qstr("\\\\")).toStdString());
try {
target->save_to_file(targetFile.toStdString());
} catch (const std::exception &e) {
if (!silent) {
LOG(("App Error: %1").arg(QString::fromStdString(e.what())));
}
return false;
}
QProcess::execute(u"systemctl"_q, {
u"--user"_q,
u"reload"_q,
u"dbus"_q,
});
return true;
}
void InstallLauncher() { void InstallLauncher() {
static const auto DisabledByEnv = !qEnvironmentVariableIsEmpty( static const auto DisabledByEnv = !qEnvironmentVariableIsEmpty(
"DESKTOPINTEGRATION"); "DESKTOPINTEGRATION");
@ -506,6 +384,7 @@ void InstallLauncher() {
QStandardPaths::ApplicationsLocation) + '/'; QStandardPaths::ApplicationsLocation) + '/';
GenerateDesktopFile(applicationsPath); GenerateDesktopFile(applicationsPath);
GenerateServiceFile();
const auto icons = QStandardPaths::writableLocation( const auto icons = QStandardPaths::writableLocation(
QStandardPaths::GenericDataLocation) + u"/icons/"_q; QStandardPaths::GenericDataLocation) + u"/icons/"_q;
@ -615,6 +494,20 @@ bool SkipTaskbarSupported() {
return false; return false;
} }
QString ExecutablePathForShortcuts() {
if (Core::UpdaterDisabled()) {
const auto &arguments = Core::Launcher::Instance().arguments();
if (!arguments.isEmpty()) {
const auto result = QFileInfo(arguments.first()).fileName();
if (!result.isEmpty()) {
return result;
}
}
return cExeName();
}
return cExeDir() + cExeName();
}
} // namespace Platform } // namespace Platform
QString psAppDataPath() { QString psAppDataPath() {
@ -676,7 +569,7 @@ void start() {
if (!Core::UpdaterDisabled()) { if (!Core::UpdaterDisabled()) {
QByteArray md5Hash(h); QByteArray md5Hash(h);
if (!Launcher::Instance().customWorkingDir()) { if (!Core::Launcher::Instance().customWorkingDir()) {
const auto exePath = QFile::encodeName( const auto exePath = QFile::encodeName(
cExeDir() + cExeName()); cExeDir() + cExeName());
@ -726,6 +619,8 @@ void start() {
h, h,
cGUIDStr(), cGUIDStr(),
u"%1"_q).toStdString()); u"%1"_q).toStdString());
InstallLauncher();
} }
void finish() { void finish() {
@ -796,17 +691,6 @@ QImage DefaultApplicationIcon() {
namespace ThirdParty { namespace ThirdParty {
void start() { void start() {
LOG(("Icon theme: %1").arg(QIcon::themeName()));
LOG(("Fallback icon theme: %1").arg(QIcon::fallbackThemeName()));
if (!QCoreApplication::eventDispatcher()->inherits(
"QEventDispatcherGlib")) {
g_warning("Qt is running without GLib event loop integration, "
"except various functionality to not to work.");
}
InstallLauncher();
LaunchGApplication();
} }
void finish() { void finish() {

View file

@ -40,6 +40,10 @@ inline uint64 ActivationWindowId(not_null<QWidget*> window) {
inline void ActivateOtherProcess(uint64 processId, uint64 windowId) { inline void ActivateOtherProcess(uint64 processId, uint64 windowId) {
} }
inline QString ExecutablePathForShortcuts() {
return cExeDir() + cExeName();
}
namespace ThirdParty { namespace ThirdParty {
inline void start() { inline void start() {

View file

@ -46,10 +46,9 @@ bool TrayIconSupported();
bool SkipTaskbarSupported(); bool SkipTaskbarSupported();
void WriteCrashDumpDetails(); void WriteCrashDumpDetails();
void NewVersionLaunched(int oldVersion); void NewVersionLaunched(int oldVersion);
[[nodiscard]] QImage DefaultApplicationIcon(); [[nodiscard]] QImage DefaultApplicationIcon();
[[nodiscard]] bool PreventsQuit(Core::QuitReason reason); [[nodiscard]] bool PreventsQuit(Core::QuitReason reason);
[[nodiscard]] QString ExecutablePathForShortcuts();
#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0) #if QT_VERSION < QT_VERSION_CHECK(6, 5, 0)
[[nodiscard]] std::optional<bool> IsDarkMode(); [[nodiscard]] std::optional<bool> IsDarkMode();

View file

@ -42,6 +42,10 @@ void SetWindowPriority(not_null<QWidget*> window, uint32 priority);
// Activate window with windowId (if found) or the largest priority. // Activate window with windowId (if found) or the largest priority.
void ActivateOtherProcess(uint64 processId, uint64 windowId); void ActivateOtherProcess(uint64 processId, uint64 windowId);
inline QString ExecutablePathForShortcuts() {
return cExeDir() + cExeName();
}
namespace ThirdParty { namespace ThirdParty {
void start(); void start();

View file

@ -18,7 +18,7 @@ QByteArray gAlphaPrivateKey;
bool gManyInstance = false; bool gManyInstance = false;
QString gKeyFile; QString gKeyFile;
QString gWorkingDir, gExeDir, gExeName; QString gWorkingDir;
QStringList gSendPaths; QStringList gSendPaths;
QString gStartUrl; QString gStartUrl;

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "base/integration.h"
#include "ui/style/style_core.h" #include "ui/style/style_core.h"
#define DeclareReadSetting(Type, Name) extern Type g##Name; \ #define DeclareReadSetting(Type, Name) extern Type g##Name; \
@ -56,11 +57,15 @@ inline void cForceWorkingDir(const QString &newDir) {
} }
} }
DeclareReadSetting(QString, ExeName); inline QString cExeName() {
DeclareReadSetting(QString, ExeDir); return base::Integration::Instance().executableName();
}
inline QString cExeDir() {
return base::Integration::Instance().executableDir();
}
DeclareSetting(QString, DialogLastPath); DeclareSetting(QString, DialogLastPath);
DeclareSetting(QString, DialogHelperPath); DeclareSetting(QString, DialogHelperPath);
inline const QString &cDialogHelperPathFinal() { inline QString cDialogHelperPathFinal() {
return cDialogHelperPath().isEmpty() ? cExeDir() : cDialogHelperPath(); return cDialogHelperPath().isEmpty() ? cExeDir() : cDialogHelperPath();
} }

View file

@ -32,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "core/update_checker.h" #include "core/update_checker.h"
#include "core/launcher.h"
#include "core/application.h" #include "core/application.h"
#include "tray.h" #include "tray.h"
#include "storage/localstorage.h" #include "storage/localstorage.h"
@ -224,7 +225,7 @@ void SetupUpdate(
return (toggled != cInstallBetaVersion()); return (toggled != cInstallBetaVersion());
}) | rpl::start_with_next([=](bool toggled) { }) | rpl::start_with_next([=](bool toggled) {
cSetInstallBetaVersion(toggled); cSetInstallBetaVersion(toggled);
Core::App().writeInstallBetaVersionsSetting(); Core::Launcher::Instance().writeInstallBetaVersionsSetting();
Core::UpdateChecker checker; Core::UpdateChecker checker;
checker.stop(); checker.stop();

View file

@ -28,7 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "storage/storage_media_prepare.h" #include "storage/storage_media_prepare.h"
#include "storage/localimageloader.h" #include "storage/localimageloader.h"
#include "core/sandbox.h" #include "core/launcher.h"
#include "core/application.h" #include "core/application.h"
#include "core/core_settings.h" #include "core/core_settings.h"
#include "main/main_session.h" #include "main/main_session.h"
@ -138,7 +138,7 @@ void EditInfoBox::setInnerFocus() {
} }
uint32 OccupationTag() { uint32 OccupationTag() {
return uint32(Core::Sandbox::Instance().installationTag() & 0xFFFFFFFF); return uint32(Core::Launcher::Instance().installationTag() & 0xFFFFFFFF);
} }
QString NormalizeName(QString name) { QString NormalizeName(QString name) {
@ -268,7 +268,7 @@ Helper::Helper(not_null<Main::Session*> session)
}).fail([=] { }).fail([=] {
setSupportName( setSupportName(
u"[rand^"_q u"[rand^"_q
+ QString::number(Core::Sandbox::Instance().installationTag()) + QString::number(Core::Launcher::Instance().installationTag())
+ ']'); + ']');
}).send(); }).send();
} }

View file

@ -7,7 +7,7 @@
{%- set OPENSSL_PREFIX = "/usr/local/desktop-app/openssl-1.1.1" -%} {%- set OPENSSL_PREFIX = "/usr/local/desktop-app/openssl-1.1.1" -%}
{%- set CMAKE_VER = "3.26.3" -%} {%- set CMAKE_VER = "3.26.3" -%}
{%- set CMAKE_FILE = "cmake-" ~ CMAKE_VER ~ "-Linux-x86_64.sh" -%} {%- set CMAKE_FILE = "cmake-" ~ CMAKE_VER ~ "-Linux-x86_64.sh" -%}
{%- set CFLAGS_DEBUG = "-g -pipe -fPIC -fstack-protector-all -fstack-clash-protection -D_GLIBCXX_ASSERTIONS" -%} {%- set CFLAGS_DEBUG = "-g -pipe -fPIC -fstack-protector-all -fstack-clash-protection -fcf-protection -D_GLIBCXX_ASSERTIONS" -%}
{%- set CFLAGS_LTO = "-flto=auto -ffat-lto-objects" -%} {%- set CFLAGS_LTO = "-flto=auto -ffat-lto-objects" -%}
{%- set LibrariesPath = "/usr/src/Libraries" -%} {%- set LibrariesPath = "/usr/src/Libraries" -%}
@ -52,14 +52,14 @@ FROM builder-base AS builder
ENV AR gcc-ar ENV AR gcc-ar
ENV RANLIB gcc-ranlib ENV RANLIB gcc-ranlib
ENV NM gcc-nm ENV NM gcc-nm
ENV CFLAGS {% if DEBUG %}-g{% endif %} -O3 {% if LTO %}{{ CFLAGS_LTO }}{% endif %} -pipe -fPIC -fstack-protector-all -fstack-clash-protection -DNDEBUG -D_FORTIFY_SOURCE=2 -D_GLIBCXX_ASSERTIONS ENV CFLAGS {% if DEBUG %}-g{% endif %} -O3 {% if LTO %}{{ CFLAGS_LTO }}{% endif %} -pipe -fPIC -fstack-protector-all -fstack-clash-protection -fcf-protection -DNDEBUG -D_FORTIFY_SOURCE=2 -D_GLIBCXX_ASSERTIONS
ENV CXXFLAGS $CFLAGS ENV CXXFLAGS $CFLAGS
FROM builder AS patches 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 a1b912c90eaab470ef283622a8f890ee6264dae7 \ && git fetch --depth=1 origin 963f5b0c2a57f7e90239e64c9e14ed5f043e637e \
&& git reset --hard FETCH_HEAD \ && git reset --hard FETCH_HEAD \
&& rm -rf .git && rm -rf .git
@ -729,10 +729,6 @@ RUN git clone -b {{ QT_TAG }} --depth=1 https://code.qt.io/qt/qt5.git qt_{{ QT }
&& git submodule update --init --recursive --depth=1 qtbase qtdeclarative qtwayland qtimageformats qtsvg qtshadertools \ && git submodule update --init --recursive --depth=1 qtbase qtdeclarative qtwayland qtimageformats qtsvg qtshadertools \
&& cd qtbase \ && cd qtbase \
&& find ../../patches/qtbase_{{ QT }} -type f -print0 | sort -z | xargs -r0 git apply \ && find ../../patches/qtbase_{{ QT }} -type f -print0 | sort -z | xargs -r0 git apply \
&& cd ../qtdeclarative \
&& sed -i '/add_subdirectory(quickcontrols)/d' src/CMakeLists.txt \
&& sed -i '/add_subdirectory(quickdialogs)/d' src/CMakeLists.txt \
&& sed -i '/add_subdirectory(quicknativestyle)/d' src/CMakeLists.txt \
&& cd .. \ && cd .. \
&& ./configure -prefix "{{ QT_PREFIX }}" \ && ./configure -prefix "{{ QT_PREFIX }}" \
CMAKE_BUILD_TYPE=None \ CMAKE_BUILD_TYPE=None \

View file

@ -1,4 +1,5 @@
#!/bin/bash #!/bin/bash
set -e
cd Telegram cd Telegram
./configure.sh "$@" ./configure.sh "$@"

View file

@ -3,10 +3,13 @@ from os import environ
from os.path import dirname from os.path import dirname
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
def checkEnv(envName, defaultValue):
return bool(len(environ[envName])) if envName in environ else defaultValue
def main(): def main():
print(Environment(loader=FileSystemLoader(dirname(__file__))).get_template("Dockerfile").render( print(Environment(loader=FileSystemLoader(dirname(__file__))).get_template("Dockerfile").render(
DEBUG=bool(len(environ["DEBUG"])) if "DEBUG" in environ else True, DEBUG=checkEnv("DEBUG", True),
LTO=bool(len(environ["LTO"])) if "LTO" in environ else True, LTO=checkEnv("LTO", True),
)) ))
if __name__ == '__main__': if __name__ == '__main__':

View file

@ -673,7 +673,7 @@ mac:
stage('dav1d', """ stage('dav1d', """
win: win:
git clone -b 1.0.0 --depth 1 https://code.videolan.org/videolan/dav1d.git git clone -b 1.2.1 --depth 1 https://code.videolan.org/videolan/dav1d.git
cd dav1d cd dav1d
depends:python/Scripts/activate.bat depends:python/Scripts/activate.bat
%THIRDPARTY_DIR%\\python\\Scripts\\activate.bat %THIRDPARTY_DIR%\\python\\Scripts\\activate.bat
@ -710,7 +710,7 @@ release:
stage('libde265', """ stage('libde265', """
win: win:
git clone --depth 1 -b v1.0.11 https://github.com/strukturag/libde265.git git clone --depth 1 -b v1.0.12 https://github.com/strukturag/libde265.git
cd libde265 cd libde265
cmake . ^ cmake . ^
-A %WIN32X64% ^ -A %WIN32X64% ^
@ -734,7 +734,7 @@ release:
stage('libheif', """ stage('libheif', """
win: win:
git clone --depth 1 -b v1.15.1 https://github.com/strukturag/libheif.git git clone --depth 1 -b v1.16.2 https://github.com/strukturag/libheif.git
cd libheif cd libheif
%THIRDPARTY_DIR%\\msys64\\usr\\bin\\sed.exe -i 's/LIBHEIF_EXPORTS/LIBDE265_STATIC_BUILD/g' libheif/CMakeLists.txt %THIRDPARTY_DIR%\\msys64\\usr\\bin\\sed.exe -i 's/LIBHEIF_EXPORTS/LIBDE265_STATIC_BUILD/g' libheif/CMakeLists.txt
%THIRDPARTY_DIR%\\msys64\\usr\\bin\\sed.exe -i 's/HAVE_VISIBILITY/LIBHEIF_STATIC_BUILD/g' libheif/CMakeLists.txt %THIRDPARTY_DIR%\\msys64\\usr\\bin\\sed.exe -i 's/HAVE_VISIBILITY/LIBHEIF_STATIC_BUILD/g' libheif/CMakeLists.txt
@ -762,7 +762,7 @@ release:
stage('libjxl', """ stage('libjxl', """
win: win:
git clone -b v0.8.1 --depth 1 --recursive --shallow-submodules https://github.com/libjxl/libjxl.git git clone -b v0.8.2 --depth 1 --recursive --shallow-submodules https://github.com/libjxl/libjxl.git
cd libjxl cd libjxl
cmake . ^ cmake . ^
-A %WIN32X64% ^ -A %WIN32X64% ^

View file

@ -63,20 +63,11 @@ def getOutput(command):
sys.exit(1) sys.exit(1)
return output.decode('utf-8') return output.decode('utf-8')
def prepareSources(): def invoke(command):
workpath = os.getcwd() return call(command.split()) == 0
os.chdir('../..')
rootpath = os.getcwd() def appendSubmodules(appendTo, root, rootRevision):
finalpath = rootpath + '/out/Release/sources.tar' startpath = os.getcwd()
if os.path.exists(finalpath):
os.remove(finalpath)
if os.path.exists(finalpath + '.gz'):
os.remove(finalpath + '.gz')
tmppath = rootpath + '/out/Release/tmp.tar'
print('Preparing source tarball...')
if (call(('git archive --prefix=tdesktop-' + version + '-full/ -o ' + finalpath + ' v' + version).split()) != 0):
os.remove(finalpath)
sys.exit(1)
lines = getOutput('git submodule foreach').split('\n') lines = getOutput('git submodule foreach').split('\n')
for line in lines: for line in lines:
if len(line) == 0: if len(line) == 0:
@ -84,23 +75,48 @@ def prepareSources():
match = re.match(r"^Entering '([^']+)'$", line) match = re.match(r"^Entering '([^']+)'$", line)
if not match: if not match:
print('Bad line: ' + line) print('Bad line: ' + line)
sys.exit(1) return False
path = match.group(1) path = match.group(1)
revision = getOutput('git rev-parse v' + version + ':' + path).split('\n')[0] subroot = root + '/' + path
revision = getOutput('git rev-parse ' + rootRevision + ':' + path).split('\n')[0]
print('Adding submodule ' + path + '...') print('Adding submodule ' + path + '...')
os.chdir(path) os.chdir(path)
if (call(('git archive --prefix=tdesktop-' + version + '-full/' + path + '/ ' + revision + ' -o ' + tmppath).split()) != 0): tmppath = appendTo + '_tmp'
os.remove(finalpath) if not invoke('git archive --prefix=' + subroot + '/ ' + revision + ' -o ' + tmppath + '.tar'):
os.remove(tmppath) os.remove(appendTo + '.tar')
sys.exit(1) os.remove(tmppath + '.tar')
if (call(('gtar --concatenate --file=' + finalpath + ' ' + tmppath).split()) != 0): return False
os.remove(finalpath) if not appendSubmodules(tmppath, subroot, revision):
os.remove(tmppath) return False
sys.exit(1) if not invoke('gtar --concatenate --file=' + appendTo + '.tar ' + tmppath + '.tar'):
os.remove(tmppath) os.remove(appendTo + '.tar')
os.chdir(rootpath) os.remove(tmppath + '.tar')
return False
os.remove(tmppath + '.tar')
os.chdir(startpath)
return True
def prepareSources():
workpath = os.getcwd()
os.chdir('../..')
rootpath = os.getcwd()
finalpart = rootpath + '/out/Release/sources'
finalpath = finalpart + '.tar'
if os.path.exists(finalpath):
os.remove(finalpath)
if os.path.exists(finalpath + '.gz'):
os.remove(finalpath + '.gz')
tmppath = rootpath + '/out/Release/tmp.tar'
print('Preparing source tarball...')
revision = 'v' + version
targetRoot = 'tdesktop-' + version + '-full';
if not invoke('git archive --prefix=' + targetRoot + '/ -o ' + finalpath + ' ' + revision):
os.remove(finalpath)
sys.exit(1)
if not appendSubmodules(finalpart, targetRoot, revision):
sys.exit(1)
print('Compressing...') print('Compressing...')
if (call(('gzip -9 ' + finalpath).split()) != 0): if not invoke('gzip -9 ' + finalpath):
os.remove(finalpath) os.remove(finalpath)
sys.exit(1) sys.exit(1)
os.chdir(workpath) os.chdir(workpath)
@ -254,12 +270,12 @@ if r.status_code == 404:
checkResponseCode(r, 201) checkResponseCode(r, 201)
tagname = 'v' + version tagname = 'v' + version
call("git fetch origin".split()) invoke("git fetch origin")
if stable == 1: if stable == 1:
call("git push launchpad {}:master".format(tagname).split()) invoke("git push launchpad {}:master".format(tagname))
else: else:
call("git push launchpad {}:beta".format(tagname).split()) invoke("git push launchpad {}:beta".format(tagname))
call("git push --tags launchpad".split()) invoke("git push --tags launchpad")
r = requests.get(url + 'repos/telegramdesktop/tdesktop/releases/tags/v' + version) r = requests.get(url + 'repos/telegramdesktop/tdesktop/releases/tags/v' + version)
checkResponseCode(r, 200) checkResponseCode(r, 200)
@ -307,9 +323,8 @@ for file in files:
checkResponseCode(r, 201) checkResponseCode(r, 201)
print('Success! Removing.') print('Success! Removing.')
return_code = call(["rm", file_path]) if not invoke('rm ' + file_path):
if return_code != 0: print('Bad rm return code :(')
print('Bad rm code: ' + str(return_code))
sys.exit(1) sys.exit(1)
sys.exit() sys.exit()

View file

@ -1,7 +1,7 @@
AppVersion 4008003 AppVersion 4008004
AppVersionStrMajor 4.8 AppVersionStrMajor 4.8
AppVersionStrSmall 4.8.3 AppVersionStrSmall 4.8.4
AppVersionStr 4.8.3 AppVersionStr 4.8.4
BetaChannel 0 BetaChannel 0
AlphaVersion 0 AlphaVersion 0
AppVersionOriginal 4.8.3 AppVersionOriginal 4.8.4

View file

@ -1,3 +1,7 @@
4.8.4 (13.06.23)
- Fix opening links on Linux.
4.8.3 (31.05.23) 4.8.3 (31.05.23)
- Fix main window focus from notifications with disabled animations. - Fix main window focus from notifications with disabled animations.

View file

@ -13,7 +13,7 @@ You will require **api_id** and **api_hash** to access the Telegram API servers.
Go to ***BuildPath*** and run Go to ***BuildPath*** and run
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew install git automake cmake wget pkg-config gnu-tar brew install git automake cmake wget pkg-config gnu-tar ninja
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

View file

@ -11,6 +11,7 @@ Categories=Chat;Network;InstantMessaging;Qt;
MimeType=x-scheme-handler/tg; MimeType=x-scheme-handler/tg;
Keywords=tg;chat;im;messaging;messenger;sms;tdesktop; Keywords=tg;chat;im;messaging;messenger;sms;tdesktop;
Actions=quit; Actions=quit;
DBusActivatable=true
SingleMainWindow=true SingleMainWindow=true
X-GNOME-UsesNotifications=true X-GNOME-UsesNotifications=true
X-GNOME-SingleWindow=true X-GNOME-SingleWindow=true

View file

@ -0,0 +1,3 @@
[D-BUS Service]
Name=org.telegram.desktop
Exec=telegram-desktop

View file

@ -28,9 +28,11 @@ apps:
- camera - camera
- desktop - desktop
- desktop-legacy - desktop-legacy
- gsettings
- hardware-observe - hardware-observe
- home - home
- network - network
- network-bind
- network-status - network-status
- opengl - opengl
- removable-media - removable-media
@ -52,7 +54,6 @@ plugs:
mount-host-font-cache: false mount-host-font-cache: false
# Support for common GTK themes # Support for common GTK themes
# https://forum.snapcraft.io/t/how-to-use-the-system-gtk-theme-via-the-gtk-common-themes-snap/6235 # https://forum.snapcraft.io/t/how-to-use-the-system-gtk-theme-via-the-gtk-common-themes-snap/6235
gsettings:
gtk-3-themes: gtk-3-themes:
interface: content interface: content
target: $SNAP/data-dir/themes target: $SNAP/data-dir/themes