Compare commits

...

17 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
John Preston
be2abd594f Alpha version 1.3.4.
- Bug fixes and other minor improvements.
2018-06-07 22:29:27 +03:00
John Preston
75a40b83ae Notify settings unknown => draw chats as muted.
Also request common notify settings at the app launch.
2018-06-07 22:28:09 +03:00
John Preston
472a677bca Fix crash in special scan upload. 2018-06-07 22:11:55 +03:00
John Preston
dca6e10beb Fix markdown apply to text with emoji. 2018-06-07 22:00:46 +03:00
John Preston
122ab94f3d Fix text color glitch after palette update.
Once again fixes #4774.
2018-06-07 21:25:10 +03:00
32 changed files with 393 additions and 205 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";
@@ -1643,15 +1643,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_passport_delete_email_sure" = "Are you sure you want to delete your email address?";
"lng_passport_delete_phone" = "Delete phone number";
"lng_passport_delete_phone_sure" = "Are you sure you want to delete your phone number?";
"lng_passport_success" = "Authorization successfull!";
"lng_passport_success" = "Authorization successful!";
"lng_passport_stop_sure" = "Are you sure you want to stop this authorization?";
"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.3.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,3,0
PRODUCTVERSION 1,3,3,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.3.0"
VALUE "FileVersion", "1.3.7.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2018"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "1.3.3.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,3,0
PRODUCTVERSION 1,3,3,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.3.0"
VALUE "FileVersion", "1.3.7.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2018"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "1.3.3.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

