Compare commits

...

12 Commits

Author SHA1 Message Date
John Preston
b0077d98f0 Version 1.3.7: Fix file dialog parent widget.
Regression was introduced in 67ea175fc6.

Fixes #4817.
2018-06-11 23:40:30 +03:00
John Preston
b5bc7a22af Version 1.3.7: Possible bug fix.
Attempt to fix strange crash in SPMediaKeyTap.
2018-06-11 22:31:44 +03:00
John Preston
e60311811b Version 1.3.7.
- Push fixes to stable version.
2018-06-11 22:28:34 +03:00
John Preston
8700c1b08f Alpha version 1.3.6: Make it another alpha. 2018-06-11 10:42:20 +03:00
John Preston
d8b51670e7 Version 1.3.6.
- Bug fixes and other minor improvements.
2018-06-11 10:39:59 +03:00
John Preston
68c2f563c6 Write logs without QTextStream. 2018-06-11 10:37:29 +03:00
John Preston
bf775cb4ca Fix history items cleanup. 2018-06-09 11:52:37 +03:00
John Preston
5c4b81434e Alpha version 1.3.5.
- Bug fixes and other minor improvements.
2018-06-08 23:12:00 +03:00
John Preston
cd1c7c56d3 Skip old and currently-sending draft updates. 2018-06-08 23:06:26 +03:00
John Preston
427ceb9a9a Submit MuteSettingsBox by Enter. 2018-06-08 22:26:23 +03:00
John Preston
2a110f0d3e Improve passport styles. 2018-06-08 22:26:08 +03:00
John Preston
d0ed75f3b5 Update langs. 2018-06-08 21:32:20 +03:00
27 changed files with 273 additions and 146 deletions

View File

@@ -1567,7 +1567,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_passport_address_agreement" = "Tenancy agreement";
"lng_passport_address_agreement_upload" = "Upload a scan of your tenancy agreement";
"lng_passport_address_registration" = "Passport registration";
"lng_passport_address_registration_upload" = "Upload a scan of your passport registration";
"lng_passport_address_registration_upload" = "Upload a scan of your passport registration page";
"lng_passport_address_temporary" = "Temporary registration";
"lng_passport_address_temporary_upload" = "Upload a scan of your temporary registration";
"lng_passport_address_about" = "To confirm your address, please upload a scan or photo of the selected document (all pages).";
@@ -1594,12 +1594,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_passport_upload_selfie" = "Upload selfie";
"lng_passport_front_side_title" = "Front side";
"lng_passport_front_side_name" = "Scan";
"lng_passport_front_side_description" = "Upload front side of your document.";
"lng_passport_upload_front_side" = "Upload front side scan";
"lng_passport_front_side_description" = "Upload the front side of your document.";
"lng_passport_upload_front_side" = "Upload a scan of the front side";
"lng_passport_reverse_side_title" = "Reverse side";
"lng_passport_reverse_side_name" = "Scan";
"lng_passport_reverse_side_description" = "Upload reverse side of your document.";
"lng_passport_upload_reverse_side" = "Upload reverse side scan";
"lng_passport_reverse_side_description" = "Upload the reverse side of your document.";
"lng_passport_upload_reverse_side" = "Upload a scan of the reverse side";
"lng_passport_personal_details" = "Personal details";
"lng_passport_personal_details_enter" = "Enter your personal details";
"lng_passport_choose_image" = "Choose scan image";
@@ -1648,10 +1648,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_passport_stop" = "Stop";
"lng_passport_restart_sure" = "An unexpected error has occurred. Perhaps some changes were made from a different Telegram application. Would you like to restart this authorization?";
"lng_passport_restart" = "Restart";
"lng_passport_error_too_large" = "This file is too large.";
"lng_passport_error_bad_size" = "This image has bad dimensions.";
"lng_passport_error_too_large" = "Sorry, this file is too large.";
"lng_passport_error_bad_size" = "Sorry, this image has wrong dimensions.";
"lng_passport_error_cant_read" = "Can't read this file. Please choose an image.";
"lng_passport_bad_name" = "Use latin characters only.";
"lng_passport_bad_name" = "Please use latin characters only.";
// Wnd specific

View File

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

View File

