Compare commits

..

33 Commits

Author SHA1 Message Date
John Preston
ef5e39f680 Beta version 4.4.3.
- Support for anonymous numbers from the Fragment.com platform.
- Fix a crash in own profile photo updating.
- Bug fixes and other minor improvements.
2022-12-29 15:03:34 +04:00
John Preston
27228480a8 Reorder privacy buttons like on Android. 2022-12-29 14:57:27 +04:00
John Preston
eebe1f4c11 Revert "Move Blocked users to Privacy in Settings."
This reverts commit 1acfe441e1.
2022-12-29 14:44:45 +04:00
Ilya Fedin
5d5e4cbdff Add information about required and supported peripheral to XDG metadata 2022-12-29 14:43:23 +04:00
Ilya Fedin
7e9920b5ea Set contributing URL in XDG metadata
Currently the button opens the official website instead
2022-12-29 14:43:23 +04:00
23rd
297fd0f0c8 Moved regexp for excluding digits to single place. 2022-12-29 13:36:28 +03:00
Ilya Fedin
0eec470387 Hide default download folder option if it's not available 2022-12-29 14:18:08 +04:00
John Preston
7a64725045 Improve fragment phone number description 2022-12-29 14:06:52 +04:00
John Preston
1acfe441e1 Move Blocked users to Privacy in Settings. 2022-12-29 14:06:52 +04:00
John Preston
80e932a083 Fix group call userpics on Retina. 2022-12-29 14:06:52 +04:00
bovirus
698d32db57 Update Inno Setup script
Add Copyright message with copyright autor styarting and ending yaer (current year) copyright
Add AppverName (app name and vesrion on top left in main window)
2022-12-29 13:41:37 +04:00
John Preston
2ee7cc784f Fix initial TTL after group creation. 2022-12-29 12:59:53 +04:00
John Preston
071411c8b9 Fix fragment button in Intro process. 2022-12-29 12:59:53 +04:00
23rd
43671e2b47 Fixed width of button in passport VerifyBox. 2022-12-29 11:48:53 +03:00
Ilya Fedin
1666683dbb Fix various line length in notifications_manager_linux 2022-12-29 12:30:17 +04:00
Ilya Fedin
c134861cd9 Have notification subtitle in title on Linux when body-markup is not supported
This makes it look way better
2022-12-29 12:30:17 +04:00
John Preston
a1a5ef9d39 Fix possible crash on force-logout from the server.. 2022-12-29 12:21:21 +04:00
John Preston
7e98e9ecf2 Fix uploading new group / account photo. 2022-12-29 12:16:49 +04:00
John Preston
cad6faa790 Fix connection re-init in case of CONNECTION_NOT_INITED. 2022-12-29 12:16:49 +04:00
John Preston
13ad39dfc2 Fix possible crash in logout. 2022-12-29 12:16:49 +04:00
23rd
aa8ca28f77 Added description to context menu for anonymous phone numbers. 2022-12-29 11:11:08 +03:00
23rd
d424a8b039 Added handler of urls for login. 2022-12-29 11:11:08 +03:00
23rd
9896855789 Added button for opening custom url to passport VerifyBox. 2022-12-29 11:11:08 +03:00
23rd
613d4932ca Added button for opening custom url to Ui::ConfirmPhoneBox. 2022-12-29 11:11:08 +03:00
23rd
44f79b8331 Added button for opening custom url to ChangePhone::EnterCode box. 2022-12-29 11:11:08 +03:00
23rd
aa1117a714 Added ability to sing up and sing in with anonymous numbers. 2022-12-29 11:11:08 +03:00
23rd
8748265b00 Added support of multiple phone pattern groups. 2022-12-29 11:11:08 +03:00
John Preston
be8aeb0d96 Fix week name display in chats list.
Fixes #25625.
2022-12-29 10:27:22 +04:00
John Preston
599cc35e57 Fix a crash in history clear. 2022-12-29 09:57:45 +04:00
John Preston
bd367da1bd Put #include after the #pragma once. 2022-12-29 09:52:38 +04:00
Ilya Fedin
62b50a41c8 Update libtgvoip 2022-12-29 09:32:07 +04:00
Ilya Fedin
a3caecbc07 Fix build with clang 2022-12-29 09:32:07 +04:00
John Preston
71354d1611 Fix two crashes in own profile photo edit. 2022-12-28 23:37:16 +04:00
66 changed files with 754 additions and 190 deletions

View File

@@ -849,6 +849,8 @@ PRIVATE
info/profile/info_profile_members.h
info/profile/info_profile_members_controllers.cpp
info/profile/info_profile_members_controllers.h
info/profile/info_profile_phone_menu.cpp
info/profile/info_profile_phone_menu.h
info/profile/info_profile_text.cpp
info/profile/info_profile_text.h
info/profile/info_profile_values.cpp

Binary file not shown.

After

Width:  |  Height:  |  Size: 525 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -323,6 +323,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_intro_qr_step3" = "Scan this image to Log In";
"lng_intro_qr_skip" = "Or log in using your phone number";
"lng_intro_fragment_title" = "Enter code";
"lng_intro_fragment_about" = "Get the code for {phone_number} in the Anonymous Numbers section on Fragment.";
"lng_intro_fragment_button" = "Open Fragment";
"lng_phone_title" = "Your Phone Number";
"lng_phone_desc" = "Please confirm your country code and\nenter your mobile phone number.";
"lng_phone_to_qr" = "Quick log in using QR code";
@@ -751,6 +755,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_download_path" = "Download path";
"lng_download_path_temp" = "Temp folder";
"lng_download_path_default" = "Default folder";
"lng_download_path_unset" = "Unset";
"lng_download_path_clear" = "Clear all";
"lng_download_path_header" = "Choose download path";
"lng_download_path_default_radio" = "Telegram folder in system «Downloads»";
@@ -1192,6 +1197,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_info_tab_media" = "Media";
"lng_info_public_photo" = "public photo";
"lng_info_mobile_label" = "Mobile";
"lng_info_mobile_context_menu_fragment_about" = "This number is not tied to a SIM card and was acquired on {link}.";
"lng_info_mobile_context_menu_fragment_about_link" = "Fragment";
"lng_info_mobile_hidden" = "Hidden";
"lng_info_username_label" = "Username";
"lng_info_usernames_label" = "also";

View File

@@ -10,7 +10,7 @@
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
ProcessorArchitecture="ARCHITECTURE"
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
Version="4.4.2.0" />
Version="4.4.3.0" />
<Properties>
<DisplayName>Telegram Desktop</DisplayName>
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>

View File