@@ -609,19 +609,21 @@ void MessageLinksParser::parse() {
const auto markdownTagsEnd = markdownTags.end();
const auto markdownTagsAllow = [&](int from, int length) {
while (markdownTag != markdownTagsEnd
&& (markdownTag->start + markdownTag->length <= from
&& (markdownTag->adjustedStart
+ markdownTag->adjustedLength <= from
|| !markdownTag->closed)) {
++markdownTag;
continue;
}
if (markdownTag == markdownTagsEnd
|| markdownTag->start >= from + length) {
|| markdownTag->adjustedStart >= from + length) {
return true;
}
// Ignore http-links that are completely inside some tags.
// This will allow sending http://test.com/__test__/test correctly.
return (markdownTag->start > from
|| markdownTag->start + markdownTag->length < from + length);
return (markdownTag->adjustedStart > from)
|| (markdownTag->adjustedStart
+ markdownTag->adjustedLength < from + length);
};
const auto len = text.size();

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 = 1003003;
constexpr str_const AppVersionStr = "1.3.3";
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

@@ -1741,7 +1741,7 @@ bool Session::notifyIsMuted(
if (const auto until = settings.muteUntil()) {
return resultFromUntil(*until);
}
return false;
return true;
}
bool Session::notifySilentPosts(not_null<const PeerData*> peer) const {

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);
}
@@ -2198,9 +2219,6 @@ void History::applyDialog(const MTPDdialog &data) {
MTP_notifyPeer(data.vpeer),
data.vnotify_settings);
// Request default notification settings for this type of chat.
Auth().data().requestNotifySettings(peer);
if (data.has_draft() && data.vdraft.type() == mtpc_draftMessage) {
Data::applyPeerCloudDraft(peer->id, data.vdraft.c_draftMessage());
}

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

@@ -3700,6 +3700,9 @@ void MainWidget::mtpPing() {
}
void MainWidget::start(const MTPUser *self) {
Auth().api().requestNotifySettings(MTP_inputNotifyUsers());
Auth().api().requestNotifySettings(MTP_inputNotifyChats());
if (!self) {
MTP::send(MTPusers_GetFullUser(MTP_inputUserSelf()), rpcDone(&MainWidget::startWithSelf));
return;
@@ -3713,7 +3716,7 @@ void MainWidget::start(const MTPUser *self) {
Local::readSavedPeers();
cSetOtherOnline(0);
if (auto user = App::feedUsers(MTP_vector<MTPUser>(1, *self))) {
if (const auto user = App::feedUsers(MTP_vector<MTPUser>(1, *self))) {
user->loadUserpic();
}

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);
}
@@ -539,7 +539,9 @@ void PanelController::uploadSpecialScan(
QByteArray &&content) {
Expects(_editScope != nullptr);
Expects(_editDocument != nullptr);
Expects(_editScope->selfieRequired);
Expects(_editDocument->requiresSpecialScan(
type,
_editScope->selfieRequired));
_form->uploadSpecialScan(_editDocument, type, std::move(content));
}
@@ -547,7 +549,9 @@ void PanelController::uploadSpecialScan(
void PanelController::deleteSpecialScan(SpecialFile type) {
Expects(_editScope != nullptr);
Expects(_editDocument != nullptr);
Expects(_editScope->selfieRequired);
Expects(_editDocument->requiresSpecialScan(
type,
_editScope->selfieRequired));
_form->deleteSpecialScan(_editDocument, type);
}
@@ -555,7 +559,9 @@ void PanelController::deleteSpecialScan(SpecialFile type) {
void PanelController::restoreSpecialScan(SpecialFile type) {
Expects(_editScope != nullptr);
Expects(_editDocument != nullptr);
Expects(_editScope->selfieRequired);
Expects(_editDocument->requiresSpecialScan(
type,
_editScope->selfieRequired));
_form->restoreSpecialScan(_editDocument, type);
}

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

@@ -272,12 +272,22 @@ public:
, _items(_expressions.size()) {
}
void feed(const QString &text, const QString &textTag) {
// Here we use the fact that text either contains only emoji
// { adjustedTextLength = text.size() * (emojiLength - 1) }
// or contains no emoji at all and can have tag edges in the middle
// { adjustedTextLength = 0 }.
//
// Otherwise we would have to pass emoji positions inside text.
void feed(
const QString &text,
int adjustedTextLength,
const QString &textTag) {
if (!_tags) {
return;
}
const auto guard = gsl::finally([&] {
_currentLength += text.size();
_currentInternalLength += text.size();
_currentAdjustedLength += adjustedTextLength;
});
if (!textTag.isEmpty()) {
finishTags();
@@ -290,7 +300,7 @@ public:
while (true) {
for (; tryFinishTag != _currentFreeTag; ++tryFinishTag) {
auto &tag = (*_tags)[tryFinishTag];
if (tag.length >= 0) {
if (tag.internalLength >= 0) {
continue;
}
@@ -298,8 +308,12 @@ public:
Assert(i != end(_tagIndices));
const auto tagIndex = i->second;
_items[tagIndex].applyOffset(
tag.start + tag.tag.size() + 1 - _currentLength);
const auto atLeastOffset =
tag.internalStart
+ tag.tag.size()
+ 1
- _currentInternalLength;
_items[tagIndex].applyOffset(atLeastOffset);
fillItem(
tagIndex,
@@ -311,10 +325,7 @@ public:
const auto position = matchPosition(tagIndex, Edge::Close);
if (position < kInvalidPosition) {
const auto till = position + tag.tag.size();
finishTag(
tryFinishTag,
_currentLength + till,
true);
finishTag(tryFinishTag, till, true);
_items[tagIndex].applyOffset(till);
}
}
@@ -325,9 +336,7 @@ public:
if (min < 0) {
return;
}
startTag(
_currentLength + matchPosition(min, Edge::Open),
_expressions[min].tag);
startTag(matchPosition(min, Edge::Open), _expressions[min].tag);
}
}
@@ -342,13 +351,18 @@ public:
}
private:
void finishTag(int index, int end, bool closed) {
void finishTag(int index, int offsetFromAccumulated, bool closed) {
Expects(_tags != nullptr);
Expects(index >= 0 && index < _tags->size());
auto &tag = (*_tags)[index];
if (tag.length < 0) {
tag.length = end - tag.start;
if (tag.internalLength < 0) {
tag.internalLength = _currentInternalLength
+ offsetFromAccumulated
- tag.internalStart;
tag.adjustedLength = _currentAdjustedLength
+ offsetFromAccumulated
- tag.adjustedStart;
tag.closed = closed;
}
if (index == _currentTag) {
@@ -369,25 +383,33 @@ private:
}
const auto endPosition = newlinePosition(
text,
std::max(0, tag.start + 1 - _currentLength));
std::max(0, tag.internalStart + 1 - _currentInternalLength));
if (matchPosition(tagIndex, Edge::Close) <= endPosition) {
return false;
}
finishTag(index, _currentLength + endPosition, false);
finishTag(index, endPosition, false);
return true;
}
void finishTags() {
while (_currentTag != _currentFreeTag) {
finishTag(_currentTag, _currentLength, false);
finishTag(_currentTag, 0, false);
}
}
void startTag(int offset, const QString &tag) {
void startTag(int offsetFromAccumulated, const QString &tag) {
Expects(_tags != nullptr);
const auto newTag = InputField::MarkdownTag{
_currentInternalLength + offsetFromAccumulated,
-1,
_currentAdjustedLength + offsetFromAccumulated,
-1,
false,
tag
};
if (_currentFreeTag < _tags->size()) {
(*_tags)[_currentFreeTag] = { offset, -1, false, tag };
(*_tags)[_currentFreeTag] = newTag;
} else {
_tags->push_back({ offset, -1, false, tag });
_tags->push_back(newTag);
}
++_currentFreeTag;
}
@@ -447,7 +469,8 @@ private:
int _currentTag = 0;
int _currentFreeTag = 0;
int _currentLength = 0;
int _currentInternalLength = 0;
int _currentAdjustedLength = 0;
};
@@ -1246,6 +1269,16 @@ void InputField::updatePalette() {
}
}
}
cursor = textCursor();
if (!cursor.hasSelection()) {
auto format = cursor.charFormat();
format.merge(PrepareTagFormat(
_st,
format.property(kTagProperty).toString()));
cursor.setCharFormat(format);
setTextCursor(cursor);
}
}
void InputField::onTouchTimer() {
@@ -1752,11 +1785,11 @@ QString InputField::getTextPart(
if (full || !text.isEmpty()) {
lastTag = format.property(kTagProperty).toString();
tagAccumulator.feed(lastTag, result.size());
markdownTagAccumulator.feed(text, lastTag);
}
auto begin = text.data();
auto ch = begin;
auto adjustedLength = text.size();
for (const auto end = begin + text.size(); ch != end; ++ch) {
if (IsNewline(*ch) && ch->unicode() != '\r') {
*ch = QLatin1Char('\n');
@@ -1768,6 +1801,7 @@ QString InputField::getTextPart(
if (ch > begin) {
result.append(begin, ch - begin);
}
adjustedLength += (emojiText.size() - 1);
if (!emojiText.isEmpty()) {
result.append(emojiText);
}
@@ -1778,12 +1812,16 @@ QString InputField::getTextPart(
if (ch > begin) {
result.append(begin, ch - begin);
}
if (full || !text.isEmpty()) {
markdownTagAccumulator.feed(text, adjustedLength, lastTag);
}
}
block = block.next();
if (block != till) {
result.append('\n');
markdownTagAccumulator.feed(newline, lastTag);
markdownTagAccumulator.feed(newline, 1, lastTag);
}
}
@@ -2141,14 +2179,17 @@ void InputField::highlightMarkdown() {
from = b;
};
for (const auto &tag : _lastMarkdownTags) {
if (tag.start > from) {
applyColor(from, tag.start, QColor(0, 0, 0));
} else if (tag.start < from) {
if (tag.internalStart > from) {
applyColor(from, tag.internalStart, QColor(0, 0, 0));
} else if (tag.internalStart < from) {
continue;
}
applyColor(tag.start, tag.start + tag.length, tag.closed
? QColor(0, 128, 0)
: QColor(128, 0, 0));
applyColor(
tag.internalStart,
tag.internalStart + tag.internalLength,
(tag.closed
? QColor(0, 128, 0)
: QColor(128, 0, 0)));
}
auto cursor = textCursor();
cursor.movePosition(QTextCursor::End);
@@ -2342,36 +2383,38 @@ TextWithTags InputField::getTextWithAppliedMarkdown() const {
const auto linksEnd = links.end();
for (const auto &tag : _lastMarkdownTags) {
const auto tagLength = int(tag.tag.size());
if (!tag.closed || tag.start < from) {
if (!tag.closed || tag.adjustedStart < from) {
continue;
}
const auto entityLength = tag.length - 2 * tagLength;
const auto entityLength = tag.adjustedLength - 2 * tagLength;
if (entityLength <= 0) {
continue;
}
addOriginalTagsUpTill(tag.start);
addOriginalTagsUpTill(tag.adjustedStart);
const auto tagAdjustedEnd = tag.adjustedStart + tag.adjustedLength;
if (originalTag != originalTagsEnd
&& originalTag->offset < tag.start + tag.length) {
&& originalTag->offset < tagAdjustedEnd) {
continue;
}
while (link != linksEnd
&& link->offset() + link->length() <= tag.start) {
&& link->offset() + link->length() <= tag.adjustedStart) {
++link;
}
if (link != linksEnd
&& link->offset() < tag.start + tag.length
&& (link->offset() + link->length() > tag.start + tag.length
|| link->offset() < tag.start)) {
&& link->offset() < tagAdjustedEnd
&& (link->offset() + link->length() > tagAdjustedEnd
|| link->offset() < tag.adjustedStart)) {
continue;
}
addOriginalTextUpTill(tag.start);
addOriginalTextUpTill(tag.adjustedStart);
result.tags.push_back(TextWithTags::Tag{
int(result.text.size()),
entityLength,
tag.tag });
result.text.append(
originalText.midRef(tag.start + tagLength, entityLength));
from = tag.start + tag.length;
result.text.append(originalText.midRef(
tag.adjustedStart + tagLength,
entityLength));
from = tag.adjustedStart + tag.adjustedLength;
removed += 2 * tagLength;
}
addOriginalTagsUpTill(originalText.size());
@@ -2739,8 +2782,8 @@ void InputField::processInstantReplaces(const QString &appended) {
}
const auto position = textCursor().position();
for (const auto &tag : _lastMarkdownTags) {
if (tag.start < position
&& tag.start + tag.length >= position
if (tag.internalStart < position
&& tag.internalStart + tag.internalLength >= position
&& (tag.tag == kTagCode || tag.tag == kTagPre)) {
return;
}

View File

@@ -125,8 +125,14 @@ public:
using TagList = TextWithTags::Tags;
struct MarkdownTag {
int start = 0;
int length = 0;
// With each emoji being QChar::ObjectReplacementCharacter.
int internalStart = 0;
int internalLength = 0;
// Adjusted by emoji to match _lastTextWithTags.
int adjustedStart = 0;
int adjustedLength = 0;
bool closed = false;
QString tag;
};

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 1003003
AppVersion 1003007
AppVersionStrMajor 1.3
AppVersionStrSmall 1.3.3
AppVersionStr 1.3.3
AlphaChannel 1
AppVersionStrSmall 1.3.7
AppVersionStr 1.3.7
AlphaChannel 0
BetaVersion 0

View File

@@ -1,3 +1,19 @@
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.
1.3.3 alpha (07.06.18)
- Bug fixes and other minor improvements.