@@ -34,8 +34,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,3,4,0
PRODUCTVERSION 1,3,4,0
FILEVERSION 1,3,7,0
PRODUCTVERSION 1,3,7,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -52,10 +52,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileDescription", "Telegram Desktop"
VALUE "FileVersion", "1.3.4.0"
VALUE "FileVersion", "1.3.7.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2018"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "1.3.4.0"
VALUE "ProductVersion", "1.3.7.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,3,4,0
PRODUCTVERSION 1,3,4,0
FILEVERSION 1,3,7,0
PRODUCTVERSION 1,3,7,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -43,10 +43,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileDescription", "Telegram Desktop Updater"
VALUE "FileVersion", "1.3.4.0"
VALUE "FileVersion", "1.3.7.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2018"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "1.3.4.0"
VALUE "ProductVersion", "1.3.7.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -2055,10 +2055,21 @@ void ApiWrap::saveDraftsToCloud() {
if (!textWithTags.tags.isEmpty()) {
flags |= MTPmessages_SaveDraft::Flag::f_entities;
}
auto entities = TextUtilities::EntitiesToMTP(ConvertTextTagsToEntities(textWithTags.tags), TextUtilities::ConvertOption::SkipLocal);
auto entities = TextUtilities::EntitiesToMTP(
ConvertTextTagsToEntities(textWithTags.tags),
TextUtilities::ConvertOption::SkipLocal);
cloudDraft->saveRequestId = request(MTPmessages_SaveDraft(MTP_flags(flags), MTP_int(cloudDraft->msgId), history->peer->input, MTP_string(textWithTags.text), entities)).done([this, history](const MTPBool &result, mtpRequestId requestId) {
if (auto cloudDraft = history->cloudDraft()) {
history->setSentDraftText(textWithTags.text);
cloudDraft->saveRequestId = request(MTPmessages_SaveDraft(
MTP_flags(flags),
MTP_int(cloudDraft->msgId),
history->peer->input,
MTP_string(textWithTags.text),
entities
)).done([=](const MTPBool &result, mtpRequestId requestId) {
history->clearSentDraftText();
if (const auto cloudDraft = history->cloudDraft()) {
if (cloudDraft->saveRequestId == requestId) {
cloudDraft->saveRequestId = 0;
history->draftSavedToCloud();
@@ -2069,8 +2080,10 @@ void ApiWrap::saveDraftsToCloud() {
_draftsSaveRequestIds.erase(history);
checkQuitPreventFinished();
}
}).fail([this, history](const RPCError &error, mtpRequestId requestId) {
if (auto cloudDraft = history->cloudDraft()) {
}).fail([=](const RPCError &error, mtpRequestId requestId) {
history->clearSentDraftText();
if (const auto cloudDraft = history->cloudDraft()) {
if (cloudDraft->saveRequestId == requestId) {
history->clearCloudDraft();
}

View File

@@ -50,8 +50,7 @@ namespace {
UserData *self = nullptr;
using PeersData = QHash<PeerId, PeerData*>;
PeersData peersData;
std::unordered_map<PeerId, std::unique_ptr<PeerData>> peersData;
using LocationsData = QHash<LocationCoords, LocationData*>;
LocationsData locationsData;
@@ -747,7 +746,7 @@ namespace App {
} else if (chat->version <= d.vversion.v && chat->count > 0) {
chat->version = d.vversion.v;
auto canEdit = chat->canEdit();
UserData *user = App::userLoaded(d.vuser_id.v);
const auto user = App::userLoaded(d.vuser_id.v);
if (user) {
if (chat->participants.empty()) {
if (chat->count > 0) {
@@ -1074,40 +1073,43 @@ namespace App {
}
PeerData *peer(const PeerId &id, PeerData::LoadedStatus restriction) {
if (!id) return nullptr;
if (!id) {
return nullptr;
}
auto i = peersData.constFind(id);
auto i = peersData.find(id);
if (i == peersData.cend()) {
PeerData *newData = nullptr;
if (peerIsUser(id)) {
newData = new UserData(id);
} else if (peerIsChat(id)) {
newData = new ChatData(id);
} else if (peerIsChannel(id)) {
newData = new ChannelData(id);
}
Assert(newData != nullptr);
auto newData = [&]() -> std::unique_ptr<PeerData> {
if (peerIsUser(id)) {
return std::make_unique<UserData>(id);
} else if (peerIsChat(id)) {
return std::make_unique<ChatData>(id);
} else if (peerIsChannel(id)) {
return std::make_unique<ChannelData>(id);
}
Unexpected("Peer id type.");
}();
newData->input = MTPinputPeer(MTP_inputPeerEmpty());
i = peersData.insert(id, newData);
i = peersData.emplace(id, std::move(newData)).first;
}
switch (restriction) {
case PeerData::MinimalLoaded: {
if (i.value()->loadedStatus == PeerData::NotLoaded) {
if (i->second->loadedStatus == PeerData::NotLoaded) {
return nullptr;
}
} break;
case PeerData::FullLoaded: {
if (i.value()->loadedStatus != PeerData::FullLoaded) {
if (i->second->loadedStatus != PeerData::FullLoaded) {
return nullptr;
}
} break;
}
return i.value();
return i->second.get();
}
void enumerateUsers(Fn<void(not_null<UserData*>)> action) {
for_const (const auto peer, peersData) {
for (const auto &[peerId, peer] : peersData) {
if (const auto user = peer->asUser()) {
action(user);
}
@@ -1116,9 +1118,9 @@ namespace App {
void enumerateChatsChannels(
Fn<void(not_null<PeerData*>)> action) {
for_const (const auto peer, peersData) {
for (const auto &[peerId, peer] : peersData) {
if (!peer->isUser()) {
action(peer);
action(peer.get());
}
}
}
@@ -1128,10 +1130,10 @@ namespace App {
}
PeerData *peerByName(const QString &username) {
QString uname(username.trimmed());
for_const (PeerData *peer, peersData) {
const auto uname = username.trimmed();
for (const auto &[peerId, peer] : peersData) {
if (!peer->userName().compare(uname, Qt::CaseInsensitive)) {
return peer;
return peer.get();
}
}
return nullptr;
@@ -1246,24 +1248,16 @@ namespace App {
void historyClearMsgs() {
::dependentItems.clear();
QVector<HistoryItem*> toDelete;
for_const (auto item, msgsData) {
if (!item->mainView()) {
toDelete.push_back(item);
}
}
for_const (auto &chMsgsData, channelMsgsData) {
for_const (auto item, chMsgsData) {
if (!item->mainView()) {
toDelete.push_back(item);
}
}
}
msgsData.clear();
channelMsgsData.clear();
for_const (auto item, toDelete) {
const auto oldData = base::take(msgsData);
const auto oldChannelData = base::take(channelMsgsData);
for (const auto item : oldData) {
delete item;
}
for (const auto &data : oldChannelData) {
for (const auto item : data) {
delete item;
}
}
clearMousedItems();
}
@@ -1275,10 +1269,7 @@ namespace App {
cSetSavedPeersByTime(SavedPeersByTime());
cSetRecentInlineBots(RecentInlineBots());
for_const (auto peer, ::peersData) {
delete peer;
}
::peersData.clear();
peersData.clear();
if (AuthSession::Exists()) {
Auth().api().clearWebPageRequests();

View File

@@ -21,6 +21,10 @@ constexpr auto kForeverHours = 24 * 365;
} // namespace
MuteSettingsBox::MuteSettingsBox(QWidget *parent, not_null<PeerData*> peer)
: _peer(peer) {
}
void MuteSettingsBox::prepare() {
setTitle(langFactory(lng_disable_notifications_from_tray));
auto y = 0;
@@ -67,15 +71,25 @@ void MuteSettingsBox::prepare() {
- st::boxOptionListSkip
+ st::defaultCheckbox.margin.bottom();
addButton(langFactory(lng_box_ok), [this, group] {
auto muteForSeconds = group->value() * 3600;
_save = [=] {
const auto muteForSeconds = group->value() * 3600;
Auth().data().updateNotifySettings(
_peer,
muteForSeconds);
closeBox();
});
};
addButton(langFactory(lng_box_ok), _save);
addButton(langFactory(lng_cancel), [this] { closeBox(); });
setDimensions(st::boxWidth, y);
}
void MuteSettingsBox::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
if (_save) {
_save();
}
}
}
// vi: ts=4 tw=80

View File

@@ -13,17 +13,17 @@ Copyright (C) 2017, Nicholas Guriev <guriev-ns@ya.ru>
* turning off notifications from a chat. The widget is opened by a context menu
* in the left list of dialogues. */
class MuteSettingsBox : public BoxContent {
Q_OBJECT
public:
MuteSettingsBox(QWidget *parent, not_null<PeerData*> peer);
public:
MuteSettingsBox(QWidget *parent, not_null<PeerData*> peer)
: _peer(peer) {
}
protected:
protected:
void prepare() override;
private:
void keyPressEvent(QKeyEvent *e) override;
private:
not_null<PeerData*> _peer;
Fn<void()> _save;
};
// vi: ts=4 tw=80

View File

@@ -82,9 +82,6 @@ enum {
MaxMessageSize = 4096,
WriteMapTimeout = 1000,
SaveDraftTimeout = 1000, // save draft after 1 secs of not changing text
SaveDraftAnywayTimeout = 5000, // or save anyway each 5 secs
SaveCloudDraftIdleTimeout = 14000, // save draft to the cloud after 14 more seconds
SetOnlineAfterActivity = 30, // user with hidden last seen stays online for such amount of seconds in the interface

View File

@@ -11,7 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#define BETA_VERSION_MACRO (0ULL)
constexpr int AppVersion = 1003004;
constexpr str_const AppVersionStr = "1.3.4";
constexpr bool AppAlphaVersion = true;
constexpr int AppVersion = 1003007;
constexpr str_const AppVersionStr = "1.3.7";
constexpr bool AppAlphaVersion = false;
constexpr uint64 AppBetaVersion = BETA_VERSION_MACRO;

View File

@@ -52,6 +52,9 @@ void applyPeerCloudDraft(PeerId peerId, const MTPDdraftMessage &draft) {
? TextUtilities::EntitiesFromMTP(draft.ventities.v)
: EntitiesInText())
};
if (history->skipCloudDraft(textWithTags.text, draft.vdate.v)) {
return;
}
auto replyTo = draft.has_reply_to_msg_id() ? draft.vreply_to_msg_id.v : MsgId(0);
auto cloudDraft = std::make_unique<Draft>(textWithTags, replyTo, MessageCursor(QFIXED_MAX, QFIXED_MAX, QFIXED_MAX), draft.is_no_webpage());
cloudDraft->date = draft.vdate.v;

View File

@@ -51,6 +51,7 @@ constexpr auto kStatusShowClientsideChooseContact = 6000;
constexpr auto kStatusShowClientsidePlayGame = 10000;
constexpr auto kSetMyActionForMs = 10000;
constexpr auto kNewBlockEachMessage = 50;
constexpr auto kSkipCloudDraftsFor = TimeId(3);
void checkForSwitchInlineButton(HistoryItem *item) {
if (item->out() || !item->hasSwitchInlineButton()) {
@@ -98,8 +99,10 @@ not_null<History*> Histories::findOrInsert(PeerId peerId) {
}
void Histories::clear() {
for (const auto &[peerId, history] : _map) {
history->unloadBlocks();
}
App::historyClearMsgs();
_map.clear();
_unreadFull = _unreadMuted = 0;
@@ -405,6 +408,24 @@ Data::Draft *History::createCloudDraft(Data::Draft *fromDraft) {
return cloudDraft();
}
bool History::skipCloudDraft(const QString &text, TimeId date) const {
if (_lastSentDraftText && *_lastSentDraftText == text) {
return true;
} else if (date <= _lastSentDraftTime + kSkipCloudDraftsFor) {
return true;
}
return false;
}
void History::setSentDraftText(const QString &text) {
_lastSentDraftText = text;
}
void History::clearSentDraftText() {
_lastSentDraftText = base::none;
accumulate_max(_lastSentDraftTime, unixtime());
}
void History::setEditDraft(std::unique_ptr<Data::Draft> &&draft) {
_editDraft = std::move(draft);
}

View File

@@ -304,6 +304,9 @@ public:
void createLocalDraftFromCloud();
void setCloudDraft(std::unique_ptr<Data::Draft> &&draft);
Data::Draft *createCloudDraft(Data::Draft *fromDraft);
bool skipCloudDraft(const QString &text, TimeId date) const;
void setSentDraftText(const QString &text);
void clearSentDraftText();
void setEditDraft(std::unique_ptr<Data::Draft> &&draft);
void clearLocalDraft();
void clearCloudDraft();
@@ -501,6 +504,8 @@ private:
std::unique_ptr<Data::Draft> _localDraft, _cloudDraft;
std::unique_ptr<Data::Draft> _editDraft;
base::optional<QString> _lastSentDraftText;
TimeId _lastSentDraftTime = 0;
MessageIdsList _forwardDraft;
using TypingUsers = QMap<UserData*, TimeMs>;

View File

@@ -91,6 +91,9 @@ constexpr auto kShowMembersDropdownTimeoutMs = 300;
constexpr auto kDisplayEditTimeWarningMs = 300 * 1000;
constexpr auto kFullDayInMs = 86400 * 1000;
constexpr auto kCancelTypingActionTimeout = TimeMs(5000);
constexpr auto kSaveDraftTimeout = 1000;
constexpr auto kSaveDraftAnywayTimeout = 5000;
constexpr auto kSaveCloudDraftIdleTimeout = 14000;
ApiWrap::RequestMessageDataCallback replyEditMessageDataCallback() {
return [](ChannelData *channel, MsgId msgId) {
@@ -1192,9 +1195,9 @@ void HistoryWidget::onDraftSave(bool delayed) {
auto ms = getms();
if (!_saveDraftStart) {
_saveDraftStart = ms;
return _saveDraftTimer.start(SaveDraftTimeout);
} else if (ms - _saveDraftStart < SaveDraftAnywayTimeout) {
return _saveDraftTimer.start(SaveDraftTimeout);
return _saveDraftTimer.start(kSaveDraftTimeout);
} else if (ms - _saveDraftStart < kSaveDraftAnywayTimeout) {
return _saveDraftTimer.start(kSaveDraftTimeout);
}
}
writeDrafts(nullptr, nullptr);
@@ -1275,7 +1278,7 @@ void HistoryWidget::writeDrafts(Data::Draft **localDraft, Data::Draft **editDraf
}
if (!_editMsgId && !_inlineBot) {
_saveCloudDraftTimer.start(SaveCloudDraftIdleTimeout);
_saveCloudDraftTimer.start(kSaveCloudDraftIdleTimeout);
}
}

View File

@@ -494,8 +494,9 @@ void TopBarWidget::updateControlsGeometry() {
buttonsWidth += buttonsLeft + st::topBarActionSkip * 3;
auto widthLeft = qMin(width() - buttonsWidth, -2 * st::defaultActiveButton.width);
_forward->setFullWidth(-(widthLeft / 2));
_delete->setFullWidth(-(widthLeft / 2));
auto buttonFullWidth = qMin(-(widthLeft / 2), 0);
_forward->setFullWidth(buttonFullWidth);
_delete->setFullWidth(buttonFullWidth);
selectedButtonsTop += (height() - _forward->height()) / 2;

View File

@@ -69,9 +69,9 @@ public:
void closeMain() {
QMutexLocker lock(_logsMutex(LogDataMain));
if (files[LogDataMain]) {
streams[LogDataMain].setDevice(0);
files[LogDataMain]->close();
const auto file = files[LogDataMain].get();
if (file && file->isOpen()) {
file->close();
}
}
@@ -80,11 +80,12 @@ public:
}
QString full() {
if (!streams[LogDataMain].device()) {
const auto file = files[LogDataMain].get();
if (!!file || !file->isOpen()) {
return QString();
}
QFile out(files[LogDataMain]->fileName());
QFile out(file->fileName());
if (out.open(QIODevice::ReadOnly)) {
return QString::fromUtf8(out.readAll());
}
@@ -93,27 +94,29 @@ public:
void write(LogDataType type, const QString &msg) {
QMutexLocker lock(_logsMutex(type));
if (type != LogDataMain) reopenDebug();
if (!streams[type].device()) return;
streams[type] << msg;
streams[type].flush();
if (type != LogDataMain) {
reopenDebug();
}
const auto file = files[type].get();
if (!file || !file->isOpen()) {
return;
}
file->write(msg.toUtf8());
file->flush();
}
private:
std::unique_ptr<QFile> files[LogDataCount];
QTextStream streams[LogDataCount];
int32 part = -1;
bool reopen(LogDataType type, int32 dayIndex, const QString &postfix) {
if (streams[type].device()) {
if (files[type] && files[type]->isOpen()) {
if (type == LogDataMain) {
if (!postfix.isEmpty()) {
return true;
}
} else {
streams[type].setDevice(0);
files[type]->close();
}
}
@@ -134,8 +137,6 @@ private:
}
if (to->open(mode | QIODevice::Append)) {
std::swap(files[type], to);
streams[type].setDevice(files[type].get());
streams[type].setCodec("UTF-8");
LOG(("Moved logging from '%1' to '%2'!").arg(to->fileName()).arg(files[type]->fileName()));
to->remove();
@@ -192,17 +193,14 @@ private:
}
}
if (files[type]->open(mode)) {
streams[type].setDevice(files[type].get());
streams[type].setCodec("UTF-8");
if (type != LogDataMain) {
streams[type] << ((mode & QIODevice::Append)
files[type]->write(((mode & QIODevice::Append)
? qsl("\
----------------------------------------------------------------\n\
NEW LOGGING INSTANCE STARTED!!!\n\
----------------------------------------------------------------\n")
: qsl("%1\n").arg(dayIndex));
streams[type].flush();
: qsl("%1\n").arg(dayIndex)).toUtf8());
files[type]->flush();
}
return true;

View File

@@ -34,6 +34,7 @@ passportErrorLabel: FlatLabel(passportPasswordLabel) {
textFg: boxTextFgError;
}
passportVerifyErrorLabel: FlatLabel(passportErrorLabel) {
minWidth: 128px;
align: align(topleft);
}
@@ -169,10 +170,11 @@ passportDetailsField: InputField(defaultInputField) {
font: normalFont;
}
passportDetailsDateField: InputField(passportDetailsField) {
textMargins: margins(2px, 8px, 2px, 0px);
border: 0px;
borderActive: 0px;
heightMin: 30px;
placeholderFont: font(semibold 14px);
placeholderFont: semiboldFont;
placeholderFgActive: placeholderFgActive;
}
passportDetailsSeparator: FlatLabel(passportPasswordLabelBold) {
@@ -189,7 +191,7 @@ passportDetailsFieldLeft: 116px;
passportDetailsFieldTop: 2px;
passportDetailsFieldSkipMin: 12px;
passportDetailsSkip: 30px;
passportDetailsGenderSkip: 30px;
passportDetailsGenderSkip: 20px;
passportRequestTypeSkip: 16px;

View File

@@ -67,7 +67,7 @@ EditDocumentScheme GetDocumentScheme(
if (value.isEmpty() || value.size() > kMaxNameSize) {
return QString();
} else if (!QRegularExpression(
"^[a-zA-Z\\- ]+$"
"^[a-zA-Z0-9\\.,/&\\-' ]+$"
).match(value).hasMatch()) {
return lang(lng_passport_bad_name);
}

View File

@@ -78,6 +78,7 @@ public:
AbstractTextRow(
QWidget *parent,
const QString &label,
int maxLabelWidth,
const QString &value,
int limit);
@@ -101,6 +102,7 @@ public:
QWidget *parent,
not_null<PanelController*> controller,
const QString &label,
int maxLabelWidth,
const QString &value);
rpl::producer<QString> value() const override;
@@ -152,7 +154,11 @@ private:
class DateRow : public PanelDetailsRow {
public:
DateRow(QWidget *parent, const QString &label, const QString &value);
DateRow(
QWidget *parent,
const QString &label,
int maxLabelWidth,
const QString &value);
bool setFocusFast() override;
rpl::producer<QString> value() const override;
@@ -206,6 +212,7 @@ public:
GenderRow(
QWidget *parent,
const QString &label,
int maxLabelWidth,
const QString &value);
rpl::producer<QString> value() const override;
@@ -247,9 +254,10 @@ template <typename Input>
AbstractTextRow<Input>::AbstractTextRow(
QWidget *parent,
const QString &label,
int maxLabelWidth,
const QString &value,
int limit)
: PanelDetailsRow(parent, label)
: PanelDetailsRow(parent, label, maxLabelWidth)
, _field(this, st::passportDetailsField, nullptr, value)
, _value(value) {
_field->setMaxLength(limit);
@@ -299,8 +307,9 @@ CountryRow::CountryRow(
QWidget *parent,
not_null<PanelController*> controller,
const QString &label,
int maxLabelWidth,
const QString &value)
: PanelDetailsRow(parent, label)
: PanelDetailsRow(parent, label, maxLabelWidth)
, _controller(controller)
, _link(this, CountryString(value), st::boxLinkButton)
, _value(value) {
@@ -505,8 +514,9 @@ void DateInput::correctValue(
DateRow::DateRow(
QWidget *parent,
const QString &label,
int maxLabelWidth,
const QString &value)
: PanelDetailsRow(parent, label)
: PanelDetailsRow(parent, label, maxLabelWidth)
, _day(
this,
st::passportDetailsDateField,
@@ -726,25 +736,26 @@ int DateRow::resizeInner(int left, int top, int width) {
const auto right = left + width;
const auto &_st = st::passportDetailsDateField;
const auto &font = _st.placeholderFont;
const auto addToWidth = st::passportDetailsSeparatorPadding.left();
const auto dayWidth = _st.textMargins.left()
+ _st.placeholderMargins.left()
+ font->width(lang(lng_date_input_day))
+ _st.placeholderMargins.right()
+ _st.textMargins.right()
+ st::lineWidth;
+ addToWidth;
const auto monthWidth = _st.textMargins.left()
+ _st.placeholderMargins.left()
+ font->width(lang(lng_date_input_month))
+ _st.placeholderMargins.right()
+ _st.textMargins.right()
+ st::lineWidth;
+ addToWidth;
_day->setGeometry(left, top, dayWidth, _day->height());
left += dayWidth - st::lineWidth;
left += dayWidth - addToWidth;
_separator1->resizeToNaturalWidth(width);
_separator1->move(left, top);
left += _separator1->width();
_month->setGeometry(left, top, monthWidth, _month->height());
left += monthWidth - st::lineWidth;
left += monthWidth - addToWidth;
_separator2->resizeToNaturalWidth(width);
_separator2->move(left, top);
left += _separator2->width();
@@ -829,8 +840,9 @@ void DateRow::startBorderAnimation() {
GenderRow::GenderRow(
QWidget *parent,
const QString &label,
int maxLabelWidth,
const QString &value)
: PanelDetailsRow(parent, label)
: PanelDetailsRow(parent, label, maxLabelWidth)
, _group(StringToGender(value).has_value()
? std::make_shared<Ui::RadioenumGroup<Gender>>(*StringToGender(value))
: std::make_shared<Ui::RadioenumGroup<Gender>>())
@@ -938,8 +950,10 @@ void GenderRow::errorAnimationCallback() {
PanelDetailsRow::PanelDetailsRow(
QWidget *parent,
const QString &label)
: _label(label) {
const QString &label,
int maxLabelWidth)
: _label(label)
, _maxLabelWidth(maxLabelWidth) {
}
object_ptr<PanelDetailsRow> PanelDetailsRow::Create(
@@ -947,6 +961,7 @@ object_ptr<PanelDetailsRow> PanelDetailsRow::Create(
Type type,
not_null<PanelController*> controller,
const QString &label,
int maxLabelWidth,
const QString &value,
const QString &error,
int limit) {
@@ -956,20 +971,35 @@ object_ptr<PanelDetailsRow> PanelDetailsRow::Create(
return object_ptr<AbstractTextRow<Ui::InputField>>(
parent,
label,
maxLabelWidth,
value,
limit);
case Type::Postcode:
return object_ptr<AbstractTextRow<PostcodeInput>>(
parent,
label,
maxLabelWidth,
value,
limit);
case Type::Country:
return object_ptr<CountryRow>(parent, controller, label, value);
return object_ptr<CountryRow>(
parent,
controller,
label,
maxLabelWidth,
value);
case Type::Gender:
return object_ptr<GenderRow>(parent, label, value);
return object_ptr<GenderRow>(
parent,
label,
maxLabelWidth,
value);
case Type::Date:
return object_ptr<DateRow>(parent, label, value);
return object_ptr<DateRow>(
parent,
label,
maxLabelWidth,
value);
default:
Unexpected("Type in PanelDetailsRow::Create.");
}
@@ -981,13 +1011,19 @@ object_ptr<PanelDetailsRow> PanelDetailsRow::Create(
return result;
}
int PanelDetailsRow::LabelWidth(const QString &label) {
return st::semiboldFont->width(label);
}
bool PanelDetailsRow::setFocusFast() {
return false;
}
int PanelDetailsRow::resizeGetHeight(int newWidth) {
const auto padding = st::passportDetailsPadding;
const auto inputLeft = padding.left() + st::passportDetailsFieldLeft;
const auto inputLeft = padding.left() + std::max(
st::passportDetailsFieldLeft,
_maxLabelWidth + st::passportDetailsFieldSkipMin);
const auto inputTop = st::passportDetailsFieldTop;
const auto inputRight = padding.right();
const auto inputWidth = std::max(newWidth - inputLeft - inputRight, 0);
@@ -997,6 +1033,7 @@ int PanelDetailsRow::resizeGetHeight(int newWidth) {
+ (_error ? _error->height() : 0)
+ padding.bottom();
if (_error) {
_error->resizeToWidth(inputWidth);
_error->moveToLeft(inputLeft, result - _error->height());
}
return result;

View File

@@ -37,16 +37,19 @@ public:
PanelDetailsRow(
QWidget *parent,
const QString &label);
const QString &label,
int maxLabelWidth);
static object_ptr<PanelDetailsRow> Create(
QWidget *parent,
Type type,
not_null<PanelController*> controller,
const QString &label,
int maxLabelWidth,
const QString &value,
const QString &error,
int limit = 0);
static int LabelWidth(const QString &label);
virtual bool setFocusFast();
virtual rpl::producer<QString> value() const = 0;
@@ -69,6 +72,7 @@ private:
void startErrorAnimation(bool shown);
QString _label;
int _maxLabelWidth = 0;
object_ptr<Ui::SlideWrap<Ui::FlatLabel>> _error = { nullptr };
bool _errorShown = false;
bool _errorHideSubscription = false;

View File

@@ -326,24 +326,42 @@ not_null<Ui::RpWidget*> PanelEditDocument::setupContent(
return ValueField();
};
for (auto i = 0, count = int(_scheme.rows.size()); i != count; ++i) {
const auto &row = _scheme.rows[i];
auto fields = (row.valueClass == Scheme::ValueClass::Fields)
? &data
: scanData;
if (!fields) {
continue;
const auto enumerateRows = [&](auto &&callback) {
for (auto i = 0, count = int(_scheme.rows.size()); i != count; ++i) {
const auto &row = _scheme.rows[i];
auto fields = (row.valueClass == Scheme::ValueClass::Fields)
? &data
: scanData;
if (!fields) {
continue;
}
callback(i, row, *fields);
}
const auto current = valueOrEmpty(*fields, row.key);
};
auto maxLabelWidth = 0;
enumerateRows([&](
int i,
const EditDocumentScheme::Row &row,
const ValueMap &fields) {
accumulate_max(
maxLabelWidth,
PanelDetailsRow::LabelWidth(row.label));
});
enumerateRows([&](
int i,
const EditDocumentScheme::Row &row,
const ValueMap &fields) {
const auto current = valueOrEmpty(fields, row.key);
_details.emplace(i, inner->add(PanelDetailsRow::Create(
inner,
row.inputType,
_controller,
row.label,
maxLabelWidth,
current.text,
current.error,
row.lengthLimit)));
}
});
inner->add(
object_ptr<Ui::FixedHeightWidget>(inner, st::passportDetailsSkip));

View File

@@ -326,7 +326,7 @@ void PanelForm::updateControlsGeometry() {
_topShadow->moveToLeft(0, 0);
_bottomShadow->resizeToWidth(width());
_bottomShadow->moveToLeft(0, submitTop - st::lineWidth);
_submit->resizeToWidth(width());
_submit->setFullWidth(width());
_submit->moveToLeft(0, submitTop);
_scroll->updateBars();

View File

@@ -199,6 +199,9 @@ bool Get(
const QString &filter,
Type type,
QString startFile) {
if (parent) {
parent = parent->window();
}
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
if (NativeSupported()) {
return GetNative(

View File

@@ -281,7 +281,9 @@ QString RoundButton::computeFullText() const {
void RoundButton::resizeToText() {
int innerWidth = contentWidth();
if (_fullWidthOverride < 0) {
if (_fullWidthOverride > 0) {
resize(_fullWidthOverride, _st.height + _st.padding.top() + _st.padding.bottom());
} else if (_fullWidthOverride < 0) {
resize(innerWidth - _fullWidthOverride, _st.height + _st.padding.top() + _st.padding.bottom());
} else if (_st.width <= 0) {
resize(innerWidth - _st.width + _st.padding.left() + _st.padding.right(), _st.height + _st.padding.top() + _st.padding.bottom());

View File

@@ -77,7 +77,10 @@ static CGEventRef tapEventCallback(CGEventTapProxy proxy, CGEventType type, CGEv
CGEventMaskBit(NX_SYSDEFINED),
tapEventCallback,
self);
assert(_eventPort != NULL);
if (!_eventPort) {
[self stopWatchingMediaKeys];
return;
}
_eventPortSource = CFMachPortCreateRunLoopSource(kCFAllocatorSystemDefault, _eventPort, 0);
assert(_eventPortSource != NULL);

View File

@@ -1,6 +1,6 @@
AppVersion 1003004
AppVersion 1003007
AppVersionStrMajor 1.3
AppVersionStrSmall 1.3.4
AppVersionStr 1.3.4
AlphaChannel 1
AppVersionStrSmall 1.3.7
AppVersionStr 1.3.7
AlphaChannel 0
BetaVersion 0

View File

@@ -1,3 +1,15 @@
1.3.7 (11.06.18)
- Push fixes to stable version.
1.3.6 alpha (11.06.18)
- Bug fixes and other minor improvements.
1.3.5 alpha (08.06.18)
- Bug fixes and other minor improvements.
1.3.4 alpha (07.06.18)
- Bug fixes and other minor improvements.