mirror of
https://github.com/kotatogram/kotatogram-desktop
synced 2025-08-30 06:07:45 +00:00
Merge remote-tracking branch 'tdesktop/dev' into dev
This commit is contained in:
commit
8aa9c4aa6d
10
.github/workflows/snap.yml
vendored
10
.github/workflows/snap.yml
vendored
@ -67,7 +67,7 @@ jobs:
|
|||||||
|
|
||||||
- name: CMake build.
|
- name: CMake build.
|
||||||
if: steps.cache-cmake.outputs.cache-hit != 'true'
|
if: steps.cache-cmake.outputs.cache-hit != 'true'
|
||||||
run: snapcraft build --destructive-mode cmake
|
run: sudo snapcraft build --destructive-mode cmake
|
||||||
|
|
||||||
- name: FFmpeg cache.
|
- name: FFmpeg cache.
|
||||||
id: cache-ffmpeg
|
id: cache-ffmpeg
|
||||||
@ -78,11 +78,11 @@ jobs:
|
|||||||
|
|
||||||
- name: FFmpeg build.
|
- name: FFmpeg build.
|
||||||
if: steps.cache-ffmpeg.outputs.cache-hit != 'true'
|
if: steps.cache-ffmpeg.outputs.cache-hit != 'true'
|
||||||
run: snapcraft build --destructive-mode ffmpeg
|
run: sudo snapcraft build --destructive-mode ffmpeg
|
||||||
|
|
||||||
- name: Kotatogram Desktop snap build.
|
- name: Kotatogram Desktop snap build.
|
||||||
if: env.ONLY_CACHE == 'false'
|
if: env.ONLY_CACHE == 'false'
|
||||||
run: snapcraft --destructive-mode
|
run: sudo snapcraft --destructive-mode
|
||||||
|
|
||||||
- name: Move artifact.
|
- name: Move artifact.
|
||||||
if: env.UPLOAD_ARTIFACT == 'true'
|
if: env.UPLOAD_ARTIFACT == 'true'
|
||||||
@ -102,5 +102,5 @@ jobs:
|
|||||||
|
|
||||||
- name: Remove unneeded directories for cache.
|
- name: Remove unneeded directories for cache.
|
||||||
run: |
|
run: |
|
||||||
rm -rf parts/{cmake,ffmpeg}/{build,src,ubuntu}
|
sudo rm -rf parts/{cmake,ffmpeg}/{build,src,ubuntu}
|
||||||
rm -rf parts/{cmake,ffmpeg}/state/{stage,prime}
|
sudo rm -rf parts/{cmake,ffmpeg}/state/{stage,prime}
|
||||||
|
@ -1329,6 +1329,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
"lng_dialogs_skip_archive_in_search" = "Skip results from archive";
|
"lng_dialogs_skip_archive_in_search" = "Skip results from archive";
|
||||||
"lng_dialogs_show_archive_in_search" = "With results from archive";
|
"lng_dialogs_show_archive_in_search" = "With results from archive";
|
||||||
|
|
||||||
|
"lng_about_dice" = "Send a 🎲 emoji to any chat to get a random number from Telegram.";
|
||||||
|
|
||||||
"lng_open_this_link" = "Open this link?";
|
"lng_open_this_link" = "Open this link?";
|
||||||
"lng_open_link" = "Open";
|
"lng_open_link" = "Open";
|
||||||
"lng_allow_bot_pass" = "Allow {bot_name} to pass your Telegram name and ID to the web pages you open via this bot?";
|
"lng_allow_bot_pass" = "Allow {bot_name} to pass your Telegram name and ID to the web pages you open via this bot?";
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
|
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
|
||||||
ProcessorArchitecture="ARCHITECTURE"
|
ProcessorArchitecture="ARCHITECTURE"
|
||||||
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
|
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
|
||||||
Version="1.9.22.0" />
|
Version="2.0.0.0" />
|
||||||
<Properties>
|
<Properties>
|
||||||
<DisplayName>Telegram Desktop</DisplayName>
|
<DisplayName>Telegram Desktop</DisplayName>
|
||||||
<PublisherDisplayName>Telegram FZ-LLC</PublisherDisplayName>
|
<PublisherDisplayName>Telegram FZ-LLC</PublisherDisplayName>
|
||||||
|
@ -691,7 +691,10 @@ void ProxiesBox::applyView(View &&view) {
|
|||||||
wrap,
|
wrap,
|
||||||
std::move(view))));
|
std::move(view))));
|
||||||
setupButtons(id, i->second.get());
|
setupButtons(id, i->second.get());
|
||||||
_noRows.reset();
|
if (_noRows) {
|
||||||
|
_noRows.reset();
|
||||||
|
wrap->resizeToWidth(width());
|
||||||
|
}
|
||||||
} else if (view.host.isEmpty()) {
|
} else if (view.host.isEmpty()) {
|
||||||
_rows.erase(i);
|
_rows.erase(i);
|
||||||
} else {
|
} else {
|
||||||
|
@ -314,6 +314,7 @@ void EditExceptions(
|
|||||||
include ? rules.always() : rules.never());
|
include ? rules.always() : rules.never());
|
||||||
const auto rawController = controller.get();
|
const auto rawController = controller.get();
|
||||||
auto initBox = [=](not_null<PeerListBox*> box) {
|
auto initBox = [=](not_null<PeerListBox*> box) {
|
||||||
|
box->setCloseByOutsideClick(false);
|
||||||
box->addButton(tr::lng_settings_save(), crl::guard(context, [=] {
|
box->addButton(tr::lng_settings_save(), crl::guard(context, [=] {
|
||||||
const auto peers = box->peerListCollectSelectedRows();
|
const auto peers = box->peerListCollectSelectedRows();
|
||||||
const auto rules = data->current();
|
const auto rules = data->current();
|
||||||
@ -469,6 +470,10 @@ void CreateIconSelector(
|
|||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] QString TrimDefaultTitle(const QString &title) {
|
||||||
|
return (title.size() <= kMaxFilterTitleLength) ? title : QString();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void EditFilterBox(
|
void EditFilterBox(
|
||||||
@ -512,7 +517,7 @@ void EditFilterBox(
|
|||||||
if (nameEditing->custom) {
|
if (nameEditing->custom) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto title = DefaultTitle(filter);
|
const auto title = TrimDefaultTitle(DefaultTitle(filter));
|
||||||
if (nameEditing->field->getLastText() != title) {
|
if (nameEditing->field->getLastText() != title) {
|
||||||
nameEditing->settingDefault = true;
|
nameEditing->settingDefault = true;
|
||||||
nameEditing->field->setText(title);
|
nameEditing->field->setText(title);
|
||||||
@ -559,6 +564,11 @@ void EditFilterBox(
|
|||||||
AddSkip(content);
|
AddSkip(content);
|
||||||
AddSubsectionTitle(content, tr::lng_filters_include());
|
AddSubsectionTitle(content, tr::lng_filters_include());
|
||||||
|
|
||||||
|
const auto includeAdd = AddButton(
|
||||||
|
content,
|
||||||
|
tr::lng_filters_add_chats() | Ui::Text::ToUpper(),
|
||||||
|
st::settingsUpdate);
|
||||||
|
|
||||||
const auto include = SetupChatsPreview(
|
const auto include = SetupChatsPreview(
|
||||||
content,
|
content,
|
||||||
data,
|
data,
|
||||||
@ -566,11 +576,6 @@ void EditFilterBox(
|
|||||||
kTypes,
|
kTypes,
|
||||||
&Data::ChatFilter::always);
|
&Data::ChatFilter::always);
|
||||||
|
|
||||||
const auto includeAdd = AddButton(
|
|
||||||
content,
|
|
||||||
tr::lng_filters_add_chats() | Ui::Text::ToUpper(),
|
|
||||||
st::settingsUpdate);
|
|
||||||
|
|
||||||
AddSkip(content);
|
AddSkip(content);
|
||||||
content->add(
|
content->add(
|
||||||
object_ptr<Ui::FlatLabel>(
|
object_ptr<Ui::FlatLabel>(
|
||||||
@ -583,6 +588,11 @@ void EditFilterBox(
|
|||||||
|
|
||||||
AddSubsectionTitle(content, tr::lng_filters_exclude());
|
AddSubsectionTitle(content, tr::lng_filters_exclude());
|
||||||
|
|
||||||
|
const auto excludeAdd = AddButton(
|
||||||
|
content,
|
||||||
|
tr::lng_filters_remove_chats() | Ui::Text::ToUpper(),
|
||||||
|
st::settingsUpdate);
|
||||||
|
|
||||||
const auto exclude = SetupChatsPreview(
|
const auto exclude = SetupChatsPreview(
|
||||||
content,
|
content,
|
||||||
data,
|
data,
|
||||||
@ -590,11 +600,6 @@ void EditFilterBox(
|
|||||||
kExcludeTypes,
|
kExcludeTypes,
|
||||||
&Data::ChatFilter::never);
|
&Data::ChatFilter::never);
|
||||||
|
|
||||||
const auto excludeAdd = AddButton(
|
|
||||||
content,
|
|
||||||
tr::lng_filters_remove_chats() | Ui::Text::ToUpper(),
|
|
||||||
st::settingsUpdate);
|
|
||||||
|
|
||||||
AddSkip(content);
|
AddSkip(content);
|
||||||
content->add(
|
content->add(
|
||||||
object_ptr<Ui::FlatLabel>(
|
object_ptr<Ui::FlatLabel>(
|
||||||
|
@ -144,7 +144,7 @@ public:
|
|||||||
void saveSettingsDelayed(crl::time delay = kDefaultSaveDelay);
|
void saveSettingsDelayed(crl::time delay = kDefaultSaveDelay);
|
||||||
|
|
||||||
// Dc options and proxy.
|
// Dc options and proxy.
|
||||||
MTP::DcOptions *dcOptions() {
|
not_null<MTP::DcOptions*> dcOptions() {
|
||||||
return _dcOptions.get();
|
return _dcOptions.get();
|
||||||
}
|
}
|
||||||
struct ProxyChange {
|
struct ProxyChange {
|
||||||
|
@ -299,6 +299,8 @@ bool Manager::readCustomFile() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Manager::fillDefaults() {
|
void Manager::fillDefaults() {
|
||||||
|
const auto ctrl = Platform::IsMac() ? qsl("meta") : qsl("ctrl");
|
||||||
|
|
||||||
set(qsl("ctrl+w"), Command::Close);
|
set(qsl("ctrl+w"), Command::Close);
|
||||||
set(qsl("ctrl+f4"), Command::Close);
|
set(qsl("ctrl+f4"), Command::Close);
|
||||||
set(qsl("ctrl+l"), Command::Lock);
|
set(qsl("ctrl+l"), Command::Lock);
|
||||||
@ -320,15 +322,11 @@ void Manager::fillDefaults() {
|
|||||||
set(qsl("alt+down"), Command::ChatNext);
|
set(qsl("alt+down"), Command::ChatNext);
|
||||||
set(qsl("ctrl+pgup"), Command::ChatPrevious);
|
set(qsl("ctrl+pgup"), Command::ChatPrevious);
|
||||||
set(qsl("alt+up"), Command::ChatPrevious);
|
set(qsl("alt+up"), Command::ChatPrevious);
|
||||||
if (Platform::IsMac()) {
|
|
||||||
set(qsl("meta+tab"), Command::ChatNext);
|
set(qsl("%1+tab").arg(ctrl), Command::ChatNext);
|
||||||
set(qsl("meta+shift+tab"), Command::ChatPrevious);
|
set(qsl("%1+shift+tab").arg(ctrl), Command::ChatPrevious);
|
||||||
set(qsl("meta+backtab"), Command::ChatPrevious);
|
set(qsl("%1+backtab").arg(ctrl), Command::ChatPrevious);
|
||||||
} else {
|
|
||||||
set(qsl("ctrl+tab"), Command::ChatNext);
|
|
||||||
set(qsl("ctrl+shift+tab"), Command::ChatPrevious);
|
|
||||||
set(qsl("ctrl+backtab"), Command::ChatPrevious);
|
|
||||||
}
|
|
||||||
set(qsl("ctrl+alt+home"), Command::ChatFirst);
|
set(qsl("ctrl+alt+home"), Command::ChatFirst);
|
||||||
set(qsl("ctrl+alt+end"), Command::ChatLast);
|
set(qsl("ctrl+alt+end"), Command::ChatLast);
|
||||||
|
|
||||||
@ -344,6 +342,17 @@ void Manager::fillDefaults() {
|
|||||||
set(qsl("ctrl+4"), Command::ChatPinned4);
|
set(qsl("ctrl+4"), Command::ChatPinned4);
|
||||||
set(qsl("ctrl+5"), Command::ChatPinned5);
|
set(qsl("ctrl+5"), Command::ChatPinned5);
|
||||||
|
|
||||||
|
auto &&folders = ranges::view::zip(
|
||||||
|
kShowFolder,
|
||||||
|
ranges::view::ints(1, ranges::unreachable));
|
||||||
|
|
||||||
|
for (const auto [command, index] : folders) {
|
||||||
|
set(qsl("%1+shift+%2").arg(ctrl).arg(index > 9 ? 0 : index), command);
|
||||||
|
}
|
||||||
|
|
||||||
|
set(qsl("%1+shift+down").arg(ctrl), Command::FolderNext);
|
||||||
|
set(qsl("%1+shift+up").arg(ctrl), Command::FolderPrevious);
|
||||||
|
|
||||||
set(qsl("ctrl+0"), Command::ChatSelf);
|
set(qsl("ctrl+0"), Command::ChatSelf);
|
||||||
|
|
||||||
set(qsl("ctrl+9"), Command::ShowArchive);
|
set(qsl("ctrl+9"), Command::ShowArchive);
|
||||||
|
@ -35,6 +35,20 @@ enum class Command {
|
|||||||
ChatPinned4,
|
ChatPinned4,
|
||||||
ChatPinned5,
|
ChatPinned5,
|
||||||
|
|
||||||
|
ShowFolder1,
|
||||||
|
ShowFolder2,
|
||||||
|
ShowFolder3,
|
||||||
|
ShowFolder4,
|
||||||
|
ShowFolder5,
|
||||||
|
ShowFolder6,
|
||||||
|
ShowFolder7,
|
||||||
|
ShowFolder8,
|
||||||
|
ShowFolder9,
|
||||||
|
ShowFolder10,
|
||||||
|
|
||||||
|
FolderNext,
|
||||||
|
FolderPrevious,
|
||||||
|
|
||||||
ShowArchive,
|
ShowArchive,
|
||||||
|
|
||||||
JustSendMessage,
|
JustSendMessage,
|
||||||
@ -50,6 +64,19 @@ enum class Command {
|
|||||||
SaveDraft,
|
SaveDraft,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr auto kShowFolder = {
|
||||||
|
Command::ShowFolder1,
|
||||||
|
Command::ShowFolder2,
|
||||||
|
Command::ShowFolder3,
|
||||||
|
Command::ShowFolder4,
|
||||||
|
Command::ShowFolder5,
|
||||||
|
Command::ShowFolder6,
|
||||||
|
Command::ShowFolder7,
|
||||||
|
Command::ShowFolder8,
|
||||||
|
Command::ShowFolder9,
|
||||||
|
Command::ShowFolder10,
|
||||||
|
};
|
||||||
|
|
||||||
[[nodiscard]] FnMut<bool()> RequestHandler(Command command);
|
[[nodiscard]] FnMut<bool()> RequestHandler(Command command);
|
||||||
|
|
||||||
class Request {
|
class Request {
|
||||||
|
@ -52,6 +52,14 @@ void UiIntegration::activationFromTopPanel() {
|
|||||||
Platform::IgnoreApplicationActivationRightNow();
|
Platform::IgnoreApplicationActivationRightNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UiIntegration::startFontsBegin() {
|
||||||
|
Platform::FallbackFontConfigCheckBegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UiIntegration::startFontsEnd() {
|
||||||
|
Platform::FallbackFontConfigCheckEnd();
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<ClickHandler> UiIntegration::createLinkHandler(
|
std::shared_ptr<ClickHandler> UiIntegration::createLinkHandler(
|
||||||
EntityType type,
|
EntityType type,
|
||||||
const QString &text,
|
const QString &text,
|
||||||
|
@ -23,6 +23,9 @@ public:
|
|||||||
void textActionsUpdated() override;
|
void textActionsUpdated() override;
|
||||||
void activationFromTopPanel() override;
|
void activationFromTopPanel() override;
|
||||||
|
|
||||||
|
void startFontsBegin() override;
|
||||||
|
void startFontsEnd() override;
|
||||||
|
|
||||||
std::shared_ptr<ClickHandler> createLinkHandler(
|
std::shared_ptr<ClickHandler> createLinkHandler(
|
||||||
EntityType type,
|
EntityType type,
|
||||||
const QString &text,
|
const QString &text,
|
||||||
|
@ -22,9 +22,9 @@ constexpr auto AppId = "{C4A4AE8F-B9F7-4CC7-8A6C-BF7EEE87ACA5}"_cs;
|
|||||||
constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs;
|
constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs;
|
||||||
constexpr auto AppName = "Kotatogram Desktop"_cs;
|
constexpr auto AppName = "Kotatogram Desktop"_cs;
|
||||||
constexpr auto AppFile = "Kotatogram"_cs;
|
constexpr auto AppFile = "Kotatogram"_cs;
|
||||||
constexpr auto AppVersion = 1009022;
|
constexpr auto AppVersion = 2000000;
|
||||||
constexpr auto AppVersionStr = "1.9.22";
|
constexpr auto AppVersionStr = "2.0";
|
||||||
constexpr auto AppBetaVersion = true;
|
constexpr auto AppBetaVersion = false;
|
||||||
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
||||||
constexpr auto AppKotatoVersion = 1002000;
|
constexpr auto AppKotatoVersion = 1002000;
|
||||||
constexpr auto AppKotatoVersionStr = "1.2";
|
constexpr auto AppKotatoVersionStr = "1.2";
|
||||||
|
@ -230,6 +230,10 @@ not_null<Row*> Entry::addToChatList(
|
|||||||
void Entry::removeFromChatList(
|
void Entry::removeFromChatList(
|
||||||
FilterId filterId,
|
FilterId filterId,
|
||||||
not_null<MainList*> list) {
|
not_null<MainList*> list) {
|
||||||
|
if (isPinnedDialog(filterId)) {
|
||||||
|
owner().setChatPinned(_key, filterId, false);
|
||||||
|
}
|
||||||
|
|
||||||
const auto i = _chatListLinks.find(filterId);
|
const auto i = _chatListLinks.find(filterId);
|
||||||
if (i == end(_chatListLinks)) {
|
if (i == end(_chatListLinks)) {
|
||||||
return;
|
return;
|
||||||
|
@ -1278,7 +1278,8 @@ bool InnerWidget::updateReorderPinned(QPoint localPosition) {
|
|||||||
const auto delta = [&] {
|
const auto delta = [&] {
|
||||||
if (localPosition.y() < _visibleTop) {
|
if (localPosition.y() < _visibleTop) {
|
||||||
return localPosition.y() - _visibleTop;
|
return localPosition.y() - _visibleTop;
|
||||||
} else if (_openedFolder && localPosition.y() > _visibleBottom) {
|
} else if ((_openedFolder || _filterId)
|
||||||
|
&& localPosition.y() > _visibleBottom) {
|
||||||
return localPosition.y() - _visibleBottom;
|
return localPosition.y() - _visibleBottom;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -3074,6 +3075,54 @@ void InnerWidget::setupShortcuts() {
|
|||||||
return jumpToDialogRow({ row->key(), FullMsgId() });
|
return jumpToDialogRow({ row->key(), FullMsgId() });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto &&folders = ranges::view::zip(
|
||||||
|
Shortcuts::kShowFolder,
|
||||||
|
ranges::view::ints(0, ranges::unreachable));
|
||||||
|
|
||||||
|
for (const auto [command, index] : folders) {
|
||||||
|
request->check(command) && request->handle([=, index = index] {
|
||||||
|
const auto list = &session().data().chatsFilters().list();
|
||||||
|
if (index >= list->size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto filterId = list->at(index).id();
|
||||||
|
_controller->setActiveChatsFilter((filterId == _filterId)
|
||||||
|
? 0
|
||||||
|
: filterId);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto nearFolder = [=](bool isNext) {
|
||||||
|
const auto id = _controller->activeChatsFilterCurrent();
|
||||||
|
const auto list = &session().data().chatsFilters().list();
|
||||||
|
const auto it = (id == 0)
|
||||||
|
? begin(*list) - 1
|
||||||
|
: ranges::find(*list, id, &Data::ChatFilter::id);
|
||||||
|
if (it == end(*list) && id != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto i = isNext ? 1 : -1;
|
||||||
|
const auto index = it - begin(*list) + i;
|
||||||
|
if (index >= (int)list->size() || index < -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto filterId = (index == -1)
|
||||||
|
? 0
|
||||||
|
: list->at(index).id();
|
||||||
|
_controller->setActiveChatsFilter(filterId);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
request->check(Command::FolderNext) && request->handle([=] {
|
||||||
|
return nearFolder(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
request->check(Command::FolderPrevious) && request->handle([=] {
|
||||||
|
return nearFolder(false);
|
||||||
|
});
|
||||||
|
|
||||||
if (session().supportMode() && row.key.history()) {
|
if (session().supportMode() && row.key.history()) {
|
||||||
request->check(
|
request->check(
|
||||||
Command::SupportScrollToCurrent
|
Command::SupportScrollToCurrent
|
||||||
|
@ -745,7 +745,9 @@ void Widget::onDraggingScrollDelta(int delta) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Widget::onDraggingScrollTimer() {
|
void Widget::onDraggingScrollTimer() {
|
||||||
auto delta = (_draggingScrollDelta > 0) ? qMin(_draggingScrollDelta * 3 / 20 + 1, int32(Ui::kMaxScrollSpeed)) : qMax(_draggingScrollDelta * 3 / 20 - 1, -int32(Ui::kMaxScrollSpeed));
|
const auto delta = (_draggingScrollDelta > 0)
|
||||||
|
? qMin(_draggingScrollDelta * 3 / 20 + 1, Ui::kMaxScrollSpeed)
|
||||||
|
: qMax(_draggingScrollDelta * 3 / 20 - 1, -Ui::kMaxScrollSpeed);
|
||||||
_scroll->scrollToY(_scroll->scrollTop() + delta);
|
_scroll->scrollToY(_scroll->scrollTop() + delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1826,6 +1826,7 @@ void HistoryWidget::showHistory(
|
|||||||
|
|
||||||
_showAtMsgId = showAtMsgId;
|
_showAtMsgId = showAtMsgId;
|
||||||
_historyInited = false;
|
_historyInited = false;
|
||||||
|
_contactStatus = nullptr;
|
||||||
|
|
||||||
// Unload lottie animations.
|
// Unload lottie animations.
|
||||||
Auth().data().unloadHeavyViewParts(HistoryInner::ElementDelegate());
|
Auth().data().unloadHeavyViewParts(HistoryInner::ElementDelegate());
|
||||||
@ -1843,8 +1844,6 @@ void HistoryWidget::showHistory(
|
|||||||
}, _contactStatus->lifetime());
|
}, _contactStatus->lifetime());
|
||||||
orderWidgets();
|
orderWidgets();
|
||||||
controller()->tabbedSelector()->setCurrentPeer(_peer);
|
controller()->tabbedSelector()->setCurrentPeer(_peer);
|
||||||
} else {
|
|
||||||
_contactStatus = nullptr;
|
|
||||||
}
|
}
|
||||||
refreshTabbedPanel();
|
refreshTabbedPanel();
|
||||||
|
|
||||||
|
@ -13,6 +13,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#include "history/history_item.h"
|
#include "history/history_item.h"
|
||||||
#include "history/history_item_components.h"
|
#include "history/history_item_components.h"
|
||||||
#include "history/view/history_view_element.h"
|
#include "history/view/history_view_element.h"
|
||||||
|
#include "ui/toast/toast.h"
|
||||||
|
#include "lang/lang_keys.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
|
|
||||||
namespace HistoryView {
|
namespace HistoryView {
|
||||||
@ -30,10 +32,9 @@ Dice::Dice(not_null<Element*> parent, not_null<Data::MediaDice*> dice)
|
|||||||
, _dice(dice)
|
, _dice(dice)
|
||||||
, _start(parent, Lookup(parent, 0)) {
|
, _start(parent, Lookup(parent, 0)) {
|
||||||
_showLastFrame = _parent->data()->Has<HistoryMessageForwarded>();
|
_showLastFrame = _parent->data()->Has<HistoryMessageForwarded>();
|
||||||
|
_start.setDiceIndex(0);
|
||||||
if (_showLastFrame) {
|
if (_showLastFrame) {
|
||||||
_drawingEnd = true;
|
_drawingEnd = true;
|
||||||
} else {
|
|
||||||
_start.setDiceIndex(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,6 +44,20 @@ QSize Dice::size() {
|
|||||||
return _start.size();
|
return _start.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClickHandlerPtr Dice::link() {
|
||||||
|
if (_parent->data()->Has<HistoryMessageForwarded>()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
static auto kHandler = std::make_shared<LambdaClickHandler>([] {
|
||||||
|
auto config = Ui::Toast::Config();
|
||||||
|
config.multiline = true;
|
||||||
|
config.minWidth = st::msgMinWidth;
|
||||||
|
config.text = tr::lng_about_dice(tr::now);
|
||||||
|
Ui::Toast::Show(config);
|
||||||
|
});
|
||||||
|
return kHandler;
|
||||||
|
}
|
||||||
|
|
||||||
void Dice::draw(Painter &p, const QRect &r, bool selected) {
|
void Dice::draw(Painter &p, const QRect &r, bool selected) {
|
||||||
if (const auto value = _end ? 0 : _dice->diceValue()) {
|
if (const auto value = _end ? 0 : _dice->diceValue()) {
|
||||||
if (const auto document = Lookup(_parent, value)) {
|
if (const auto document = Lookup(_parent, value)) {
|
||||||
|
@ -24,6 +24,8 @@ public:
|
|||||||
QSize size() override;
|
QSize size() override;
|
||||||
void draw(Painter &p, const QRect &r, bool selected) override;
|
void draw(Painter &p, const QRect &r, bool selected) override;
|
||||||
|
|
||||||
|
ClickHandlerPtr link() override;
|
||||||
|
|
||||||
void clearStickerLoopPlayed() override {
|
void clearStickerLoopPlayed() override {
|
||||||
}
|
}
|
||||||
void unloadHeavyPart() override {
|
void unloadHeavyPart() override {
|
||||||
|
@ -31,12 +31,22 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
namespace HistoryView {
|
namespace HistoryView {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
double GetEmojiStickerZoom(not_null<Main::Session*> session) {
|
[[nodiscard]] double GetEmojiStickerZoom(not_null<Main::Session*> session) {
|
||||||
return session->account().appConfig().get<double>(
|
return session->account().appConfig().get<double>(
|
||||||
"emojies_animated_zoom",
|
"emojies_animated_zoom",
|
||||||
0.625);
|
0.625);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] QImage CacheDiceImage(int index, const QImage &image) {
|
||||||
|
static auto Cache = base::flat_map<int, QImage>();
|
||||||
|
const auto i = Cache.find(index);
|
||||||
|
if (i != end(Cache) && i->second.size() == image.size()) {
|
||||||
|
return i->second;
|
||||||
|
}
|
||||||
|
Cache[index] = image;
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Sticker::Sticker(
|
Sticker::Sticker(
|
||||||
@ -117,7 +127,7 @@ void Sticker::paintLottie(Painter &p, const QRect &r, bool selected) {
|
|||||||
: Lottie::Animation::FrameInfo();
|
: Lottie::Animation::FrameInfo();
|
||||||
if (_nextLastDiceFrame) {
|
if (_nextLastDiceFrame) {
|
||||||
_nextLastDiceFrame = false;
|
_nextLastDiceFrame = false;
|
||||||
_lastDiceFrame = frame.image;
|
_lastDiceFrame = CacheDiceImage(_diceIndex, frame.image);
|
||||||
}
|
}
|
||||||
const auto &image = _lastDiceFrame.isNull()
|
const auto &image = _lastDiceFrame.isNull()
|
||||||
? frame.image
|
? frame.image
|
||||||
@ -255,6 +265,10 @@ void Sticker::unloadLottie() {
|
|||||||
if (!_lottie) {
|
if (!_lottie) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (_diceIndex > 0 && _lastDiceFrame.isNull()) {
|
||||||
|
_nextLastDiceFrame = false;
|
||||||
|
_lottieOncePlayed = false;
|
||||||
|
}
|
||||||
_lottie = nullptr;
|
_lottie = nullptr;
|
||||||
_parent->data()->history()->owner().unregisterHeavyViewPart(_parent);
|
_parent->data()->history()->owner().unregisterHeavyViewPart(_parent);
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#include "ui/widgets/labels.h"
|
#include "ui/widgets/labels.h"
|
||||||
#include "ui/wrap/fade_wrap.h"
|
#include "ui/wrap/fade_wrap.h"
|
||||||
#include "core/update_checker.h"
|
#include "core/update_checker.h"
|
||||||
|
#include "core/application.h"
|
||||||
|
#include "mtproto/dc_options.h"
|
||||||
#include "window/window_slide_animation.h"
|
#include "window/window_slide_animation.h"
|
||||||
#include "window/window_connecting_widget.h"
|
#include "window/window_connecting_widget.h"
|
||||||
#include "base/platform/base_platform_info.h"
|
#include "base/platform/base_platform_info.h"
|
||||||
|
#include "api/api_text_entities.h"
|
||||||
#include "facades.h"
|
#include "facades.h"
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
#include "styles/style_layers.h"
|
#include "styles/style_layers.h"
|
||||||
@ -72,6 +75,11 @@ Widget::Widget(QWidget *parent, not_null<Main::Account*> account)
|
|||||||
createLanguageLink();
|
createLanguageLink();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_account->mtpUpdates(
|
||||||
|
) | rpl::start_with_next([=](const MTPUpdates &updates) {
|
||||||
|
handleUpdates(updates);
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
_back->entity()->setClickedCallback([=] {
|
_back->entity()->setClickedCallback([=] {
|
||||||
historyMove(Direction::Back);
|
historyMove(Direction::Back);
|
||||||
});
|
});
|
||||||
@ -116,6 +124,34 @@ void Widget::refreshLang() {
|
|||||||
InvokeQueued(this, [this] { updateControlsGeometry(); });
|
InvokeQueued(this, [this] { updateControlsGeometry(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Widget::handleUpdates(const MTPUpdates &updates) {
|
||||||
|
updates.match([&](const MTPDupdateShort &data) {
|
||||||
|
handleUpdate(data.vupdate());
|
||||||
|
}, [&](const MTPDupdates &data) {
|
||||||
|
for (const auto &update : data.vupdates().v) {
|
||||||
|
handleUpdate(update);
|
||||||
|
}
|
||||||
|
}, [&](const MTPDupdatesCombined &data) {
|
||||||
|
for (const auto &update : data.vupdates().v) {
|
||||||
|
handleUpdate(update);
|
||||||
|
}
|
||||||
|
}, [](const auto &) {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::handleUpdate(const MTPUpdate &update) {
|
||||||
|
update.match([&](const MTPDupdateDcOptions &data) {
|
||||||
|
Core::App().dcOptions()->addFromList(data.vdc_options());
|
||||||
|
}, [&](const MTPDupdateConfig &data) {
|
||||||
|
_account->mtp()->requestConfig();
|
||||||
|
}, [&](const MTPDupdateServiceNotification &data) {
|
||||||
|
const auto text = TextWithEntities{
|
||||||
|
qs(data.vmessage()),
|
||||||
|
Api::EntitiesFromMTP(data.ventities().v)
|
||||||
|
};
|
||||||
|
Ui::show(Box<InformBox>(text));
|
||||||
|
}, [](const auto &) {});
|
||||||
|
}
|
||||||
|
|
||||||
void Widget::createLanguageLink() {
|
void Widget::createLanguageLink() {
|
||||||
if (_changeLanguage) {
|
if (_changeLanguage) {
|
||||||
return;
|
return;
|
||||||
@ -651,7 +687,6 @@ void Widget::updateControlsGeometry() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Widget::keyPressEvent(QKeyEvent *e) {
|
void Widget::keyPressEvent(QKeyEvent *e) {
|
||||||
if (_a_show.animating() || getStep()->animating()) return;
|
if (_a_show.animating() || getStep()->animating()) return;
|
||||||
|
|
||||||
|
@ -93,6 +93,8 @@ private:
|
|||||||
void createLanguageLink();
|
void createLanguageLink();
|
||||||
void checkUpdateStatus();
|
void checkUpdateStatus();
|
||||||
void setupNextButton();
|
void setupNextButton();
|
||||||
|
void handleUpdates(const MTPUpdates &updates);
|
||||||
|
void handleUpdate(const MTPUpdate &update);
|
||||||
|
|
||||||
void updateControlsGeometry();
|
void updateControlsGeometry();
|
||||||
[[nodiscard]] not_null<details::Data*> getData() {
|
[[nodiscard]] not_null<details::Data*> getData() {
|
||||||
|
@ -18,6 +18,7 @@ namespace {
|
|||||||
|
|
||||||
constexpr auto kSkipInvalidDataPackets = 10;
|
constexpr auto kSkipInvalidDataPackets = 10;
|
||||||
constexpr auto kMaxInlineArea = 1280 * 720;
|
constexpr auto kMaxInlineArea = 1280 * 720;
|
||||||
|
constexpr auto kMaxSendingArea = 3840 * 2160; // usual 4K
|
||||||
|
|
||||||
// See https://github.com/telegramdesktop/tdesktop/issues/7225
|
// See https://github.com/telegramdesktop/tdesktop/issues/7225
|
||||||
constexpr auto kAlignImageBy = 64;
|
constexpr auto kAlignImageBy = 64;
|
||||||
@ -60,7 +61,10 @@ ReaderImplementation::ReadResult FFMpegReaderImplementation::readNextFrame() {
|
|||||||
do {
|
do {
|
||||||
int res = avcodec_receive_frame(_codecContext, _frame.get());
|
int res = avcodec_receive_frame(_codecContext, _frame.get());
|
||||||
if (res >= 0) {
|
if (res >= 0) {
|
||||||
if (_frame->width * _frame->height > kMaxInlineArea) {
|
const auto limit = (_mode == Mode::Inspecting)
|
||||||
|
? kMaxSendingArea
|
||||||
|
: kMaxInlineArea;
|
||||||
|
if (_frame->width * _frame->height > limit) {
|
||||||
return ReadResult::Error;
|
return ReadResult::Error;
|
||||||
}
|
}
|
||||||
processReadFrame();
|
processReadFrame();
|
||||||
|
@ -313,6 +313,14 @@ std::unique_ptr<QTemporaryFile> TrayIconFile(
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UseUnityCounter() {
|
||||||
|
static const auto UnityCounter = QDBusInterface(
|
||||||
|
"com.canonical.Unity",
|
||||||
|
"/").isValid();
|
||||||
|
|
||||||
|
return UnityCounter;
|
||||||
|
}
|
||||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||||
|
|
||||||
bool IsSNIAvailable() {
|
bool IsSNIAvailable() {
|
||||||
@ -341,18 +349,6 @@ bool IsSNIAvailable() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UseUnityCounter() {
|
|
||||||
#ifdef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
|
||||||
static const auto UnityCounter = false;
|
|
||||||
#else // TDESKTOP_DISABLE_DBUS_INTEGRATION
|
|
||||||
static const auto UnityCounter = QDBusInterface(
|
|
||||||
"com.canonical.Unity",
|
|
||||||
"/").isValid();
|
|
||||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
|
||||||
|
|
||||||
return UnityCounter;
|
|
||||||
}
|
|
||||||
|
|
||||||
quint32 djbStringHash(QString string) {
|
quint32 djbStringHash(QString string) {
|
||||||
quint32 hash = 5381;
|
quint32 hash = 5381;
|
||||||
QByteArray chars = string.toLatin1();
|
QByteArray chars = string.toLatin1();
|
||||||
@ -460,13 +456,19 @@ void MainWindow::initHook() {
|
|||||||
&QWindow::visibleChanged,
|
&QWindow::visibleChanged,
|
||||||
this,
|
this,
|
||||||
&MainWindow::onVisibleChanged);
|
&MainWindow::onVisibleChanged);
|
||||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
|
||||||
|
if (AppMenuSupported()) {
|
||||||
|
LOG(("Using D-Bus global menu."));
|
||||||
|
} else {
|
||||||
|
LOG(("Not using D-Bus global menu."));
|
||||||
|
}
|
||||||
|
|
||||||
if (UseUnityCounter()) {
|
if (UseUnityCounter()) {
|
||||||
LOG(("Using Unity launcher counter."));
|
LOG(("Using Unity launcher counter."));
|
||||||
} else {
|
} else {
|
||||||
LOG(("Not using Unity launcher counter."));
|
LOG(("Not using Unity launcher counter."));
|
||||||
}
|
}
|
||||||
|
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainWindow::hasTrayIcon() const {
|
bool MainWindow::hasTrayIcon() const {
|
||||||
|
@ -44,6 +44,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
using namespace Platform;
|
using namespace Platform;
|
||||||
using Platform::File::internal::EscapeShell;
|
using Platform::File::internal::EscapeShell;
|
||||||
|
|
||||||
|
namespace Platform {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr auto kDesktopFile = ":/misc/kotatogramdesktop.desktop"_cs;
|
constexpr auto kDesktopFile = ":/misc/kotatogramdesktop.desktop"_cs;
|
||||||
@ -95,23 +96,27 @@ bool RunShellCommand(const QByteArray &command) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FallbackFontConfig() {
|
[[nodiscard]] bool CheckFontConfigCrash() {
|
||||||
#ifdef TDESKTOP_USE_FONT_CONFIG_FALLBACK
|
return InSnap();
|
||||||
const auto custom = cWorkingDir() + "tdata/fc-custom-1.conf";
|
}
|
||||||
const auto finish = gsl::finally([&] {
|
|
||||||
if (QFile(custom).exists()) {
|
|
||||||
LOG(("Custom FONTCONFIG_FILE: ") + custom);
|
|
||||||
qputenv("FONTCONFIG_FILE", QFile::encodeName(custom));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
[[nodiscard]] QString FallbackFontConfigCheckPath() {
|
||||||
|
return cWorkingDir() + "tdata/fc-check";
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef TDESKTOP_USE_FONTCONFIG_FALLBACK
|
||||||
|
|
||||||
|
[[nodiscard]] bool BadFontConfigVersion() {
|
||||||
|
if (CheckFontConfigCrash()) {
|
||||||
|
return QFile(FallbackFontConfigCheckPath()).exists();
|
||||||
|
}
|
||||||
QProcess process;
|
QProcess process;
|
||||||
process.setProcessChannelMode(QProcess::MergedChannels);
|
process.setProcessChannelMode(QProcess::MergedChannels);
|
||||||
process.start("fc-list", QStringList() << "--version");
|
process.start("fc-list", QStringList() << "--version");
|
||||||
process.waitForFinished();
|
process.waitForFinished();
|
||||||
if (process.exitCode() > 0) {
|
if (process.exitCode() > 0) {
|
||||||
LOG(("App Error: Could not start fc-list. Process exited with code: %1.").arg(process.exitCode()));
|
LOG(("App Error: Could not start fc-list. Process exited with code: %1.").arg(process.exitCode()));
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString result(process.readAllStandardOutput());
|
QString result(process.readAllStandardOutput());
|
||||||
@ -120,20 +125,31 @@ void FallbackFontConfig() {
|
|||||||
QVersionNumber version = QVersionNumber::fromString(result.split("version ").last());
|
QVersionNumber version = QVersionNumber::fromString(result.split("version ").last());
|
||||||
if (version.isNull()) {
|
if (version.isNull()) {
|
||||||
LOG(("App Error: Could not get version from fc-list output."));
|
LOG(("App Error: Could not get version from fc-list output."));
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(("Fontconfig version: %1.").arg(version.toString()));
|
LOG(("Fontconfig version: %1.").arg(version.toString()));
|
||||||
if (version < QVersionNumber::fromString("2.13")) {
|
if (version < QVersionNumber::fromString("2.13")) {
|
||||||
if (qgetenv("TDESKTOP_FORCE_CUSTOM_FONTCONFIG").isEmpty()) {
|
if (qgetenv("TDESKTOP_FORCE_CUSTOM_FONTCONFIG").isEmpty()) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
QFile(":/fc/fc-custom.conf").copy(custom);
|
|
||||||
#endif // TDESKTOP_USE_FONT_CONFIG_FALLBACK
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FallbackFontConfig() {
|
||||||
|
if (BadFontConfigVersion()) {
|
||||||
|
const auto custom = cWorkingDir() + "tdata/fc-custom-1.conf";
|
||||||
|
QFile(":/fc/fc-custom.conf").copy(custom);
|
||||||
|
if (QFile(custom).exists()) {
|
||||||
|
LOG(("Custom FONTCONFIG_FILE: ") + custom);
|
||||||
|
qputenv("FONTCONFIG_FILE", QFile::encodeName(custom));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TDESKTOP_USE_FONTCONFIG_FALLBACK
|
||||||
|
|
||||||
bool GenerateDesktopFile(
|
bool GenerateDesktopFile(
|
||||||
const QString &targetPath,
|
const QString &targetPath,
|
||||||
const QString &args,
|
const QString &args,
|
||||||
@ -208,8 +224,6 @@ bool GenerateDesktopFile(
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace Platform {
|
|
||||||
|
|
||||||
void SetApplicationIcon(const QIcon &icon) {
|
void SetApplicationIcon(const QIcon &icon) {
|
||||||
QApplication::setWindowIcon(icon);
|
QApplication::setWindowIcon(icon);
|
||||||
}
|
}
|
||||||
@ -404,6 +418,23 @@ std::optional<crl::time> LastUserInputTime() {
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FallbackFontConfigCheckBegin() {
|
||||||
|
if (!CheckFontConfigCrash()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto file = QFile(FallbackFontConfigCheckPath());
|
||||||
|
if (file.open(QIODevice::WriteOnly)) {
|
||||||
|
file.write("1", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FallbackFontConfigCheckEnd() {
|
||||||
|
if (!CheckFontConfigCrash()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QFile(FallbackFontConfigCheckPath()).remove();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Platform
|
} // namespace Platform
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -521,7 +552,10 @@ namespace Platform {
|
|||||||
|
|
||||||
void start() {
|
void start() {
|
||||||
LOG(("Launcher filename: %1").arg(GetLauncherFilename()));
|
LOG(("Launcher filename: %1").arg(GetLauncherFilename()));
|
||||||
|
|
||||||
|
#ifdef TDESKTOP_USE_FONTCONFIG_FALLBACK
|
||||||
FallbackFontConfig();
|
FallbackFontConfig();
|
||||||
|
#endif // TDESKTOP_USE_FONTCONFIG_FALLBACK
|
||||||
|
|
||||||
qputenv("PULSE_PROP_application.name", AppName.utf8());
|
qputenv("PULSE_PROP_application.name", AppName.utf8());
|
||||||
qputenv("PULSE_PROP_application.icon_name", GetIconName().toLatin1());
|
qputenv("PULSE_PROP_application.icon_name", GetIconName().toLatin1());
|
||||||
@ -529,9 +563,9 @@ void start() {
|
|||||||
#ifdef TDESKTOP_FORCE_GTK_FILE_DIALOG
|
#ifdef TDESKTOP_FORCE_GTK_FILE_DIALOG
|
||||||
LOG(("Checking for XDG Desktop Portal..."));
|
LOG(("Checking for XDG Desktop Portal..."));
|
||||||
// this can give us a chance to use a proper file dialog for current session
|
// this can give us a chance to use a proper file dialog for current session
|
||||||
if(IsXDGDesktopPortalPresent()) {
|
if (IsXDGDesktopPortalPresent()) {
|
||||||
LOG(("XDG Desktop Portal is present!"));
|
LOG(("XDG Desktop Portal is present!"));
|
||||||
if(UseXDGDesktopPortal()) {
|
if (UseXDGDesktopPortal()) {
|
||||||
LOG(("Usage of XDG Desktop Portal is enabled."));
|
LOG(("Usage of XDG Desktop Portal is enabled."));
|
||||||
qputenv("QT_QPA_PLATFORMTHEME", "xdgdesktopportal");
|
qputenv("QT_QPA_PLATFORMTHEME", "xdgdesktopportal");
|
||||||
} else {
|
} else {
|
||||||
|
@ -40,6 +40,9 @@ QString GetIconName();
|
|||||||
inline void IgnoreApplicationActivationRightNow() {
|
inline void IgnoreApplicationActivationRightNow() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FallbackFontConfigCheckBegin();
|
||||||
|
void FallbackFontConfigCheckEnd();
|
||||||
|
|
||||||
} // namespace Platform
|
} // namespace Platform
|
||||||
|
|
||||||
inline void psCheckLocalSocket(const QString &serverName) {
|
inline void psCheckLocalSocket(const QString &serverName) {
|
||||||
|
@ -22,6 +22,12 @@ QString SingleInstanceLocalServerName(const QString &hash);
|
|||||||
|
|
||||||
void RemoveQuarantine(const QString &path);
|
void RemoveQuarantine(const QString &path);
|
||||||
|
|
||||||
|
inline void FallbackFontConfigCheckBegin() {
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FallbackFontConfigCheckEnd() {
|
||||||
|
}
|
||||||
|
|
||||||
namespace ThirdParty {
|
namespace ThirdParty {
|
||||||
|
|
||||||
inline void start() {
|
inline void start() {
|
||||||
|
@ -26,6 +26,12 @@ QString SingleInstanceLocalServerName(const QString &hash);
|
|||||||
inline void IgnoreApplicationActivationRightNow() {
|
inline void IgnoreApplicationActivationRightNow() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void FallbackFontConfigCheckBegin() {
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FallbackFontConfigCheckEnd() {
|
||||||
|
}
|
||||||
|
|
||||||
namespace ThirdParty {
|
namespace ThirdParty {
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
|
@ -15,6 +15,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#include "data/data_drafts.h"
|
#include "data/data_drafts.h"
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
#include "boxes/send_files_box.h"
|
#include "boxes/send_files_box.h"
|
||||||
|
#include "base/flags.h"
|
||||||
|
#include "base/platform/base_platform_file_utilities.h"
|
||||||
#include "base/platform/base_platform_info.h"
|
#include "base/platform/base_platform_info.h"
|
||||||
#include "ui/widgets/input_fields.h"
|
#include "ui/widgets/input_fields.h"
|
||||||
#include "ui/emoji_config.h"
|
#include "ui/emoji_config.h"
|
||||||
@ -35,7 +37,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "window/themes/window_theme.h"
|
#include "window/themes/window_theme.h"
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
#include "base/flags.h"
|
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "facades.h"
|
#include "facades.h"
|
||||||
@ -251,97 +252,24 @@ struct EncryptedDescriptor {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct FileWriteDescriptor {
|
struct FileWriteDescriptor {
|
||||||
FileWriteDescriptor(const FileKey &key, FileOptions options = FileOption::User | FileOption::Safe)
|
FileWriteDescriptor(
|
||||||
: file((options & FileOption::Safe) ? (QFileDevice&)saveFile : plainFile) {
|
const FileKey &key,
|
||||||
init(toFilePart(key), options);
|
FileOptions options = FileOption::User | FileOption::Safe);
|
||||||
}
|
FileWriteDescriptor(
|
||||||
FileWriteDescriptor(const QString &name, FileOptions options = FileOption::User | FileOption::Safe)
|
const QString &name,
|
||||||
: file((options & FileOption::Safe) ? (QFileDevice&)saveFile : plainFile) {
|
FileOptions options = FileOption::User | FileOption::Safe);
|
||||||
init(name, options);
|
~FileWriteDescriptor();
|
||||||
}
|
|
||||||
void init(const QString &name, FileOptions options) {
|
|
||||||
if (options & FileOption::User) {
|
|
||||||
if (!_userWorking()) return;
|
|
||||||
} else {
|
|
||||||
if (!_working()) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto base = ((options & FileOption::User) ? _userBasePath : _basePath) + name;
|
void init(const QString &name, FileOptions options);
|
||||||
if (options & FileOption::Safe) {
|
bool writeData(const QByteArray &data);
|
||||||
toDelete = base;
|
bool writeEncrypted(
|
||||||
saveFile.setFileName(base + 's');
|
EncryptedDescriptor &data,
|
||||||
} else {
|
const MTP::AuthKeyPtr &key = LocalKey);
|
||||||
plainFile.setFileName(base + '0');
|
void finish();
|
||||||
}
|
|
||||||
if (file.open(QIODevice::WriteOnly)) {
|
|
||||||
file.write(tdfMagic, tdfMagicLen);
|
|
||||||
qint32 version = AppVersion;
|
|
||||||
file.write((const char*)&version, sizeof(version));
|
|
||||||
|
|
||||||
stream.setDevice(&file);
|
|
||||||
stream.setVersion(QDataStream::Qt_5_1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool writeData(const QByteArray &data) {
|
|
||||||
if (!file.isOpen()) return false;
|
|
||||||
|
|
||||||
stream << data;
|
|
||||||
quint32 len = data.isNull() ? 0xffffffff : data.size();
|
|
||||||
if (QSysInfo::ByteOrder != QSysInfo::BigEndian) {
|
|
||||||
len = qbswap(len);
|
|
||||||
}
|
|
||||||
md5.feed(&len, sizeof(len));
|
|
||||||
md5.feed(data.constData(), data.size());
|
|
||||||
dataSize += sizeof(len) + data.size();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
static QByteArray prepareEncrypted(EncryptedDescriptor &data, const MTP::AuthKeyPtr &key = LocalKey) {
|
|
||||||
data.finish();
|
|
||||||
QByteArray &toEncrypt(data.data);
|
|
||||||
|
|
||||||
// prepare for encryption
|
|
||||||
uint32 size = toEncrypt.size(), fullSize = size;
|
|
||||||
if (fullSize & 0x0F) {
|
|
||||||
fullSize += 0x10 - (fullSize & 0x0F);
|
|
||||||
toEncrypt.resize(fullSize);
|
|
||||||
memset_rand(toEncrypt.data() + size, fullSize - size);
|
|
||||||
}
|
|
||||||
*(uint32*)toEncrypt.data() = size;
|
|
||||||
QByteArray encrypted(0x10 + fullSize, Qt::Uninitialized); // 128bit of sha1 - key128, sizeof(data), data
|
|
||||||
hashSha1(toEncrypt.constData(), toEncrypt.size(), encrypted.data());
|
|
||||||
MTP::aesEncryptLocal(toEncrypt.constData(), encrypted.data() + 0x10, fullSize, key, encrypted.constData());
|
|
||||||
|
|
||||||
return encrypted;
|
|
||||||
}
|
|
||||||
bool writeEncrypted(EncryptedDescriptor &data, const MTP::AuthKeyPtr &key = LocalKey) {
|
|
||||||
return writeData(prepareEncrypted(data, key));
|
|
||||||
}
|
|
||||||
void finish() {
|
|
||||||
if (!file.isOpen()) return;
|
|
||||||
|
|
||||||
stream.setDevice(nullptr);
|
|
||||||
|
|
||||||
md5.feed(&dataSize, sizeof(dataSize));
|
|
||||||
qint32 version = AppVersion;
|
|
||||||
md5.feed(&version, sizeof(version));
|
|
||||||
md5.feed(tdfMagic, tdfMagicLen);
|
|
||||||
file.write((const char*)md5.result(), 0x10);
|
|
||||||
|
|
||||||
if (saveFile.isOpen()) {
|
|
||||||
saveFile.commit();
|
|
||||||
} else {
|
|
||||||
plainFile.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!toDelete.isEmpty()) {
|
|
||||||
QFile::remove(toDelete + '0');
|
|
||||||
QFile::remove(toDelete + '1');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
QFile plainFile;
|
QFile plainFile;
|
||||||
QSaveFile saveFile;
|
QSaveFile saveFile;
|
||||||
QFileDevice &file;
|
not_null<QFileDevice*> file;
|
||||||
QDataStream stream;
|
QDataStream stream;
|
||||||
|
|
||||||
QString toDelete;
|
QString toDelete;
|
||||||
@ -349,11 +277,141 @@ struct FileWriteDescriptor {
|
|||||||
HashMd5 md5;
|
HashMd5 md5;
|
||||||
int32 dataSize = 0;
|
int32 dataSize = 0;
|
||||||
|
|
||||||
~FileWriteDescriptor() {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] QByteArray PrepareEncrypted(
|
||||||
|
EncryptedDescriptor &data,
|
||||||
|
const MTP::AuthKeyPtr &key = LocalKey) {
|
||||||
|
data.finish();
|
||||||
|
QByteArray &toEncrypt(data.data);
|
||||||
|
|
||||||
|
// prepare for encryption
|
||||||
|
uint32 size = toEncrypt.size(), fullSize = size;
|
||||||
|
if (fullSize & 0x0F) {
|
||||||
|
fullSize += 0x10 - (fullSize & 0x0F);
|
||||||
|
toEncrypt.resize(fullSize);
|
||||||
|
memset_rand(toEncrypt.data() + size, fullSize - size);
|
||||||
|
}
|
||||||
|
*(uint32*)toEncrypt.data() = size;
|
||||||
|
QByteArray encrypted(0x10 + fullSize, Qt::Uninitialized); // 128bit of sha1 - key128, sizeof(data), data
|
||||||
|
hashSha1(toEncrypt.constData(), toEncrypt.size(), encrypted.data());
|
||||||
|
MTP::aesEncryptLocal(toEncrypt.constData(), encrypted.data() + 0x10, fullSize, key, encrypted.constData());
|
||||||
|
|
||||||
|
return encrypted;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileWriteDescriptor::FileWriteDescriptor(
|
||||||
|
const FileKey &key,
|
||||||
|
FileOptions options)
|
||||||
|
: file((options & FileOption::Safe) ? (QFileDevice*)&saveFile : &plainFile) {
|
||||||
|
init(toFilePart(key), options);
|
||||||
|
}
|
||||||
|
|
||||||
|
FileWriteDescriptor::FileWriteDescriptor(
|
||||||
|
const QString &name,
|
||||||
|
FileOptions options)
|
||||||
|
: file((options & FileOption::Safe) ? (QFileDevice*)&saveFile : &plainFile) {
|
||||||
|
init(name, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
FileWriteDescriptor::~FileWriteDescriptor() {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileWriteDescriptor::init(const QString &name, FileOptions options) {
|
||||||
|
if (options & FileOption::User) {
|
||||||
|
if (!_userWorking()) return;
|
||||||
|
} else {
|
||||||
|
if (!_working()) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto base = ((options & FileOption::User) ? _userBasePath : _basePath) + name;
|
||||||
|
saveFile.setFileName(base + 's');
|
||||||
|
plainFile.setFileName(base + '0');
|
||||||
|
if (options & FileOption::Safe) {
|
||||||
|
toDelete = base;
|
||||||
|
}
|
||||||
|
if (!file->open(QIODevice::WriteOnly)) {
|
||||||
|
LOG(("Storage Error: Could not open '%1' for writing.").arg(file->fileName()));
|
||||||
|
if (!(options & FileOption::Safe)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
file = &plainFile;
|
||||||
|
LOG(("Storage Info: Trying to fallback to '%1'.").arg(file->fileName()));
|
||||||
|
if (!file->open(QIODevice::WriteOnly)) {
|
||||||
|
LOG(("Storage Error: Could not open '%1' for safe writing.").arg(file->fileName()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file->write(tdfMagic, tdfMagicLen);
|
||||||
|
qint32 version = AppVersion;
|
||||||
|
file->write((const char*)&version, sizeof(version));
|
||||||
|
|
||||||
|
stream.setDevice(file);
|
||||||
|
stream.setVersion(QDataStream::Qt_5_1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileWriteDescriptor::writeData(const QByteArray &data) {
|
||||||
|
if (!file->isOpen()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream << data;
|
||||||
|
quint32 len = data.isNull() ? 0xffffffff : data.size();
|
||||||
|
if (QSysInfo::ByteOrder != QSysInfo::BigEndian) {
|
||||||
|
len = qbswap(len);
|
||||||
|
}
|
||||||
|
md5.feed(&len, sizeof(len));
|
||||||
|
md5.feed(data.constData(), data.size());
|
||||||
|
dataSize += sizeof(len) + data.size();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileWriteDescriptor::writeEncrypted(
|
||||||
|
EncryptedDescriptor &data,
|
||||||
|
const MTP::AuthKeyPtr &key) {
|
||||||
|
return writeData(PrepareEncrypted(data, key));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileWriteDescriptor::finish() {
|
||||||
|
if (!file->isOpen()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.setDevice(nullptr);
|
||||||
|
|
||||||
|
md5.feed(&dataSize, sizeof(dataSize));
|
||||||
|
qint32 version = AppVersion;
|
||||||
|
md5.feed(&version, sizeof(version));
|
||||||
|
md5.feed(tdfMagic, tdfMagicLen);
|
||||||
|
file->write((const char*)md5.result(), 0x10);
|
||||||
|
|
||||||
|
if (saveFile.isOpen()) {
|
||||||
|
if (!saveFile.commit()) {
|
||||||
|
LOG(("Storage Error: Could not commit safe writing in '%1'."
|
||||||
|
).arg(saveFile.fileName()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
plainFile.close();
|
||||||
|
if (!toDelete.isEmpty()) {
|
||||||
|
QFile::remove(toDelete + '1');
|
||||||
|
if (!base::Platform::RenameWithOverwrite(
|
||||||
|
plainFile.fileName(),
|
||||||
|
saveFile.fileName())) {
|
||||||
|
LOG(("Storage Error: Could not rename '%1' to '%2'"
|
||||||
|
).arg(plainFile.fileName()
|
||||||
|
).arg(saveFile.fileName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!toDelete.isEmpty()) {
|
||||||
|
QFile::remove(toDelete + '0');
|
||||||
|
QFile::remove(toDelete + '1');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool readFile(FileReadDescriptor &result, const QString &name, FileOptions options = FileOption::User | FileOption::Safe) {
|
bool readFile(FileReadDescriptor &result, const QString &name, FileOptions options = FileOption::User | FileOption::Safe) {
|
||||||
if (options & FileOption::User) {
|
if (options & FileOption::User) {
|
||||||
if (!_userWorking()) return false;
|
if (!_userWorking()) return false;
|
||||||
@ -2484,7 +2542,7 @@ void _writeMap(WriteMapWhen when) {
|
|||||||
|
|
||||||
EncryptedDescriptor passKeyData(kLocalKeySize);
|
EncryptedDescriptor passKeyData(kLocalKeySize);
|
||||||
LocalKey->write(passKeyData.stream);
|
LocalKey->write(passKeyData.stream);
|
||||||
_passKeyEncrypted = FileWriteDescriptor::prepareEncrypted(passKeyData, PassKey);
|
_passKeyEncrypted = PrepareEncrypted(passKeyData, PassKey);
|
||||||
}
|
}
|
||||||
map.writeData(_passKeySalt);
|
map.writeData(_passKeySalt);
|
||||||
map.writeData(_passKeyEncrypted);
|
map.writeData(_passKeyEncrypted);
|
||||||
@ -2873,7 +2931,7 @@ void setPasscode(const QByteArray &passcode) {
|
|||||||
|
|
||||||
EncryptedDescriptor passKeyData(kLocalKeySize);
|
EncryptedDescriptor passKeyData(kLocalKeySize);
|
||||||
LocalKey->write(passKeyData.stream);
|
LocalKey->write(passKeyData.stream);
|
||||||
_passKeyEncrypted = FileWriteDescriptor::prepareEncrypted(passKeyData, PassKey);
|
_passKeyEncrypted = PrepareEncrypted(passKeyData, PassKey);
|
||||||
|
|
||||||
_mapChanged = true;
|
_mapChanged = true;
|
||||||
_writeMap(WriteMapWhen::Now);
|
_writeMap(WriteMapWhen::Now);
|
||||||
|
@ -123,9 +123,12 @@ void FiltersMenu::setup() {
|
|||||||
const auto j = _filters.find(_activeFilterId);
|
const auto j = _filters.find(_activeFilterId);
|
||||||
if (j != end(_filters)) {
|
if (j != end(_filters)) {
|
||||||
j->second->setActive(true);
|
j->second->setActive(true);
|
||||||
|
scrollToButton(j->second);
|
||||||
} else if (!_activeFilterId) {
|
} else if (!_activeFilterId) {
|
||||||
_all->setActive(true);
|
_all->setActive(true);
|
||||||
|
scrollToButton(_all);
|
||||||
}
|
}
|
||||||
|
_reorder->finishReordering();
|
||||||
}, _outer.lifetime());
|
}, _outer.lifetime());
|
||||||
|
|
||||||
_menu.setClickedCallback([=] {
|
_menu.setClickedCallback([=] {
|
||||||
@ -133,6 +136,32 @@ void FiltersMenu::setup() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FiltersMenu::scrollToButton(not_null<Ui::RpWidget*> widget) {
|
||||||
|
const auto globalPosition = widget->mapToGlobal(QPoint(0, 0));
|
||||||
|
const auto localTop = _scroll.mapFromGlobal(globalPosition).y();
|
||||||
|
const auto localBottom = localTop + widget->height() - _scroll.height();
|
||||||
|
const auto isTopEdge = (localTop < 0);
|
||||||
|
const auto isBottomEdge = (localBottom > 0);
|
||||||
|
if (!isTopEdge && !isBottomEdge) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_scrollToAnimation.stop();
|
||||||
|
const auto scrollTop = _scroll.scrollTop();
|
||||||
|
const auto scrollTo = scrollTop + (isBottomEdge ? localBottom : localTop);
|
||||||
|
|
||||||
|
auto scroll = [=] {
|
||||||
|
_scroll.scrollToY(qRound(_scrollToAnimation.value(scrollTo)));
|
||||||
|
};
|
||||||
|
|
||||||
|
_scrollToAnimation.start(
|
||||||
|
std::move(scroll),
|
||||||
|
scrollTop,
|
||||||
|
scrollTo,
|
||||||
|
st::slideDuration,
|
||||||
|
anim::sineInOut);
|
||||||
|
}
|
||||||
|
|
||||||
void FiltersMenu::refresh(bool firstLoad) {
|
void FiltersMenu::refresh(bool firstLoad) {
|
||||||
const auto filters = &_session->session().data().chatsFilters();
|
const auto filters = &_session->session().data().chatsFilters();
|
||||||
if (filters->list().empty() || _ignoreRefresh) {
|
if (filters->list().empty() || _ignoreRefresh) {
|
||||||
@ -177,7 +206,7 @@ void FiltersMenu::setupList() {
|
|||||||
tr::lng_filters_setup(tr::now),
|
tr::lng_filters_setup(tr::now),
|
||||||
Ui::FilterIcon::Setup);
|
Ui::FilterIcon::Setup);
|
||||||
}
|
}
|
||||||
_reorder = std::make_unique<Ui::VerticalLayoutReorder>(_list);
|
_reorder = std::make_unique<Ui::VerticalLayoutReorder>(_list, &_scroll);
|
||||||
|
|
||||||
_reorder->updates(
|
_reorder->updates(
|
||||||
) | rpl::start_with_next([=](Ui::VerticalLayoutReorder::Single data) {
|
) | rpl::start_with_next([=](Ui::VerticalLayoutReorder::Single data) {
|
||||||
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "ui/effects/animations.h"
|
||||||
#include "ui/widgets/side_bar_button.h"
|
#include "ui/widgets/side_bar_button.h"
|
||||||
#include "ui/widgets/scroll_area.h"
|
#include "ui/widgets/scroll_area.h"
|
||||||
#include "ui/wrap/vertical_layout.h"
|
#include "ui/wrap/vertical_layout.h"
|
||||||
@ -51,6 +52,7 @@ private:
|
|||||||
void showEditBox(FilterId id);
|
void showEditBox(FilterId id);
|
||||||
void showRemoveBox(FilterId id);
|
void showRemoveBox(FilterId id);
|
||||||
void remove(FilterId id);
|
void remove(FilterId id);
|
||||||
|
void scrollToButton(not_null<Ui::RpWidget*> widget);
|
||||||
|
|
||||||
const not_null<SessionController*> _session;
|
const not_null<SessionController*> _session;
|
||||||
const not_null<Ui::RpWidget*> _parent;
|
const not_null<Ui::RpWidget*> _parent;
|
||||||
@ -70,6 +72,8 @@ private:
|
|||||||
|
|
||||||
base::unique_qptr<Ui::PopupMenu> _popupMenu;
|
base::unique_qptr<Ui::PopupMenu> _popupMenu;
|
||||||
|
|
||||||
|
Ui::Animations::Simple _scrollToAnimation;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Window
|
} // namespace Window
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
AppVersion 1009022
|
AppVersion 2000000
|
||||||
AppVersionStrMajor 1.9
|
AppVersionStrMajor 2.0
|
||||||
AppVersionStrSmall 1.9.22
|
AppVersionStrSmall 2.0
|
||||||
AppVersionStr 1.9.22
|
AppVersionStr 2.0.0
|
||||||
BetaChannel 1
|
BetaChannel 0
|
||||||
AlphaVersion 0
|
AlphaVersion 0
|
||||||
AppVersionOriginal 1.9.22.beta
|
AppVersionOriginal 2.0
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
# For license and copyright information please follow this link:
|
# For license and copyright information please follow this link:
|
||||||
# https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
# https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
|
option(TDESKTOP_USE_FONTCONFIG_FALLBACK "Use custom fonts.conf (Linux only)." OFF)
|
||||||
option(TDESKTOP_FORCE_GTK_FILE_DIALOG "Force using GTK file dialog (Linux only)." OFF)
|
option(TDESKTOP_FORCE_GTK_FILE_DIALOG "Force using GTK file dialog (Linux only)." OFF)
|
||||||
option(TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME "Disable automatic 'tg://' URL scheme handler registration." ${DESKTOP_APP_USE_PACKAGED})
|
option(TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME "Disable automatic 'tg://' URL scheme handler registration." ${DESKTOP_APP_USE_PACKAGED})
|
||||||
option(TDESKTOP_DISABLE_NETWORK_PROXY "Disable all code for working through Socks5 or MTProxy." OFF)
|
option(TDESKTOP_DISABLE_NETWORK_PROXY "Disable all code for working through Socks5 or MTProxy." OFF)
|
||||||
@ -63,6 +64,10 @@ if (DESKTOP_APP_SPECIAL_TARGET)
|
|||||||
target_compile_definitions(Telegram PRIVATE TDESKTOP_ALLOW_CLOSED_ALPHA)
|
target_compile_definitions(Telegram PRIVATE TDESKTOP_ALLOW_CLOSED_ALPHA)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (TDESKTOP_USE_FONTCONFIG_FALLBACK)
|
||||||
|
target_compile_definitions(Telegram PRIVATE TDESKTOP_USE_FONTCONFIG_FALLBACK)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (TDESKTOP_FORCE_GTK_FILE_DIALOG)
|
if (TDESKTOP_FORCE_GTK_FILE_DIALOG)
|
||||||
target_compile_definitions(Telegram PRIVATE TDESKTOP_FORCE_GTK_FILE_DIALOG)
|
target_compile_definitions(Telegram PRIVATE TDESKTOP_FORCE_GTK_FILE_DIALOG)
|
||||||
endif()
|
endif()
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 7de25679dd68f3fb7d2faee77ff5311f4d9587d6
|
Subproject commit 05b4e4e2a813b2888858acde80f67c4eafffdbce
|
@ -1,3 +1,12 @@
|
|||||||
|
2.0 (30.03.20)
|
||||||
|
|
||||||
|
- Organize chats into Chat Folders if you have too many chats.
|
||||||
|
- Create custom folders with flexible settings, or use default recommendations.
|
||||||
|
- Pin an unlimited number of chats in each folder.
|
||||||
|
- Switch between folders in the new side bar to easily access all of your chats.
|
||||||
|
- Send :dice: to any chat to try your luck and get a random number from the animated dice.
|
||||||
|
- Send :virus:, :face_with_thermometer:, :mask:, :face_with_head_bandage:, :sneeze:, :sick:, :soap: or :ambulance: to try out the new animated emoji.
|
||||||
|
|
||||||
1.9.22 beta (27.03.20)
|
1.9.22 beta (27.03.20)
|
||||||
|
|
||||||
- Organize chats into Chat Folders if you have too many chats.
|
- Organize chats into Chat Folders if you have too many chats.
|
||||||
|
2
cmake
2
cmake
@ -1 +1 @@
|
|||||||
Subproject commit d48723593fa05c57814c74221e6b39c4c1fb2297
|
Subproject commit b4ea62dfda376354aaae1482441a21ee06348580
|
@ -102,6 +102,7 @@ parts:
|
|||||||
- -DDESKTOP_APP_USE_PACKAGED_EXPECTED=OFF
|
- -DDESKTOP_APP_USE_PACKAGED_EXPECTED=OFF
|
||||||
- -DDESKTOP_APP_USE_PACKAGED_RLOTTIE=OFF
|
- -DDESKTOP_APP_USE_PACKAGED_RLOTTIE=OFF
|
||||||
- -DTDESKTOP_USE_PACKAGED_TGVOIP=OFF
|
- -DTDESKTOP_USE_PACKAGED_TGVOIP=OFF
|
||||||
|
- -DTDESKTOP_USE_FONTCONFIG_FALLBACK=ON
|
||||||
override-pull: |
|
override-pull: |
|
||||||
snapcraftctl pull
|
snapcraftctl pull
|
||||||
|
|
||||||
@ -109,10 +110,6 @@ parts:
|
|||||||
snapcraftctl set-version "$version"
|
snapcraftctl set-version "$version"
|
||||||
|
|
||||||
sed -i 's|^Icon=.*|Icon=/share/icons/hicolor/512x512/apps/kotatogram.png|g' lib/xdg/kotatogramdesktop.desktop
|
sed -i 's|^Icon=.*|Icon=/share/icons/hicolor/512x512/apps/kotatogram.png|g' lib/xdg/kotatogramdesktop.desktop
|
||||||
override-build: |
|
|
||||||
snapcraftctl build
|
|
||||||
mkdir -p "$SNAPCRAFT_PART_INSTALL/etc/fonts"
|
|
||||||
cp "$SNAPCRAFT_PART_SRC/Telegram/lib_ui/qt_conf/fc-custom.conf" "$SNAPCRAFT_PART_INSTALL/etc/fonts/fonts.conf"
|
|
||||||
after:
|
after:
|
||||||
- cmake
|
- cmake
|
||||||
- desktop-qt5
|
- desktop-qt5
|
||||||
@ -150,13 +147,11 @@ parts:
|
|||||||
- locales-all
|
- locales-all
|
||||||
- xdg-user-dirs
|
- xdg-user-dirs
|
||||||
- fcitx-frontend-qt5
|
- fcitx-frontend-qt5
|
||||||
stage: [-etc/fonts/fonts.conf]
|
|
||||||
|
|
||||||
qt5-gtk-platform:
|
qt5-gtk-platform:
|
||||||
plugin: nil
|
plugin: nil
|
||||||
stage-packages:
|
stage-packages:
|
||||||
- qt5-gtk-platformtheme
|
- qt5-gtk-platformtheme
|
||||||
stage: [-etc/fonts/fonts.conf]
|
|
||||||
|
|
||||||
cmake:
|
cmake:
|
||||||
source: "https://gitlab.kitware.com/cmake/cmake.git"
|
source: "https://gitlab.kitware.com/cmake/cmake.git"
|
||||||
@ -182,13 +177,35 @@ parts:
|
|||||||
- libtinfo5
|
- libtinfo5
|
||||||
prime: [-./*]
|
prime: [-./*]
|
||||||
|
|
||||||
|
nasm:
|
||||||
|
source: https://repo.or.cz/nasm.git
|
||||||
|
source-depth: 1
|
||||||
|
source-tag: nasm-2.14.02
|
||||||
|
plugin: autotools
|
||||||
|
override-build: |
|
||||||
|
./autogen.sh
|
||||||
|
./configure --prefix=
|
||||||
|
make
|
||||||
|
install -d "$SNAPCRAFT_PART_INSTALL/bin"
|
||||||
|
install nasm "$SNAPCRAFT_PART_INSTALL/bin/nasm"
|
||||||
|
install ndisasm "$SNAPCRAFT_PART_INSTALL/bin/ndisasm"
|
||||||
|
prime: [-./*]
|
||||||
|
|
||||||
|
dav1d:
|
||||||
|
source: https://github.com/videolan/dav1d.git
|
||||||
|
source-depth: 1
|
||||||
|
source-tag: 0.6.0
|
||||||
|
plugin: meson
|
||||||
|
meson-parameters: [--prefix=/usr]
|
||||||
|
after:
|
||||||
|
- nasm
|
||||||
|
|
||||||
ffmpeg:
|
ffmpeg:
|
||||||
source: https://github.com/FFmpeg/FFmpeg.git
|
source: https://github.com/FFmpeg/FFmpeg.git
|
||||||
source-depth: 1
|
source-depth: 1
|
||||||
source-branch: release/4.2
|
source-branch: release/4.2
|
||||||
plugin: autotools
|
plugin: autotools
|
||||||
build-packages:
|
build-packages:
|
||||||
- yasm
|
|
||||||
- libasound2-dev
|
- libasound2-dev
|
||||||
- libopus-dev
|
- libopus-dev
|
||||||
- libva-dev
|
- libva-dev
|
||||||
@ -210,6 +227,7 @@ parts:
|
|||||||
- --disable-iconv
|
- --disable-iconv
|
||||||
- --enable-gpl
|
- --enable-gpl
|
||||||
- --enable-version3
|
- --enable-version3
|
||||||
|
- --enable-libdav1d
|
||||||
- --enable-libopus
|
- --enable-libopus
|
||||||
- --enable-vaapi
|
- --enable-vaapi
|
||||||
- --enable-vdpau
|
- --enable-vdpau
|
||||||
@ -219,6 +237,7 @@ parts:
|
|||||||
- --enable-decoder=flac
|
- --enable-decoder=flac
|
||||||
- --enable-decoder=gif
|
- --enable-decoder=gif
|
||||||
- --enable-decoder=h264
|
- --enable-decoder=h264
|
||||||
|
- --enable-decoder=libdav1d
|
||||||
- --enable-decoder=mp1
|
- --enable-decoder=mp1
|
||||||
- --enable-decoder=mp1float
|
- --enable-decoder=mp1float
|
||||||
- --enable-decoder=mp2
|
- --enable-decoder=mp2
|
||||||
@ -268,6 +287,8 @@ parts:
|
|||||||
patch -p1 < "$SNAPCRAFT_STAGE/ffmpeg.diff"
|
patch -p1 < "$SNAPCRAFT_STAGE/ffmpeg.diff"
|
||||||
after:
|
after:
|
||||||
- patches
|
- patches
|
||||||
|
- nasm
|
||||||
|
- dav1d
|
||||||
|
|
||||||
openal:
|
openal:
|
||||||
source: https://github.com/kcat/openal-soft.git
|
source: https://github.com/kcat/openal-soft.git
|
||||||
|
Loading…
x
Reference in New Issue
Block a user