@@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,4,2,0
PRODUCTVERSION 4,4,2,0
FILEVERSION 4,4,3,0
PRODUCTVERSION 4,4,3,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -62,10 +62,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram FZ-LLC"
VALUE "FileDescription", "Telegram Desktop"
VALUE "FileVersion", "4.4.2.0"
VALUE "FileVersion", "4.4.3.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2022"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "4.4.2.0"
VALUE "ProductVersion", "4.4.3.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,4,2,0
PRODUCTVERSION 4,4,2,0
FILEVERSION 4,4,3,0
PRODUCTVERSION 4,4,3,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", "4.4.2.0"
VALUE "FileVersion", "4.4.3.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2022"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "4.4.2.0"
VALUE "ProductVersion", "4.4.3.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "lang/lang_keys.h"
#include "main/main_account.h"
#include "main/main_session.h"
#include "ui/boxes/confirm_box.h"
#include "ui/boxes/confirm_phone_box.h"
@@ -58,6 +59,10 @@ void ConfirmPhone::resolve(
}, [&](const MTPDauth_sentCodeTypeSetUpEmailRequired &) {
return bad("SetUpEmailRequired");
});
const auto fragmentUrl = data.vtype().match([](
const MTPDauth_sentCodeTypeFragmentSms &data) {
return qs(data.vurl());
}, [](const auto &) { return QString(); });
const auto phoneHash = qs(data.vphone_code_hash());
const auto timeout = [&]() -> std::optional<int> {
if (const auto nextType = data.vnext_type()) {
@@ -70,8 +75,15 @@ void ConfirmPhone::resolve(
auto box = Box<Ui::ConfirmPhoneBox>(
phone,
sentCodeLength,
fragmentUrl,
timeout);
const auto boxWeak = Ui::MakeWeak(box.data());
using LoginCode = rpl::event_stream<QString>;
const auto codeHandles = box->lifetime().make_state<LoginCode>();
controller->session().account().setHandleLoginCode([=](
const QString &code) {
codeHandles->fire_copy(code);
});
box->resendRequests(
) | rpl::start_with_next([=] {
_api.request(MTPauth_ResendCode(
@@ -83,7 +95,9 @@ void ConfirmPhone::resolve(
}
}).send();
}, box->lifetime());
box->checkRequests(
rpl::merge(
codeHandles->events(),
box->checkRequests()
) | rpl::start_with_next([=](const QString &code) {
if (_checkRequestId) {
return;
@@ -115,6 +129,10 @@ void ConfirmPhone::resolve(
boxWeak->showServerError(errorText);
}).handleFloodErrors().send();
}, box->lifetime());
box->boxClosing(
) | rpl::start_with_next([=] {
controller->session().account().setHandleLoginCode(nullptr);
}, box->lifetime());
controller->show(std::move(box), Ui::LayerOption::CloseOther);
});

View File

@@ -467,6 +467,7 @@ void GroupInfoBox::prepare() {
&_navigation->parentController()->window(),
Ui::UserpicButton::Role::ChoosePhoto,
st::defaultUserpicButton);
_photo->showCustomOnChosen();
_title.create(
this,
st::defaultInputField,
@@ -640,10 +641,11 @@ void GroupInfoBox::createGroup(
MTP_int(_ttlPeriod)
)).done([=](const MTPUpdates &result) {
auto image = _photo->takeResultImage();
const auto period = _ttlPeriod;
const auto navigation = _navigation;
getDelegate()->hideLayer(); // Destroys 'this'.
ChatCreateDone(navigation, std::move(image), _ttlPeriod, result);
ChatCreateDone(navigation, std::move(image), period, result);
}).fail([=](const MTP::Error &error) {
const auto &type = error.type();
_creationRequestId = 0;

View File

@@ -293,6 +293,10 @@ membersAbout: FlatLabel(defaultFlatLabel) {
style: boxLabelStyle;
}
fragmentBoxButton: RoundButton(introFragmentButton) {
width: 256px;
}
passcodeHeaderFont: font(19px);
passcodeHeaderHeight: 80px;
passcodeInput: InputField(introPhone) {

View File

@@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "boxes/change_phone_box.h"
#include "core/file_utilities.h"
#include "lang/lang_keys.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/sent_code_field.h"
@@ -19,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/boxes/confirm_box.h"
#include "boxes/phone_banned_box.h"
#include "countries/countries_instance.h" // Countries::ExtractPhoneCode.
#include "main/main_account.h"
#include "main/main_session.h"
#include "data/data_session.h"
#include "data/data_user.h"
@@ -67,6 +69,10 @@ void CreateErrorLabel(
}
}
[[nodiscard]] int ErrorSkip() {
return st::boxLittleSkip + st::changePhoneError.style.font->height;
}
} // namespace
namespace Settings {
@@ -109,6 +115,7 @@ public:
not_null<Window::SessionController*> controller,
const QString &phone,
const QString &hash,
const QString &openUrl,
int codeLength,
int callTimeout);
@@ -120,7 +127,7 @@ protected:
void prepare() override;
private:
void submit();
void submit(const QString &code);
void sendCall();
void updateCall();
void sendCodeFail(const MTP::Error &error);
@@ -128,18 +135,20 @@ private:
void hideError() {
showError(QString());
}
int countHeight();
[[nodiscard]] int countHeight() const;
const not_null<Window::SessionController*> _controller;
MTP::Sender _api;
QString _phone;
QString _hash;
QString _openUrl;
int _codeLength = 0;
int _callTimeout = 0;
object_ptr<Ui::SentCodeField> _code = { nullptr };
object_ptr<Ui::FadeWrap<Ui::FlatLabel>> _error = { nullptr };
object_ptr<Ui::FlatLabel> _callLabel = { nullptr };
object_ptr<Ui::RoundButton> _fragment = { nullptr };
mtpRequestId _requestId = 0;
Ui::SentCodeCall _call;
@@ -174,11 +183,9 @@ void ChangePhone::EnterPhone::prepare() {
this,
tr::lng_change_phone_new_description(tr::now),
st::changePhoneLabel);
const auto errorSkip = st::boxLittleSkip
+ st::changePhoneError.style.font->height;
description->moveToLeft(
st::boxPadding.left(),
_phone->y() + _phone->height() + errorSkip + st::boxLittleSkip);
_phone->y() + _phone->height() + ErrorSkip() + st::boxLittleSkip);
setDimensions(
st::boxWidth,
@@ -221,6 +228,7 @@ void ChangePhone::EnterPhone::sendPhoneDone(
return false;
};
auto codeLength = 0;
auto codeByFragmentUrl = QString();
const auto hasLength = data.vtype().match([&](
const MTPDauth_sentCodeTypeApp &typeData) {
LOG(("Error: should not be in-app code!"));
@@ -231,6 +239,7 @@ void ChangePhone::EnterPhone::sendPhoneDone(
return true;
}, [&](const MTPDauth_sentCodeTypeFragmentSms &typeData) {
codeLength = typeData.vlength().v;
codeByFragmentUrl = qs(typeData.vurl());
return true;
}, [&](const MTPDauth_sentCodeTypeCall &typeData) {
codeLength = typeData.vlength().v;
@@ -263,6 +272,7 @@ void ChangePhone::EnterPhone::sendPhoneDone(
_controller,
phoneNumber,
phoneCodeHash,
codeByFragmentUrl,
codeLength,
callTimeout),
Ui::LayerOption::KeepOther);
@@ -307,18 +317,21 @@ ChangePhone::EnterCode::EnterCode(
not_null<Window::SessionController*> controller,
const QString &phone,
const QString &hash,
const QString &openUrl,
int codeLength,
int callTimeout)
: _controller(controller)
, _api(&controller->session().mtp())
, _phone(phone)
, _hash(hash)
, _openUrl(openUrl)
, _codeLength(codeLength)
, _callTimeout(callTimeout)
, _call([this] { sendCall(); }, [this] { updateCall(); }) {
}
void ChangePhone::EnterCode::prepare() {
const auto width = st::boxWidth;
setTitle(tr::lng_change_phone_title());
const auto descriptionText = tr::lng_change_phone_code_description(
@@ -332,44 +345,69 @@ void ChangePhone::EnterCode::prepare() {
st::changePhoneLabel);
description->moveToLeft(st::boxPadding.left(), 0);
const auto submitInput = [=] { submit(_code->getDigitsOnly()); };
const auto phoneValue = QString();
_code.create(
this,
st::defaultInputField,
tr::lng_change_phone_code_title(),
phoneValue);
_code->setAutoSubmit(_codeLength, [=] { submit(); });
_code->setAutoSubmit(_codeLength, submitInput);
_code->setChangedCallback([=] { hideError(); });
_code->resize(st::boxWidth - 2 * st::boxPadding.left(), _code->height());
_code->resize(width - 2 * st::boxPadding.left(), _code->height());
_code->moveToLeft(st::boxPadding.left(), description->bottomNoMargins());
connect(_code, &Ui::InputField::submitted, [=] { submit(); });
connect(_code, &Ui::InputField::submitted, submitInput);
setDimensions(st::boxWidth, countHeight());
if (!_openUrl.isEmpty()) {
_fragment.create(
this,
tr::lng_intro_fragment_button(),
st::fragmentBoxButton);
_fragment->setClickedCallback([=] { File::OpenUrl(_openUrl); });
_fragment->setTextTransform(
Ui::RoundButton::TextTransform::NoTransform);
const auto codeBottom = _code->y() + _code->height();
_fragment->setFullWidth(_code->width());
_fragment->moveToLeft(
(width - _fragment->width()) / 2,
codeBottom + ErrorSkip() + st::boxLittleSkip);
}
_controller->session().account().setHandleLoginCode([=](QString code) {
submit(code);
});
boxClosing(
) | rpl::start_with_next([controller = _controller] {
controller->session().account().setHandleLoginCode(nullptr);
}, lifetime());
setDimensions(width, countHeight());
if (_callTimeout > 0) {
_call.setStatus({ Ui::SentCodeCall::State::Waiting, _callTimeout });
updateCall();
}
addButton(tr::lng_change_phone_new_submit(), [=] { submit(); });
addButton(tr::lng_change_phone_new_submit(), submitInput);
addButton(tr::lng_cancel(), [=] { closeBox(); });
}
int ChangePhone::EnterCode::countHeight() {
const auto errorSkip = st::boxLittleSkip
+ st::changePhoneError.style.font->height;
return _code->bottomNoMargins() + errorSkip + 3 * st::boxLittleSkip;
int ChangePhone::EnterCode::countHeight() const {
return _code->bottomNoMargins()
+ ErrorSkip()
+ 3 * st::boxLittleSkip
+ (_fragment ? _fragment->height() : 0);
}
void ChangePhone::EnterCode::submit() {
void ChangePhone::EnterCode::submit(const QString &code) {
if (_requestId) {
return;
}
hideError();
const auto session = &_controller->session();
const auto code = _code->getDigitsOnly();
const auto weak = Ui::MakeWeak(this);
_requestId = session->api().request(MTPaccount_ChangePhone(
MTP_string(_phone),

View File

@@ -25,7 +25,14 @@ DownloadPathBox::DownloadPathBox(
, _path(Core::App().settings().downloadPath())
, _pathBookmark(Core::App().settings().downloadPathBookmark())
, _group(std::make_shared<Ui::RadioenumGroup<Directory>>(typeFromPath(_path)))
, _default(this, _group, Directory::Downloads, tr::lng_download_path_default_radio(tr::now), st::defaultBoxCheckbox)
, _default(Core::App().canReadDefaultDownloadPath(true)
? object_ptr<Ui::Radioenum<Directory>>(
this,
_group,
Directory::Downloads,
tr::lng_download_path_default_radio(tr::now),
st::defaultBoxCheckbox)
: nullptr)
, _temp(this, _group, Directory::Temp, tr::lng_download_path_temp_radio(tr::now), st::defaultBoxCheckbox)
, _dir(this, _group, Directory::Custom, tr::lng_download_path_dir_radio(tr::now), st::defaultBoxCheckbox)
, _pathLink(this, QString(), st::boxLinkButton) {
@@ -50,7 +57,7 @@ void DownloadPathBox::updateControlsVisibility() {
auto custom = (_group->value() == Directory::Custom);
_pathLink->setVisible(custom);
auto newHeight = st::boxOptionListPadding.top() + _default->getMargins().top() + _default->heightNoMargins() + st::boxOptionListSkip + _temp->heightNoMargins() + st::boxOptionListSkip + _dir->heightNoMargins();
auto newHeight = st::boxOptionListPadding.top() + (_default ? _default->getMargins().top() + _default->heightNoMargins() : 0) + st::boxOptionListSkip + _temp->heightNoMargins() + st::boxOptionListSkip + _dir->heightNoMargins();
if (custom) {
newHeight += st::downloadPathSkip + _pathLink->height();
}
@@ -62,8 +69,10 @@ void DownloadPathBox::updateControlsVisibility() {
void DownloadPathBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(e);
_default->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), st::boxOptionListPadding.top() + _default->getMargins().top());
_temp->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _default->bottomNoMargins() + st::boxOptionListSkip);
if (_default) {
_default->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), st::boxOptionListPadding.top() + _default->getMargins().top());
}
_temp->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), (_default ? _default->bottomNoMargins() : 0) + st::boxOptionListSkip);
_dir->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _temp->bottomNoMargins() + st::boxOptionListSkip);
auto inputx = st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultCheck.diameter + st::defaultBoxCheckbox.textPosition.x();
auto inputy = _dir->bottomNoMargins() + st::downloadPathSkip;

View File

@@ -477,6 +477,7 @@ object_ptr<Ui::RpWidget> Controller::createPhotoEdit() {
st::defaultUserpicButton),
st::editPeerPhotoMargins);
_controls.photo = photoWrap->entity();
_controls.photo->showCustomOnChosen();
return photoWrap;
}

View File

@@ -595,11 +595,9 @@ void Application::saveSettings() {
Local::writeSettings();
}
bool Application::canSaveFileWithoutAskingForPath() const {
if (Core::App().settings().askDownloadPath()) {
return false;
} else if (KSandbox::isInside()
&& Core::App().settings().downloadPath().isEmpty()) {
bool Application::canReadDefaultDownloadPath(bool always) const {
if (KSandbox::isInside()
&& (always || Core::App().settings().downloadPath().isEmpty())) {
const auto path = QStandardPaths::writableLocation(
QStandardPaths::DownloadLocation);
return base::CanReadDirectory(path);
@@ -607,6 +605,11 @@ bool Application::canSaveFileWithoutAskingForPath() const {
return true;
}
bool Application::canSaveFileWithoutAskingForPath() const {
return !Core::App().settings().askDownloadPath()
&& canReadDefaultDownloadPath();
}
MTP::Config &Application::fallbackProductionConfig() const {
if (!_fallbackProductionConfig) {
_fallbackProductionConfig = std::make_unique<MTP::Config>(

View File

@@ -178,6 +178,8 @@ public:
[[nodiscard]] Settings &settings();
void saveSettingsDelayed(crl::time delay = kDefaultSaveDelay);
void saveSettings();
[[nodiscard]] bool canReadDefaultDownloadPath(bool always = false) const;
[[nodiscard]] bool canSaveFileWithoutAskingForPath() const;
// Fallback config and proxy.

View File

@@ -84,6 +84,14 @@ std::map<int, const char*> BetaLogs() {
"- Set a public photo for those who are restricted to see "
"your profile photo in the Privacy Settings.\n"
"- Bug fixes and other minor improvements.\n"
},
{
4004003,
"- Support for anonymous numbers from the Fragment.com platform.\n"
"- Fix a crash in own profile photo updating.\n"
"- Bug fixes and other minor improvements.\n"
}
};

View File

@@ -24,8 +24,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtCore/QStandardPaths>
#include <QtGui/QDesktopServices>
#include <ksandbox.h>
bool filedialogGetSaveFile(
QPointer<QWidget> parent,
QString &file,
@@ -173,15 +171,12 @@ QString DefaultDownloadPathFolder(not_null<Main::Session*> session) {
}
QString DefaultDownloadPath(not_null<Main::Session*> session) {
const auto standardLocation = QStandardPaths::writableLocation(
QStandardPaths::DownloadLocation);
const auto realDefaultPath = standardLocation
const auto realDefaultPath = QStandardPaths::writableLocation(
QStandardPaths::DownloadLocation)
+ '/'
+ DefaultDownloadPathFolder(session)
+ '/';
if (KSandbox::isInside()
&& Core::App().settings().downloadPath().isEmpty()
&& !base::CanReadDirectory(standardLocation)) {
if (!Core::App().canReadDefaultDownloadPath()) {
QStringList files;
QByteArray remoteContent;
const auto success = Platform::FileDialog::Get(

View File

@@ -49,6 +49,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "settings/settings_chat.h"
#include "settings/settings_premium.h"
#include "mainwidget.h"
#include "main/main_account.h"
#include "main/main_session.h"
#include "main/main_session_settings.h"
#include "inline_bots/bot_attach_web_view.h"
@@ -792,6 +793,25 @@ bool ResolvePremiumOffer(
return true;
}
bool ResolveLoginCode(
Window::SessionController *controller,
const Match &match,
const QVariant &context) {
const auto loginCode = match->captured(2);
if (loginCode.isEmpty()) {
return false;
};
(controller
? controller->session().account()
: Core::App().activeAccount()).handleLoginCode(loginCode);
if (controller) {
controller->window().activate();
} else if (const auto window = Core::App().activeWindow()) {
window->activate();
}
return true;
}
} // namespace
const std::vector<LocalUrlHandler> &LocalUrlHandlers() {
@@ -864,6 +884,10 @@ const std::vector<LocalUrlHandler> &LocalUrlHandlers() {
u"premium_offer/?(\\?.+)?(#|$)"_q,
ResolvePremiumOffer,
},
{
u"^login/?(\\?code=([0-9]+))(&|$)"_q,
ResolveLoginCode
},
{
u"^([^\\?]+)(\\?|#|$)"_q,
HandleUnknown

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 = 4004002;
constexpr auto AppVersionStr = "4.4.2";
constexpr auto AppVersion = 4004003;
constexpr auto AppVersionStr = "4.4.3";
constexpr auto AppBetaVersion = true;
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;

View File

@@ -356,24 +356,55 @@ FormatResult CountriesInstance::format(FormatArgs args) {
const auto codeSize = int(bestCallingCodePtr->callingCode.size());
if (args.onlyGroups && args.incomplete) {
auto groups = args.skipCode
auto initialGroups = args.skipCode
? QVector<int>()
: QVector<int>{ codeSize };
auto groupSize = 0;
auto initialGroupsSize = 0;
if (bestCallingCodePtr->patterns.empty()) {
return FormatResult{ .groups = std::move(groups) };
return FormatResult{ .groups = std::move(initialGroups) };
}
for (const auto &c : bestCallingCodePtr->patterns.front()) {
if (c == ' ') {
groups.push_back(base::take(groupSize));
} else {
groupSize++;
auto bestGroups = initialGroups;
auto bestGroupsSize = initialGroupsSize;
auto bestPatternMaxMatches = -1;
for (const auto &pattern : bestCallingCodePtr->patterns) {
auto groups = initialGroups;
auto groupSize = initialGroupsSize;
auto lastSpacesCount = 0;
auto maxMatchedDigits = 0;
auto isNotBestPattern = false;
for (auto i = 0; i < pattern.size(); i++) {
const auto c = pattern.at(i);
if (c.isDigit()) {
const auto n = (i - lastSpacesCount) + codeSize;
if (n < phoneNumber.size()) {
if (phoneNumber.at(n) == c) {
maxMatchedDigits++;
} else {
isNotBestPattern = true;
}
} else {
isNotBestPattern = true;
}
}
if (c.isSpace()) {
groups.push_back(base::take(groupSize));
lastSpacesCount++;
} else {
groupSize++;
}
}
if (maxMatchedDigits > bestPatternMaxMatches) {
bestPatternMaxMatches = isNotBestPattern
? -1
: maxMatchedDigits;
bestGroups = std::move(groups);
bestGroupsSize = groupSize;
}
}
if (groupSize) {
groups.push_back(base::take(groupSize));
if (bestGroupsSize) {
bestGroups.push_back(base::take(bestGroupsSize));
}
return FormatResult{ .groups = std::move(groups) };
return FormatResult{ .groups = std::move(bestGroups) };
}
const auto formattedPart = phoneNumber.mid(codeSize);

View File

@@ -89,12 +89,10 @@ void PaintRowDate(
const auto lastDate = lastTime.date();
const auto dt = [&] {
const auto wasSameDay = (lastDate == nowDate);
const auto wasRecently = qAbs(lastTime.secsTo(now)) < kRecentlyInSeconds;
if (wasSameDay || wasRecently) {
if ((lastDate == nowDate)
|| (qAbs(lastTime.secsTo(now)) < kRecentlyInSeconds)) {
return QLocale().toString(lastTime.time(), QLocale::ShortFormat);
} else if (lastDate.year() == nowDate.year()
&& lastDate.weekNumber() == nowDate.weekNumber()) {
} else if (qAbs(lastDate.daysTo(nowDate)) < 7) {
return langDayOfWeek(lastDate);
} else {
return QLocale().toString(lastDate, QLocale::ShortFormat);

View File

@@ -1431,12 +1431,18 @@ void HistoryItem::applyEdition(const MTPDmessageService &message) {
if (wasGrouped) {
history()->owner().groups().unregisterMessage(this);
}
if (const auto reply = Get<HistoryMessageReply>()) {
reply->clearData(this);
}
clearDependencyMessage();
UpdateComponents(0);
createServiceFromMtp(message);
applyServiceDateEdition(message);
finishEditionToEmpty();
} else if (isService()) {
if (const auto reply = Get<HistoryMessageReply>()) {
reply->clearData(this);
}
clearDependencyMessage();
UpdateComponents(0);
createServiceFromMtp(message);

View File

@@ -141,7 +141,7 @@ rpl::producer<Ui::GroupCallBarContent> GroupCallBarContentByCall(
userpic.peer->loadUserpic();
auto image = userpic.peer->generateUserpicImage(
userpic.view,
userpicSize);
userpicSize * style::DevicePixelRatio());
userpic.uniqueKey = userpic.peer->userpicUniqueKey(userpic.view);
state->current.users.push_back({
.userpic = std::move(image),

View File

@@ -88,7 +88,7 @@ rpl::producer<Ui::RequestsBarContent> RequestsBarContentByPeer(
userpic.peer->loadUserpic();
auto image = userpic.peer->generateUserpicImage(
userpic.view,
userpicSize);
userpicSize * style::DevicePixelRatio());
userpic.uniqueKey = userpic.peer->userpicUniqueKey(userpic.view);
state->current.users.push_back({
.userpic = std::move(image),

View File

@@ -45,6 +45,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "info/info_controller.h"
#include "info/info_memento.h"
#include "info/profile/info_profile_icon.h"
#include "info/profile/info_profile_phone_menu.h"
#include "info/profile/info_profile_values.h"
#include "info/profile/info_profile_text.h"
#include "support/support_helper.h"
@@ -391,10 +392,17 @@ object_ptr<Ui::RpWidget> DetailsFiller::setupInfo() {
user->session().supportHelper().infoTextValue(user));
}
addInfoOneLine(
tr::lng_info_mobile_label(),
PhoneOrHiddenValue(user),
tr::lng_profile_copy_phone(tr::now));
{
const auto phoneLabel = addInfoOneLine(
tr::lng_info_mobile_label(),
PhoneOrHiddenValue(user),
tr::lng_profile_copy_phone(tr::now)).text;
const auto hook = [=](Ui::FlatLabel::ContextMenuRequest request) {
phoneLabel->fillContextMenu(request);
AddPhoneMenu(request.menu, user);
};
phoneLabel->setContextMenuHook(hook);
}
auto label = user->isBot()
? tr::lng_info_about_label()
: tr::lng_info_bio_label();

View File

@@ -0,0 +1,155 @@
/*
This file is part of Telegram Desktop,
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
*/
#include "info/profile/info_profile_phone_menu.h"
#include "data/data_user.h"
#include "lang/lang_keys.h"
#include "main/main_account.h"
#include "main/main_app_config.h"
#include "main/main_session.h"
#include "ui/text/text_utilities.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/menu/menu_action.h"
#include "ui/widgets/popup_menu.h"
#include "styles/style_chat.h" // expandedMenuSeparator.
namespace Info {
namespace Profile {
namespace {
class TextItem final : public Ui::Menu::ItemBase {
public:
TextItem(
not_null<Ui::RpWidget*> parent,
const style::Menu &st,
rpl::producer<TextWithEntities> &&text);
not_null<QAction*> action() const override;
bool isEnabled() const override;
protected:
int contentHeight() const override;
private:
const base::unique_qptr<Ui::FlatLabel> _label;
const not_null<QAction*> _dummyAction;
};
[[nodiscard]] int CountMinWidthForHeight(
not_null<Ui::FlatLabel*> label,
int basicWidth,
int heightLimit) {
const auto height = [&](int width) {
label->resizeToWidth(width);
return label->height();
};
auto widthMin = basicWidth;
auto widthMax = label->naturalWidth();
if (height(widthMin) <= heightLimit || height(widthMax) > heightLimit) {
return basicWidth;
}
while (widthMin + 1 < widthMax) {
const auto middle = (widthMin + widthMax) / 2;
if (height(middle) > heightLimit) {
widthMin = middle;
} else {
widthMax = middle;
}
}
return widthMax;
}
TextItem::TextItem(
not_null<Ui::RpWidget*> parent,
const style::Menu &st,
rpl::producer<TextWithEntities> &&text)
: ItemBase(parent, st)
, _label(base::make_unique_q<Ui::FlatLabel>(
this,
std::move(text),
st::historyMessagesTTLLabel))
, _dummyAction(Ui::CreateChild<QAction>(parent.get())) {
// Try to fit the phrase in two lines.
const auto limit = st::historyMessagesTTLLabel.style.font->height * 2;
const auto min1 = st::historyMessagesTTLLabel.minWidth;
const auto min2 = CountMinWidthForHeight(_label.get(), min1, limit);
const auto added = st.itemPadding.left() + st.itemPadding.right();
setMinWidth(std::max(min1, min2) + added);
sizeValue(
) | rpl::start_with_next([=](const QSize &s) {
if (s.width() <= added) {
return;
}
_label->resizeToWidth(s.width() - added);
_label->moveToLeft(
st.itemPadding.left(),
(s.height() - _label->height()) / 2);
}, lifetime());
_label->resizeToWidth(parent->width() - added);
initResizeHook(parent->sizeValue());
}
not_null<QAction*> TextItem::action() const {
return _dummyAction;
}
bool TextItem::isEnabled() const {
return false;
}
int TextItem::contentHeight() const {
return _label->height();
}
} // namespace
void AddPhoneMenu(not_null<Ui::PopupMenu*> menu, not_null<UserData*> user) {
if (user->isSelf()) {
return;
}
using Strings = std::vector<QString>;
const auto prefixes = user->session().account().appConfig().get<Strings>(
u"fragment_prefixes"_q,
std::vector<QString>());
{
const auto proj = [&phone = user->phone()](const QString &p) {
return phone.startsWith(p);
};
if (ranges::none_of(prefixes, proj)) {
return;
}
}
const auto domains = user->session().account().appConfig().get<Strings>(
u"whitelisted_domains"_q,
std::vector<QString>());
const auto proj = [&, domain = u"fragment"_q](const QString &p) {
return p.contains(domain);
};
const auto it = ranges::find_if(domains, proj);
if (it == end(domains)) {
return;
}
menu->addSeparator(&st::expandedMenuSeparator);
const auto link = Ui::Text::Link(
tr::lng_info_mobile_context_menu_fragment_about_link(tr::now),
*it);
menu->addAction(base::make_unique_q<TextItem>(
menu->menu(),
st::reactionMenu.menu,
tr::lng_info_mobile_context_menu_fragment_about(
lt_link,
rpl::single(link),
Ui::Text::RichLangValue)));
}
} // namespace Profile
} // namespace Info

View File

@@ -0,0 +1,22 @@
/*
This file is part of Telegram Desktop,
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
*/
#pragma once
class UserData;
namespace Ui {
class PopupMenu;
} // namespace Ui
namespace Info {
namespace Profile {
void AddPhoneMenu(not_null<Ui::PopupMenu*> menu, not_null<UserData*> user);
} // namespace Profile
} // namespace Info

View File

@@ -85,9 +85,17 @@ introCoverDuration: 200;
introNextButton: RoundButton(defaultActiveButton) {
width: 300px;
height: 42px;
radius: 6px;
textTop: 11px;
font: font(boxFontSize semibold);
}
introFragmentIcon: icon{{ "fragment", activeButtonFg }};
introFragmentIconOver: icon{{ "fragment", activeButtonFgOver }};
introFragmentButton: RoundButton(introNextButton) {
icon: introFragmentIcon;
iconOver: introFragmentIconOver;
iconPosition: point(-10px, 9px);
}
introStepFieldTop: 96px;
introPhoneTop: 6px;

View File

@@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h"
#include "intro/intro_signup.h"
#include "intro/intro_password_check.h"
#include "core/file_utilities.h"
#include "core/update_checker.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h"
@@ -99,8 +100,15 @@ CodeWidget::CodeWidget(
_code->setDigitsCountMax(getData()->codeLength);
setTitleText(rpl::single(Ui::FormatPhone(getData()->phone)));
setTitleText(getData()->codeByFragmentUrl.isEmpty()
? rpl::single(Ui::FormatPhone(getData()->phone))
: tr::lng_intro_fragment_title());
updateDescText();
account->setHandleLoginCode([=](const QString &code) {
_code->setText(code);
submitCode();
});
}
void CodeWidget::refreshLang() {
@@ -117,10 +125,19 @@ int CodeWidget::errorTop() const {
void CodeWidget::updateDescText() {
const auto byTelegram = getData()->codeByTelegram;
const auto isFragment = !getData()->codeByFragmentUrl.isEmpty();
setDescriptionText(
(byTelegram ? tr::lng_code_from_telegram : tr::lng_code_desc)(
Ui::Text::RichLangValue));
if (getData()->codeByTelegram) {
isFragment
? tr::lng_intro_fragment_about(
lt_phone_number,
rpl::single(TextWithEntities{
.text = Ui::FormatPhone(getData()->phone)
}),
Ui::Text::RichLangValue)
: (byTelegram ? tr::lng_code_from_telegram : tr::lng_code_desc)(
Ui::Text::RichLangValue));
if (isFragment) {
} else if (getData()->codeByTelegram) {
_noTelegramCode->show();
_callTimer.cancel();
} else {
@@ -204,6 +221,7 @@ void CodeWidget::activate() {
void CodeWidget::finished() {
Step::finished();
account().setHandleLoginCode(nullptr);
_checkRequestTimer.cancel();
_callTimer.cancel();
apiClear();
@@ -300,7 +318,7 @@ void CodeWidget::codeSubmitFail(const MTP::Error &error) {
void CodeWidget::codeChanged() {
hideError();
submit();
submitCode();
}
void CodeWidget::sendCall() {
@@ -362,10 +380,18 @@ void CodeWidget::gotPassword(const MTPaccount_Password &result) {
}
void CodeWidget::submit() {
if (getData()->codeByFragmentUrl.isEmpty()) {
submitCode();
} else {
File::OpenUrl(getData()->codeByFragmentUrl);
}
}
void CodeWidget::submitCode() {
const auto text = QString(
_code->getLastText()
).remove(
QRegularExpression("[^\\d]")
TextUtilities::RegExpDigitsExclude()
).mid(0, getData()->codeLength);
if (_sentRequest
@@ -393,6 +419,18 @@ void CodeWidget::submit() {
}).handleFloodErrors().send();
}
rpl::producer<QString> CodeWidget::nextButtonText() const {
return getData()->codeByFragmentUrl.isEmpty()
? Step::nextButtonText()
: tr::lng_intro_fragment_button();
}
const style::RoundButton *CodeWidget::nextButtonStyle() const {
return !getData()->codeByFragmentUrl.isEmpty()
? &st::introFragmentButton
: nullptr;
}
void CodeWidget::noTelegramCode() {
if (_noTelegramCodeRequestId) {
return;

View File

@@ -55,6 +55,8 @@ public:
void finished() override;
void cancelled() override;
void submit() override;
rpl::producer<QString> nextButtonText() const override;
const style::RoundButton *nextButtonStyle() const override;
void updateDescText();
@@ -83,6 +85,8 @@ private:
void noTelegramCodeDone(const MTPauth_SentCode &result);
void noTelegramCodeFail(const MTP::Error &result);
void submitCode();
void stopCheck();
object_ptr<Ui::LinkButton> _noTelegramCode;

View File

@@ -34,6 +34,8 @@ SignupWidget::SignupWidget(
, _first(this, st::introName, tr::lng_signup_firstname())
, _last(this, st::introName, tr::lng_signup_lastname())
, _invertOrder(langFirstNameGoesSecond()) {
_photo->showCustomOnChosen();
Lang::Updated(
) | rpl::start_with_next([=] {
refreshLang();

View File

@@ -119,6 +119,10 @@ rpl::producer<QString> Step::nextButtonText() const {
return tr::lng_intro_next();
}
const style::RoundButton *Step::nextButtonStyle() const {
return nullptr;
}
void Step::goBack() {
if (_goCallback) {
_goCallback(nullptr, StackAction::Back, Animate::Back);

View File

@@ -12,6 +12,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/rp_widget.h"
#include "ui/effects/animations.h"
namespace style {
struct RoundButton;
} // namespace style;
namespace Main {
class Account;
} // namespace Main;
@@ -77,6 +81,7 @@ public:
virtual void submit() = 0;
[[nodiscard]] virtual rpl::producer<QString> nextButtonText() const;
[[nodiscard]] virtual const style::RoundButton *nextButtonStyle() const;
[[nodiscard]] int contentLeft() const;
[[nodiscard]] int contentTop() const;

View File

@@ -74,6 +74,7 @@ Widget::Widget(
: RpWidget(parent)
, _account(account)
, _data(details::Data{ .controller = controller })
, _nextStyle(&st::introNextButton)
, _back(this, object_ptr<Ui::IconButton>(this, st::introBackButton))
, _settings(
this,
@@ -83,7 +84,7 @@ Widget::Widget(
st::defaultBoxButton))
, _next(
this,
object_ptr<Ui::RoundButton>(this, nullptr, st::introNextButton))
object_ptr<Ui::RoundButton>(this, nullptr, *_nextStyle))
, _connecting(std::make_unique<Window::ConnectionState>(
this,
account,
@@ -127,10 +128,6 @@ Widget::Widget(
_back->entity()->setClickedCallback([=] { backRequested(); });
_back->hide(anim::type::instant);
_next->entity()->setClickedCallback([=] { getStep()->submit(); });
_next->entity()->setTextTransform(
Ui::RoundButton::TextTransform::NoTransform);
if (_changeLanguage) {
_changeLanguage->finishAnimating();
}
@@ -344,13 +341,31 @@ void Widget::historyMove(StackAction action, Animate animate) {
if (_terms) {
hideAndDestroy(std::exchange(_terms, { nullptr }));
}
{
const auto st = getStep()->nextButtonStyle();
const auto nextStyle = st ? st : &st::introNextButton;
if (_nextStyle != nextStyle) {
_nextStyle = nextStyle;
_next = nullptr;
_next.create(
this,
object_ptr<Ui::RoundButton>(this, nullptr, *nextStyle));
showControls();
updateControlsGeometry();
}
}
getStep()->finishInit();
getStep()->prepareShowAnimated(wasStep);
if (wasStep->hasCover() != getStep()->hasCover()) {
_nextTopFrom = wasStep->contentTop() + st::introNextTop;
_controlsTopFrom = wasStep->hasCover() ? st::introCoverHeight : 0;
_coverShownAnimation.start([this] { updateControlsGeometry(); }, 0., 1., st::introCoverDuration, wasStep->hasCover() ? anim::linear : anim::easeOutCirc);
_coverShownAnimation.start(
[this] { updateControlsGeometry(); },
0.,
1.,
st::introCoverDuration,
wasStep->hasCover() ? anim::linear : anim::easeOutCirc);
}
_stepLifetime.destroy();
@@ -665,6 +680,10 @@ void Widget::showControls() {
}
void Widget::setupNextButton() {
_next->entity()->setClickedCallback([=] { getStep()->submit(); });
_next->entity()->setTextTransform(
Ui::RoundButton::TextTransform::NoTransform);
_next->entity()->setText(getStep()->nextButtonText(
) | rpl::filter([](const QString &text) {
return !text.isEmpty();
@@ -757,13 +776,18 @@ void Widget::resizeEvent(QResizeEvent *e) {
}
void Widget::updateControlsGeometry() {
auto shown = _coverShownAnimation.value(1.);
const auto skip = st::introSettingsSkip;
const auto shown = _coverShownAnimation.value(1.);
auto controlsTopTo = getStep()->hasCover() ? st::introCoverHeight : 0;
auto controlsTop = anim::interpolate(_controlsTopFrom, controlsTopTo, shown);
_settings->moveToRight(st::introSettingsSkip, controlsTop + st::introSettingsSkip);
const auto controlsTop = anim::interpolate(
_controlsTopFrom,
getStep()->hasCover() ? st::introCoverHeight : 0,
shown);
_settings->moveToRight(skip, controlsTop + skip);
if (_update) {
_update->moveToRight(st::introSettingsSkip + _settings->width() + st::introSettingsSkip, _settings->y());
_update->moveToRight(
skip + _settings->width() + skip,
_settings->y());
}
_back->moveToLeft(0, controlsTop);
@@ -779,13 +803,19 @@ void Widget::updateControlsGeometry() {
? QRect(0, 0, width(), realNextTop)
: QRect());
if (_changeLanguage) {
_changeLanguage->moveToLeft((width() - _changeLanguage->width()) / 2, _next->y() + _next->height() + _changeLanguage->height());
_changeLanguage->moveToLeft(
(width() - _changeLanguage->width()) / 2,
_next->y() + _next->height() + _changeLanguage->height());
}
if (_resetAccount) {
_resetAccount->moveToLeft((width() - _resetAccount->width()) / 2, height() - st::introResetBottom - _resetAccount->height());
_resetAccount->moveToLeft(
(width() - _resetAccount->width()) / 2,
height() - st::introResetBottom - _resetAccount->height());
}
if (_terms) {
_terms->moveToLeft((width() - _terms->width()) / 2, height() - st::introTermsBottom - _terms->height());
_terms->moveToLeft(
(width() - _terms->width()) / 2,
height() - st::introTermsBottom - _terms->height());
}
}

View File

@@ -186,6 +186,8 @@ private:
int _nextTopFrom = 0;
int _controlsTopFrom = 0;
const style::RoundButton *_nextStyle = nullptr;
object_ptr<Ui::FadeWrap<Ui::IconButton>> _back;
object_ptr<Ui::FadeWrap<Ui::RoundButton>> _update = { nullptr };
object_ptr<Ui::FadeWrap<Ui::RoundButton>> _settings;

View File

@@ -602,6 +602,16 @@ void Account::destroyStaleAuthorizationKeys() {
}
}
void Account::setHandleLoginCode(Fn<void(QString)> callback) {
_handleLoginCode = std::move(callback);
}
void Account::handleLoginCode(const QString &code) const {
if (_handleLoginCode) {
_handleLoginCode(code);
}
}
void Account::resetAuthorizationKeys() {
Expects(_mtp != nullptr);

View File

@@ -110,6 +110,9 @@ public:
void suggestMainDcId(MTP::DcId mainDcId);
void destroyStaleAuthorizationKeys();
void setHandleLoginCode(Fn<void(QString)> callback);
void handleLoginCode(const QString &code) const;
[[nodiscard]] rpl::lifetime &lifetime() {
return _lifetime;
}
@@ -152,6 +155,8 @@ private:
std::unique_ptr<Session> _session;
rpl::variable<Session*> _sessionValue;
Fn<void(QString)> _handleLoginCode = nullptr;
UserId _sessionUserId = 0;
QByteArray _sessionUserSerialized;
int32 _sessionUserStreamVersion = 0;

View File

@@ -198,7 +198,6 @@ QByteArray Session::validTmpPassword() const {
// Can be called only right before ~Session.
void Session::finishLogout() {
updates().updateOnline();
unlockTerms();
data().clear();
data().clearLocalStorage();

View File

@@ -1537,6 +1537,7 @@ bool Instance::Private::onErrorDefault(
const auto session = getSession(qAbs(dcWithShift));
request->needsLayer = true;
session->setConnectionNotInited();
session->sendPrepared(request);
return true;
} else if (type == u"CONNECTION_LANG_CODE_INVALID"_q) {

View File

@@ -257,10 +257,14 @@ void Session::refreshOptions() {
}
void Session::reInitConnection() {
_dc->setConnectionInited(false);
setConnectionNotInited();
restart();
}
void Session::setConnectionNotInited() {
_dc->setConnectionInited(false);
}
void Session::stop() {
if (_killed) {
DEBUG_LOG(("Session Error: can't stop a killed session"));

View File

@@ -142,6 +142,7 @@ public:
void start();
void reInitConnection();
void setConnectionNotInited();
void restart();
void refreshOptions();

View File

@@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "passport/passport_panel_controller.h"
#include "main/main_account.h"
#include "main/main_session.h"
#include "lang/lang_keys.h"
#include "passport/passport_panel_edit_document.h"
#include "passport/passport_panel_edit_contact.h"
@@ -485,7 +487,9 @@ EditContactScheme GetContactScheme(Scope::Type type) {
return Ui::FormatPhone(value);
};
result.postprocess = [](QString value) {
return value.replace(QRegularExpression("[^\\d]"), QString());
return value.replace(
TextUtilities::RegExpDigitsExclude(),
QString());
};
return result;
} break;
@@ -1319,11 +1323,16 @@ void PanelController::processVerificationNeeded(
});
const auto box = [&] {
if (type == Value::Type::Phone) {
return show(VerifyPhoneBox(
const auto submit = [=](const QString &code) {
_form->verify(value, code);
};
const auto account = &_form->window()->session().account();
account->setHandleLoginCode(submit);
const auto box = show(VerifyPhoneBox(
text,
value->verification.codeLength,
[=](const QString &code) { _form->verify(value, code); },
value->verification.fragmentUrl,
submit,
value->verification.call ? rpl::single(
value->verification.call->getText()
) | rpl::then(rpl::duplicate(
@@ -1339,6 +1348,11 @@ void PanelController::processVerificationNeeded(
) | rpl::map([=](not_null<const Value*> field) {
return field->verification.error;
}) | rpl::distinct_until_changed()));
box->boxClosing(
) | rpl::start_with_next([=] {
account->setHandleLoginCode(nullptr);
}, box->lifetime());
return box;
} else if (type == Value::Type::Email) {
return show(VerifyEmailBox(
text,

View File

@@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "passport/passport_panel_edit_contact.h"
#include "core/file_utilities.h"
#include "passport/passport_panel_controller.h"
#include "passport/ui/passport_details_row.h"
#include "ui/widgets/input_fields.h"
@@ -26,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "countries/countries_instance.h" // Countries::ExtractPhoneCode.
#include "main/main_session.h"
#include "lang/lang_keys.h"
#include "styles/style_boxes.h"
#include "styles/style_passport.h"
#include "styles/style_layers.h"
@@ -39,6 +41,7 @@ public:
rpl::producer<QString> title,
const QString &text,
int codeLength,
const QString &openUrl,
Fn<void(QString code)> submit,
Fn<void()> resend,
rpl::producer<QString> call,
@@ -54,6 +57,7 @@ private:
void setupControls(
const QString &text,
int codeLength,
const QString &openUrl,
Fn<void(QString code)> submit,
Fn<void()> resend,
rpl::producer<QString> call,
@@ -72,6 +76,7 @@ VerifyBox::VerifyBox(
rpl::producer<QString> title,
const QString &text,
int codeLength,
const QString &openUrl,
Fn<void(QString code)> submit,
Fn<void()> resend,
rpl::producer<QString> call,
@@ -81,6 +86,7 @@ VerifyBox::VerifyBox(
setupControls(
text,
codeLength,
openUrl,
submit,
resend,
std::move(call),
@@ -91,6 +97,7 @@ VerifyBox::VerifyBox(
void VerifyBox::setupControls(
const QString &text,
int codeLength,
const QString &openUrl,
Fn<void(QString code)> submit,
Fn<void()> resend,
rpl::producer<QString> call,
@@ -130,6 +137,21 @@ void VerifyBox::setupControls(
std::move(call),
st::boxDividerLabel),
small);
if (!openUrl.isEmpty()) {
const auto button = _content->add(
object_ptr<Ui::RoundButton>(
_content,
tr::lng_intro_fragment_button(),
st::fragmentBoxButton),
small);
_content->widthValue(
) | rpl::start_with_next([=](int w) {
button->setFullWidth(w - small.left() - small.right());
}, button->lifetime());
button->setClickedCallback([=] { ::File::OpenUrl(openUrl); });
button->setTextTransform(
Ui::RoundButton::TextTransform::NoTransform);
}
if (resend) {
auto link = TextWithEntities{ tr::lng_cloud_password_resend(tr::now) };
link.entities.push_back({
@@ -144,9 +166,7 @@ void VerifyBox::setupControls(
link
) | rpl::then(rpl::duplicate(
resent
) | rpl::map([](const QString &value) {
return TextWithEntities{ value };
})),
) | rpl::map(TextWithEntities::Simple)),
st::boxDividerLabel),
small);
std::move(
@@ -392,6 +412,7 @@ void PanelEditContact::save(const QString &value) {
object_ptr<Ui::BoxContent> VerifyPhoneBox(
const QString &phone,
int codeLength,
const QString &openUrl,
Fn<void(QString code)> submit,
rpl::producer<QString> call,
rpl::producer<QString> error) {
@@ -402,6 +423,7 @@ object_ptr<Ui::BoxContent> VerifyPhoneBox(
lt_phone,
Ui::FormatPhone(phone)),
codeLength,
openUrl,
submit,
nullptr,
std::move(call),
@@ -420,6 +442,7 @@ object_ptr<Ui::BoxContent> VerifyEmailBox(
tr::lng_passport_email_title(),
tr::lng_passport_confirm_email(tr::now, lt_email, email),
codeLength,
QString(),
submit,
resend,
rpl::single(QString()),

View File

@@ -78,6 +78,7 @@ private:
object_ptr<Ui::BoxContent> VerifyPhoneBox(
const QString &phone,
int codeLength,
const QString &openUrl,
Fn<void(QString code)> submit,
rpl::producer<QString> call,
rpl::producer<QString> error);

View File

@@ -80,7 +80,8 @@ std::unique_ptr<base::Platform::DBus::ServiceWatcher> CreateServiceWatcher() {
try {
return ranges::contains(
base::Platform::DBus::ListActivatableNames(connection),
Glib::ustring(std::string(kService)));
std::string(kService),
&Glib::ustring::raw);
} catch (...) {
// avoid service restart loop in sandboxed environments
return true;
@@ -129,9 +130,11 @@ void StartServiceAsync(Fn<void()> callback) {
};
const auto errorName =
Gio::DBus::ErrorUtils::get_remote_error(e);
Gio::DBus::ErrorUtils::get_remote_error(e).raw();
if (!ranges::contains(NotSupportedErrors, errorName)) {
if (!ranges::contains(
NotSupportedErrors,
errorName)) {
throw e;
}
}
@@ -166,7 +169,8 @@ bool GetServiceRegistered() {
try {
return ranges::contains(
DBus::ListActivatableNames(connection),
Glib::ustring(std::string(kService)));
std::string(kService),
&Glib::ustring::raw);
} catch (...) {
return false;
}
@@ -383,12 +387,12 @@ bool NotificationData::init(
const QString &msg,
Window::Notifications::Manager::DisplayOptions options) {
if (_application) {
_notification = Gio::Notification::create(title.toStdString());
_notification->set_body(
_notification = Gio::Notification::create(
subtitle.isEmpty()
? msg.toStdString()
: u"%1\n%2"_q.arg(subtitle, msg).toStdString());
? title.toStdString()
: subtitle.toStdString() + " (" + title.toStdString() + ')');
_notification->set_body(msg.toStdString());
_notification->set_icon(
Gio::ThemedIcon::create(base::IconName().toStdString()));
@@ -498,19 +502,22 @@ bool NotificationData::init(
});
};
_title = title.toStdString();
_imageKey = GetImageKey(CurrentServerInformationValue().specVersion);
if (capabilities.contains(u"body-markup"_q)) {
_title = title.toStdString();
_body = subtitle.isEmpty()
? msg.toHtmlEscaped().toStdString()
: u"<b>%1</b>\n%2"_q.arg(
subtitle.toHtmlEscaped(),
msg.toHtmlEscaped()).toStdString();
} else {
_body = subtitle.isEmpty()
? msg.toStdString()
: u"%1\n%2"_q.arg(subtitle, msg).toStdString();
_title = subtitle.isEmpty()
? title.toStdString()
: subtitle.toStdString() + " (" + title.toStdString() + ')';
_body = msg.toStdString();
}
if (capabilities.contains("actions")) {
@@ -529,12 +536,13 @@ bool NotificationData::init(
_actions.push_back(
tr::lng_notification_reply(tr::now).toStdString());
_notificationRepliedSignalId = _dbusConnection->signal_subscribe(
signalEmitted,
std::string(kService),
std::string(kInterface),
"NotificationReplied",
std::string(kObjectPath));
_notificationRepliedSignalId =
_dbusConnection->signal_subscribe(
signalEmitted,
std::string(kService),
std::string(kInterface),
"NotificationReplied",
std::string(kObjectPath));
} else {
// icon name according to https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html
_actions.push_back("mail-reply-sender");
@@ -818,8 +826,6 @@ bool ByDefault() {
static const auto NeededCapabilities = {
// To show message content
u"body"_q,
// To make the sender name bold
u"body-markup"_q,
// To have buttons on notifications
u"actions"_q,
// To have quick reply
@@ -892,7 +898,8 @@ void Create(Window::Notifications::System *system) {
return;
}
GetServerInformation([=](const std::optional<ServerInformation> &result) {
GetServerInformation([=](
const std::optional<ServerInformation> &result) {
CurrentServerInformation = result;
oneReady();
});

View File

@@ -264,7 +264,8 @@ void LaunchGApplication() {
if (ranges::contains(
activatableNames,
"org.freedesktop.Notifications")) {
"org.freedesktop.Notifications",
&Glib::ustring::raw)) {
return true;
}

View File

@@ -1055,7 +1055,9 @@ void SetupDataStorage(
auto pathtext = Core::App().settings().downloadPathValue(
) | rpl::map([](const QString &text) {
if (text.isEmpty()) {
return tr::lng_download_path_default(tr::now);
return Core::App().canReadDefaultDownloadPath(true)
? tr::lng_download_path_default(tr::now)
: tr::lng_download_path_unset(tr::now);
} else if (text == FileDialog::Tmp()) {
return tr::lng_download_path_temp(tr::now);
}

View File

@@ -280,22 +280,27 @@ void SetupPrivacy(
{ &st::settingsIconOnline, kIconLightBlue },
Key::LastSeen,
[=] { return std::make_unique<LastSeenPrivacyController>(session); });
add(
tr::lng_settings_profile_photo_privacy(),
{ &st::settingsIconAccount, kIconRed },
Key::ProfilePhoto,
[] { return std::make_unique<ProfilePhotoPrivacyController>(); });
add(
tr::lng_settings_forwards_privacy(),
{ &st::settingsIconForward, kIconLightOrange },
Key::Forwards,
[=] { return std::make_unique<ForwardsPrivacyController>(
controller); });
add(
tr::lng_settings_profile_photo_privacy(),
{ &st::settingsIconAccount, kIconRed },
Key::ProfilePhoto,
[] { return std::make_unique<ProfilePhotoPrivacyController>(); });
add(
tr::lng_settings_calls(),
{ &st::settingsIconVideoCalls, kIconGreen },
Key::Calls,
[] { return std::make_unique<CallsPrivacyController>(); });
add(
tr::lng_settings_groups_invite(),
{ &st::settingsIconGroup, kIconDarkBlue },
Key::Invites,
[] { return std::make_unique<GroupsInvitePrivacyController>(); });
AddPremiumPrivacyButton(
controller,
container,
@@ -303,16 +308,11 @@ void SetupPrivacy(
{ &st::settingsPremiumIconVoice, kIconRed },
Key::Voices,
[=] { return std::make_unique<VoicesPrivacyController>(session); });
add(
tr::lng_settings_groups_invite(),
{ &st::settingsIconGroup, kIconDarkBlue },
Key::Invites,
[] { return std::make_unique<GroupsInvitePrivacyController>(); });
session->api().userPrivacy().reload(Api::UserPrivacy::Key::AddedByPhone);
AddSkip(container, st::settingsPrivacySecurityPadding);
AddDividerText(container, tr::lng_settings_group_privacy_about());
AddDivider(container);
}
void SetupArchiveAndMute(
@@ -865,10 +865,10 @@ void PrivacySecurity::setupContent(
return rpl::duplicate(updateOnTick);
};
SetupPrivacy(controller, content, trigger());
SetupSecurity(controller, content, trigger(), [=](Type type) {
_showOther.fire_copy(type);
});
SetupPrivacy(controller, content, trigger());
#if !defined OS_MAC_STORE && !defined OS_WIN_STORE
SetupSensitiveContent(controller, content, trigger());
#else // !OS_MAC_STORE && !OS_WIN_STORE

View File

@@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "ui/boxes/confirm_phone_box.h"
#include "core/file_utilities.h"
#include "ui/boxes/confirm_box.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h"
@@ -22,10 +23,20 @@ ConfirmPhoneBox::ConfirmPhoneBox(
QWidget*,
const QString &phone,
int codeLength,
const QString &openUrl,
std::optional<int> timeout)
: _phone(phone)
, _sentCodeLength(codeLength)
, _call([this] { sendCall(); }, [this] { update(); }) {
, _call([=] { sendCall(); }, [=] { update(); }) {
if (!openUrl.isEmpty()) {
_fragment.create(
this,
tr::lng_intro_fragment_button(),
st::fragmentBoxButton);
_fragment->setClickedCallback([=] { File::OpenUrl(openUrl); });
_fragment->setTextTransform(
Ui::RoundButton::TextTransform::NoTransform);
}
if (timeout) {
_call.setStatus({ Ui::SentCodeCall::State::Waiting, *timeout });
}
@@ -59,7 +70,8 @@ void ConfirmPhoneBox::prepare() {
+ _code->height()
+ st::usernameSkip
+ _about->height()
+ st::usernameSkip);
+ st::usernameSkip
+ (_fragment ? (_fragment->height() + fragmentSkip()) : 0));
connect(_code, &Ui::InputField::submitted, [=] { sendCode(); });
@@ -132,15 +144,27 @@ void ConfirmPhoneBox::resizeEvent(QResizeEvent *e) {
_code->height());
_code->moveToLeft(st::usernamePadding.left(), st::usernamePadding.top());
_about->moveToLeft(
st::usernamePadding.left(),
_code->y() + _code->height() + st::usernameSkip);
if (_fragment) {
_fragment->setFullWidth(_code->width());
_fragment->moveToLeft(
(width() - _fragment->width()) / 2,
_code->y() + _code->height() + st::usernameSkip);
}
const auto aboutTop = _fragment
? (_fragment->y() + _fragment->height() + fragmentSkip())
: (_code->y() + _code->height() + st::usernameSkip);
_about->moveToLeft(st::usernamePadding.left(), aboutTop);
}
void ConfirmPhoneBox::setInnerFocus() {
_code->setFocusFast();
}
int ConfirmPhoneBox::fragmentSkip() const {
return st::usernamePadding.bottom();
}
rpl::producer<QString> ConfirmPhoneBox::checkRequests() const {
return _checkRequests.events();
}

View File

@@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Ui {
class FlatLabel;
class RoundButton;
class ConfirmPhoneBox final : public Ui::BoxContent {
public:
@@ -20,6 +21,7 @@ public:
QWidget*,
const QString &phone,
int codeLength,
const QString &openUrl,
std::optional<int> timeout);
[[nodiscard]] rpl::producer<QString> checkRequests() const;
@@ -40,6 +42,8 @@ private:
void sendCall();
void checkPhoneAndHash();
[[nodiscard]] int fragmentSkip() const;
QString getPhone() const;
void showError(const QString &error);
@@ -54,6 +58,7 @@ private:
object_ptr<Ui::FlatLabel> _about = { nullptr };
object_ptr<Ui::SentCodeField> _code = { nullptr };
object_ptr<Ui::RoundButton> _fragment = { nullptr };
QString _error;
Ui::SentCodeCall _call;

View File

@@ -262,7 +262,7 @@ void GroupCallUserpics::validateCache(Userpic &userpic) {
{
auto p = QPainter(&userpic.cache);
const auto skip = (kWideScale - 1) / 2 * size;
p.drawImage(skip, skip, userpic.data.userpic);
p.drawImage(QRect(skip, skip, size, size), userpic.data.userpic);
if (userpic.cacheMasked) {
auto hq = PainterHighQualityEnabler(p);

View File

@@ -91,7 +91,6 @@ void CameraBox(
},
std::move(callback),
track->frame(FrameRequest()).mirrored(true, false));
box->closeBox();
};
box->setTitle(tr::lng_profile_camera_title());
@@ -208,13 +207,13 @@ void UserpicButton::prepare() {
prepareUserpicPixmap();
}
setClickHandlerByRole();
}
if (_role == Role::ChangePhoto) {
chosenImages(
) | rpl::start_with_next([=](ChosenImage &&chosen) {
showCustom(std::move(chosen.image));
}, lifetime());
}
void UserpicButton::showCustomOnChosen() {
chosenImages(
) | rpl::start_with_next([=](ChosenImage &&chosen) {
showCustom(std::move(chosen.image));
}, lifetime());
}
void UserpicButton::requestSuggestAvailability() {
@@ -274,10 +273,12 @@ void UserpicButton::choosePhotoLocally() {
const auto user = _peer ? _peer->asUser() : nullptr;
const auto name = (user && !user->firstName.isEmpty())
? user->firstName
: _peer->name();
: _peer
? _peer->name()
: QString();
const auto phrase = (type == ChosenType::Suggest)
? &tr::lng_profile_suggest_sure
: (_peer->isUser() && !_peer->isSelf())
: (user && !user->isSelf())
? &tr::lng_profile_set_personal_sure
: nullptr;
PrepareProfilePhotoFromFile(

View File

@@ -100,6 +100,7 @@ public:
void showCustom(QImage &&image);
void showSource(Source source);
void showCustomOnChosen();
void overrideHasPersonalPhoto(bool has);
[[nodiscard]] rpl::producer<> resetPersonalRequests() const;

View File

@@ -10,7 +10,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h"
#include "countries/countries_instance.h"
#include <QRegularExpression>
#include <QtCore/QLocale>
#include <locale>
#include <sstream>

View File

@@ -134,6 +134,12 @@ void PhonePartInput::correctValue(
int wasCursor,
QString &now,
int &nowCursor) {
if (!now.isEmpty() && (_lastDigits != now)) {
_lastDigits = now;
_lastDigits.replace(TextUtilities::RegExpDigitsExclude(), QString());
updatePattern(_groupsCallback(_code + _lastDigits));
}
QString newText;
int oldPos(nowCursor), newPos(-1), oldLen(now.length()), digitCount = 0;
for (int i = 0; i < oldLen; ++i) {
@@ -212,21 +218,8 @@ void PhonePartInput::addedToNumber(const QString &added) {
}
void PhonePartInput::chooseCode(const QString &code) {
_pattern = _groupsCallback(code);
if (!_pattern.isEmpty() && _pattern.at(0) == code.size()) {
_pattern.pop_front();
} else {
_pattern.clear();
}
_additionalPlaceholder = QString();
if (!_pattern.isEmpty()) {
_additionalPlaceholder.reserve(20);
for (const auto part : std::as_const(_pattern)) {
_additionalPlaceholder.append(' ');
_additionalPlaceholder.append(QString(part, QChar(0x2212)));
}
}
setPlaceholderHidden(!_additionalPlaceholder.isEmpty());
_code = code;
updatePattern(_groupsCallback(_code));
auto wasText = getLastText();
auto wasCursor = cursorPosition();
@@ -239,6 +232,27 @@ void PhonePartInput::chooseCode(const QString &code) {
update();
}
void PhonePartInput::updatePattern(QVector<int> &&pattern) {
if (_pattern == pattern) {
return;
}
_pattern = std::move(pattern);
if (!_pattern.isEmpty() && _pattern.at(0) == _code.size()) {
_pattern.pop_front();
} else {
_pattern.clear();
}
_additionalPlaceholder = QString();
if (!_pattern.isEmpty()) {
_additionalPlaceholder.reserve(20);
for (const auto &part : _pattern) {
_additionalPlaceholder.append(' ');
_additionalPlaceholder.append(QString(part, QChar(0x2212)));
}
}
setPlaceholderHidden(!_additionalPlaceholder.isEmpty());
}
UsernameInput::UsernameInput(
QWidget *parent,
const style::InputField &st,
@@ -345,7 +359,7 @@ void PhoneInput::correctValue(
QString &now,
int &nowCursor) {
auto digits = now;
digits.replace(QRegularExpression("[^\\d]"), QString());
digits.replace(TextUtilities::RegExpDigitsExclude(), QString());
_pattern = _groupsCallback(digits);
QString newPlaceholder;

View File

@@ -68,6 +68,10 @@ protected:
void paintAdditionalPlaceholder(QPainter &p) override;
private:
void updatePattern(QVector<int> &&pattern);
QString _code;
QString _lastDigits;
QVector<int> _pattern;
QString _additionalPlaceholder;
rpl::event_stream<not_null<QKeyEvent*>> _frontBackspaceEvent;

View File

@@ -34,9 +34,7 @@ void SentCodeField::setChangedCallback(Fn<void()> changedCallback) {
QString SentCodeField::getDigitsOnly() const {
return QString(
getLastText()
).remove(
QRegularExpression("[^\\d]")
);
).remove(TextUtilities::RegExpDigitsExclude());
}
void SentCodeField::fix() {

View File

@@ -956,8 +956,12 @@ OthersUnreadState OtherAccountsUnreadStateCurrent() {
}
}
}
// In case we are logging out in the last paint for the slide animation
// the account doesn't have the session here already.
const auto current = active->maybeSession();
return {
.count = (app.unreadBadge() - active->session().data().unreadBadge()),
.count = (app.unreadBadge()
- (current ? current->data().unreadBadge() : 0)),
.allMuted = allMuted,
};
}

View File

@@ -4,6 +4,7 @@
#define MyAppURL "https://desktop.telegram.org"
#define MyAppExeName "Telegram.exe"
#define MyAppId "53F49750-6209-4FBF-9CA8-7A333C87D1ED"
#define CurrentYear GetDateTimeString('yyyy','','')
[Setup]
; NOTE: The value of AppId uniquely identifies this application.
@@ -12,6 +13,7 @@
AppId={{{#MyAppId}}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppCopyright={#MyAppPublisher} 2014-{#CurrentYear}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
@@ -33,27 +35,29 @@ DisableDirPage=no
DisableProgramGroupPage=no
#if MyBuildTarget == "win64"
ArchitecturesAllowed="x64 arm64"
ArchitecturesInstallIn64BitMode="x64 arm64"
OutputBaseFilename=tsetup-x64.{#MyAppVersionFull}
#define ArchModulesFolder "x64"
ArchitecturesAllowed="x64 arm64"
ArchitecturesInstallIn64BitMode="x64 arm64"
OutputBaseFilename=tsetup-x64.{#MyAppVersionFull}
#define ArchModulesFolder "x64"
AppVerName={#MyAppName} {#MyAppVersion} 64bit
#else
OutputBaseFilename=tsetup.{#MyAppVersionFull}
#define ArchModulesFolder "x86"
OutputBaseFilename=tsetup.{#MyAppVersionFull}
#define ArchModulesFolder "x86"
AppVerName={#MyAppName} {#MyAppVersion} 32bit
#endif
#define ModulesFolder "modules\" + ArchModulesFolder
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
Name: "it"; MessagesFile: "compiler:Languages\Italian.isl"
Name: "es"; MessagesFile: "compiler:Languages\Spanish.isl"
Name: "de"; MessagesFile: "compiler:Languages\German.isl"
Name: "nl"; MessagesFile: "compiler:Languages\Dutch.isl"
Name: "pt_BR"; MessagesFile: "compiler:Languages\BrazilianPortuguese.isl"
Name: "ru"; MessagesFile: "compiler:Languages\Russian.isl"
Name: "fr"; MessagesFile: "compiler:Languages\French.isl"
Name: "ua"; MessagesFile: "compiler:Languages\Ukrainian.isl"
Name: "it"; MessagesFile: "compiler:Languages\Italian.isl"
Name: "es"; MessagesFile: "compiler:Languages\Spanish.isl"
Name: "de"; MessagesFile: "compiler:Languages\German.isl"
Name: "nl"; MessagesFile: "compiler:Languages\Dutch.isl"
Name: "pt_BR"; MessagesFile: "compiler:Languages\BrazilianPortuguese.isl"
Name: "ru"; MessagesFile: "compiler:Languages\Russian.isl"
Name: "fr"; MessagesFile: "compiler:Languages\French.isl"
Name: "ua"; MessagesFile: "compiler:Languages\Ukrainian.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"

View File

@@ -1,7 +1,7 @@
AppVersion 4004002
AppVersion 4004003
AppVersionStrMajor 4.4
AppVersionStrSmall 4.4.2
AppVersionStr 4.4.2
AppVersionStrSmall 4.4.3
AppVersionStr 4.4.3
BetaChannel 1
AlphaVersion 0
AppVersionOriginal 4.4.2.beta
AppVersionOriginal 4.4.3.beta

View File

@@ -1,3 +1,9 @@
4.4.3 beta (29.12.22)
- Support for anonymous numbers from the Fragment.com platform.
- Fix a crash in own profile photo updating.
- Bug fixes and other minor improvements.
4.4.2 beta (28.12.22)
- Send photos and video files hidden by a spoiler effect.

View File

@@ -28,6 +28,7 @@
<url type="homepage">https://desktop.telegram.org/</url>
<url type="bugtracker">https://github.com/telegramdesktop/tdesktop/issues</url>
<url type="translate">https://translations.telegram.org/</url>
<url type="contribute">https://github.com/telegramdesktop/tdesktop/blob/dev/.github/CONTRIBUTING.md</url>
<screenshots>
<screenshot type="default">
<image>https://raw.githubusercontent.com/telegramdesktop/tdesktop/dev/docs/assets/preview.png</image>
@@ -43,6 +44,15 @@
<keyword>sms</keyword>
<keyword>im</keyword>
</keywords>
<requires>
<display_length compare="ge">medium</display_length>
<internet>always</internet>
</requires>
<supports>
<control>pointing</control>
<control>keyboard</control>
<control>touch</control>
</supports>
<content_rating type="oars-1.1">
<content_attribute id="violence-cartoon">none</content_attribute>
<content_attribute id="violence-fantasy">none</content_attribute>