Merge remote-tracking branch 'tdesktop/dev' into dev
This commit is contained in:
commit
5b9bc084f9
31 changed files with 668 additions and 1000 deletions
4
.github/workflows/issue_closer.yml
vendored
4
.github/workflows/issue_closer.yml
vendored
|
|
@ -26,7 +26,7 @@ jobs:
|
|||
let body = context.payload.issue.body;
|
||||
|
||||
console.log("Body of issue:\n" + body);
|
||||
let index1 = body.indexOf(item1) + item1.length;
|
||||
let index1 = body.indexOf(item1);
|
||||
let index2 = body.indexOf(item2);
|
||||
index2 = (index2 == -1) ? Number.MAX_SAFE_INTEGER : index2;
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ jobs:
|
|||
return version[0].split(".")[0];
|
||||
}
|
||||
|
||||
let issueVer = parseVersion(body.substring(index1, index2));
|
||||
let issueVer = parseVersion(body.substring(index1 + item1.length, index2));
|
||||
|
||||
if (issueVer == undefined) {
|
||||
console.log(errorStr);
|
||||
|
|
|
|||
99
.github/workflows/snap.yml
vendored
Normal file
99
.github/workflows/snap.yml
vendored
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
name: Snap.
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '*.md'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '*.md'
|
||||
|
||||
jobs:
|
||||
|
||||
linux:
|
||||
name: Ubuntu 18.04
|
||||
runs-on: ubuntu-18.04
|
||||
|
||||
env:
|
||||
UPLOAD_ARTIFACT: "false"
|
||||
ONLY_CACHE: "false"
|
||||
MANUAL_CACHING: "3"
|
||||
|
||||
steps:
|
||||
- name: Clone.
|
||||
uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: First set up.
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install gcc-8 g++-8 -y
|
||||
sudo snap install --classic snapcraft
|
||||
|
||||
# Workaround for snapcraft
|
||||
# See https://forum.snapcraft.io/t/permissions-problem-using-snapcraft-in-azure-pipelines/13258
|
||||
sudo chown root:root /
|
||||
|
||||
snapcraft --version > CACHE_KEY.txt
|
||||
gcc-8 --version >> CACHE_KEY.txt
|
||||
echo $MANUAL_CACHING >> CACHE_KEY.txt
|
||||
md5cache=$(md5sum CACHE_KEY.txt | cut -c -32)
|
||||
echo ::set-env name=CACHE_KEY::$md5cache
|
||||
|
||||
awk -v RS="" -v ORS="\n\n" '/^ cmake:/' snap/snapcraft.yaml > CMAKE_CACHE_KEY.txt
|
||||
md5cache=$(md5sum CMAKE_CACHE_KEY.txt | cut -c -32)
|
||||
echo ::set-env name=CMAKE_CACHE_KEY::$md5cache
|
||||
|
||||
awk -v RS="" -v ORS="\n\n" '/^ enchant:/' snap/snapcraft.yaml > ENCHANT_CACHE_KEY.txt
|
||||
md5cache=$(md5sum ENCHANT_CACHE_KEY.txt | cut -c -32)
|
||||
echo ::set-env name=ENCHANT_CACHE_KEY::$md5cache
|
||||
|
||||
- name: CMake cache.
|
||||
id: cache-cmake
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: parts/cmake
|
||||
key: ${{ runner.OS }}-cmake-${{ env.CACHE_KEY }}-${{ env.CMAKE_CACHE_KEY }}
|
||||
|
||||
- name: CMake build.
|
||||
if: steps.cache-cmake.outputs.cache-hit != 'true'
|
||||
run: snapcraft build --destructive-mode cmake
|
||||
|
||||
- name: Enchant cache.
|
||||
id: cache-enchant
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: parts/enchant
|
||||
key: ${{ runner.OS }}-enchant-${{ env.CACHE_KEY }}-${{ env.ENCHANT_CACHE_KEY }}
|
||||
|
||||
- name: Enchant build.
|
||||
if: steps.cache-enchant.outputs.cache-hit != 'true'
|
||||
run: snapcraft build --destructive-mode enchant
|
||||
|
||||
- name: Telegram Desktop snap build.
|
||||
if: env.ONLY_CACHE == 'false'
|
||||
run: snapcraft --destructive-mode
|
||||
|
||||
- name: Move artifact.
|
||||
if: env.UPLOAD_ARTIFACT == 'true'
|
||||
run: |
|
||||
artifact_name=$(echo telegram-desktop_*.snap)
|
||||
echo ::set-env name=ARTIFACT_NAME::$artifact_name
|
||||
|
||||
mkdir artifact
|
||||
mv $artifact_name artifact
|
||||
|
||||
- uses: actions/upload-artifact@master
|
||||
if: env.UPLOAD_ARTIFACT == 'true'
|
||||
name: Upload artifact.
|
||||
with:
|
||||
name: ${{ env.ARTIFACT_NAME }}
|
||||
path: artifact
|
||||
|
||||
- name: Remove unneeded directories for cache.
|
||||
run: |
|
||||
rm -rf parts/{cmake,enchant}/{build,src,ubuntu}
|
||||
rm -rf parts/{cmake,enchant}/state/{stage,prime}
|
||||
|
|
@ -20,6 +20,7 @@ add_subdirectory(lib_lottie)
|
|||
add_subdirectory(lib_qr)
|
||||
add_subdirectory(codegen)
|
||||
|
||||
include(CheckCXXSourceCompiles)
|
||||
include(lib_ui/cmake/generate_styles.cmake)
|
||||
include(cmake/generate_lang.cmake)
|
||||
include(cmake/generate_numbers.cmake)
|
||||
|
|
@ -105,6 +106,16 @@ if (NOT DESKTOP_APP_USE_PACKAGED)
|
|||
target_link_libraries(Telegram PRIVATE desktop-app::external_opus)
|
||||
endif()
|
||||
|
||||
# Telegram uses long atomic types, so on some architectures libatomic is needed.
|
||||
check_cxx_source_compiles("
|
||||
#include <atomic>
|
||||
std::atomic_int64_t foo;
|
||||
int main() {return foo;}
|
||||
" HAVE_LONG_ATOMIC_WITHOUT_LIB)
|
||||
if (NOT HAVE_LONG_ATOMIC_WITHOUT_LIB)
|
||||
target_link_libraries(Telegram PRIVATE atomic)
|
||||
endif()
|
||||
|
||||
target_precompile_headers(Telegram PRIVATE ${src_loc}/stdafx.h)
|
||||
nice_target_sources(Telegram ${src_loc}
|
||||
PRIVATE
|
||||
|
|
|
|||
|
|
@ -1268,6 +1268,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_cant_invite_make_admin" = "Make admin";
|
||||
|
||||
"lng_send_button" = "Send";
|
||||
"lng_schedule_button" = "Schedule";
|
||||
"lng_send_silent_message" = "Send without sound";
|
||||
"lng_schedule_message" = "Schedule message";
|
||||
"lng_reminder_message" = "Set a reminder";
|
||||
|
|
@ -2199,11 +2200,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_polls_create_limit#other" = "You can add {count} more options.";
|
||||
"lng_polls_create_maximum" = "You have added the maximum number of options.";
|
||||
"lng_polls_create_settings" = "Settings";
|
||||
"lng_polls_create_hint" = "Tap to select the right option";
|
||||
"lng_polls_create_anonymous" = "Anonymous Votes";
|
||||
"lng_polls_create_multiple_choice" = "Multiple Answers";
|
||||
"lng_polls_create_quiz_mode" = "Quiz Mode";
|
||||
"lng_polls_create_button" = "Create";
|
||||
"lng_polls_create_one_answer" = "Quiz has only one right answer.";
|
||||
"lng_polls_choose_question" = "Please enter a question.";
|
||||
"lng_polls_choose_answers" = "Please enter at least two options.";
|
||||
"lng_polls_choose_correct" = "Please choose the correct answer.";
|
||||
|
|
|
|||
|
|
@ -60,5 +60,6 @@
|
|||
</qresource>
|
||||
<qresource prefix="/ktg_lang">
|
||||
<file alias="ru.json">../../langs/rewrites/ru.json</file>
|
||||
<file alias="kotatogramdesktop.desktop">../../../../lib/xdg/kotatogramdesktop.desktop</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
|
||||
ProcessorArchitecture="ARCHITECTURE"
|
||||
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
|
||||
Version="1.9.8.0" />
|
||||
Version="1.9.9.0" />
|
||||
<Properties>
|
||||
<DisplayName>Telegram Desktop</DisplayName>
|
||||
<PublisherDisplayName>Telegram FZ-LLC</PublisherDisplayName>
|
||||
|
|
|
|||
|
|
@ -579,6 +579,13 @@ void ApiWrap::sendMessageFail(
|
|||
requestFullPeer(peer);
|
||||
}
|
||||
}
|
||||
} else if (error.type() == qstr("SCHEDULE_STATUS_PRIVATE")) {
|
||||
auto &scheduled = _session->data().scheduledMessages();
|
||||
Assert(peer->isUser());
|
||||
if (const auto item = scheduled.lookupItem(peer->id, itemId.msg)) {
|
||||
scheduled.removeSending(item);
|
||||
Ui::show(Box<InformBox>(tr::lng_cant_do_this(tr::now)));
|
||||
}
|
||||
}
|
||||
if (const auto item = _session->data().message(itemId)) {
|
||||
Assert(randomId != 0);
|
||||
|
|
@ -3652,10 +3659,22 @@ void ApiWrap::applyUpdateNoPtsCheck(const MTPUpdate &update) {
|
|||
auto &d = update.c_updateNewMessage();
|
||||
auto needToAdd = true;
|
||||
if (d.vmessage().type() == mtpc_message) { // index forwarded messages to links _overview
|
||||
if (_session->data().checkEntitiesAndViewsUpdate(d.vmessage().c_message())) { // already in blocks
|
||||
const auto &data = d.vmessage().c_message();
|
||||
if (_session->data().checkEntitiesAndViewsUpdate(data)) { // already in blocks
|
||||
LOG(("Skipping message, because it is already in blocks!"));
|
||||
needToAdd = false;
|
||||
}
|
||||
if (needToAdd && !data.is_from_scheduled()) {
|
||||
// If we still need to add a new message,
|
||||
// we should first check if this message is in
|
||||
// the list of scheduled messages.
|
||||
// This is necessary to correctly update the file reference.
|
||||
// Note that when a message is scheduled until online
|
||||
// while the recipient is already online, the server sends
|
||||
// an ordinary new message with skipped "from_scheduled" flag.
|
||||
_session->data().scheduledMessages().checkEntitiesAndUpdate(
|
||||
data);
|
||||
}
|
||||
}
|
||||
if (needToAdd) {
|
||||
_session->data().addNewMessage(
|
||||
|
|
|
|||
|
|
@ -873,7 +873,7 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
|||
) | rpl::filter([=](not_null<QEvent*> e) {
|
||||
return (e->type() == QEvent::MouseButtonPress) && quiz->checked();
|
||||
}) | rpl::start_with_next([=] {
|
||||
Ui::Toast::Show("Quiz has only one right answer.");
|
||||
Ui::Toast::Show(tr::lng_polls_create_one_answer(tr::now));
|
||||
}, multiple->lifetime());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1832,7 +1832,11 @@ void SendFilesBox::setupShadows(
|
|||
}
|
||||
|
||||
void SendFilesBox::prepare() {
|
||||
_send = addButton(tr::lng_send_button(), [=] { send({}); });
|
||||
_send = addButton(
|
||||
(_sendType == Api::SendType::Normal
|
||||
? tr::lng_send_button()
|
||||
: tr::lng_schedule_button()),
|
||||
[=] { send({}); });
|
||||
if (_sendType == Api::SendType::Normal) {
|
||||
SetupSendMenuAndShortcuts(
|
||||
_send,
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#define TDESKTOP_ALPHA_VERSION (0ULL)
|
||||
#endif // TDESKTOP_ALLOW_CLOSED_ALPHA
|
||||
|
||||
constexpr auto AppVersion = 1009008;
|
||||
constexpr auto AppVersionStr = "1.9.8";
|
||||
constexpr auto AppVersion = 1009009;
|
||||
constexpr auto AppVersionStr = "1.9.9";
|
||||
constexpr auto AppBetaVersion = false;
|
||||
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
||||
constexpr auto AppKotatoVersion = 1001005;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "main/main_session.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_item_components.h"
|
||||
#include "history/history_message.h"
|
||||
#include "apiwrap.h"
|
||||
|
||||
namespace Data {
|
||||
|
|
@ -111,11 +112,82 @@ MsgId ScheduledMessages::lookupId(not_null<HistoryItem*> item) const {
|
|||
return j->second;
|
||||
}
|
||||
|
||||
HistoryItem *ScheduledMessages::lookupItem(PeerId peer, MsgId msg) const {
|
||||
const auto history = _session->data().historyLoaded(peer);
|
||||
if (!history) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto i = _data.find(history);
|
||||
if (i == end(_data)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto &items = i->second.items;
|
||||
const auto j = ranges::find_if(items, [&](auto &item) {
|
||||
return item->id == msg;
|
||||
});
|
||||
if (j == end(items)) {
|
||||
return nullptr;
|
||||
}
|
||||
return (*j).get();
|
||||
}
|
||||
|
||||
int ScheduledMessages::count(not_null<History*> history) const {
|
||||
const auto i = _data.find(history);
|
||||
return (i != end(_data)) ? i->second.items.size() : 0;
|
||||
}
|
||||
|
||||
void ScheduledMessages::sendNowSimpleMessage(
|
||||
const MTPDupdateShortSentMessage &update,
|
||||
not_null<HistoryItem*> local) {
|
||||
Expects(local->isSending());
|
||||
Expects(local->isScheduled());
|
||||
Expects(local->date() == kScheduledUntilOnlineTimestamp);
|
||||
|
||||
// When the user sends a text message scheduled until online
|
||||
// while the recipient is already online, the server sends
|
||||
// updateShortSentMessage to the client and the client calls this method.
|
||||
// Since such messages can only be sent to recipients,
|
||||
// we know for sure that a message can't have fields such as the author,
|
||||
// views count, etc.
|
||||
|
||||
const auto &history = local->history();
|
||||
auto flags = NewMessageFlags(history->peer)
|
||||
| MTPDmessage::Flag::f_entities
|
||||
| MTPDmessage::Flag::f_from_id
|
||||
| (local->replyToId()
|
||||
? MTPDmessage::Flag::f_reply_to_msg_id
|
||||
: MTPDmessage::Flag(0));
|
||||
auto clientFlags = NewMessageClientFlags()
|
||||
| MTPDmessage_ClientFlag::f_local_history_entry;
|
||||
|
||||
history->addNewMessage(
|
||||
MTP_message(
|
||||
MTP_flags(flags),
|
||||
update.vid(),
|
||||
MTP_int(_session->userId()),
|
||||
peerToMTP(history->peer->id),
|
||||
MTPMessageFwdHeader(),
|
||||
MTPint(),
|
||||
MTP_int(local->replyToId()),
|
||||
update.vdate(),
|
||||
MTP_string(local->originalText().text),
|
||||
MTP_messageMediaEmpty(),
|
||||
MTPReplyMarkup(),
|
||||
Api::EntitiesToMTP(local->originalText().entities),
|
||||
MTP_int(1),
|
||||
MTPint(),
|
||||
MTP_string(),
|
||||
MTPlong(),
|
||||
//MTPMessageReactions(),
|
||||
MTPVector<MTPRestrictionReason>()),
|
||||
clientFlags,
|
||||
NewMessageType::Unread);
|
||||
|
||||
local->destroy();
|
||||
}
|
||||
|
||||
void ScheduledMessages::apply(const MTPDupdateNewScheduledMessage &update) {
|
||||
const auto &message = update.vmessage();
|
||||
const auto peer = PeerFromMessage(message);
|
||||
|
|
@ -132,6 +204,45 @@ void ScheduledMessages::apply(const MTPDupdateNewScheduledMessage &update) {
|
|||
_updates.fire_copy(history);
|
||||
}
|
||||
|
||||
void ScheduledMessages::checkEntitiesAndUpdate(const MTPDmessage &data) {
|
||||
// When the user sends a message with a media scheduled until online
|
||||
// while the recipient is already online, the server sends
|
||||
// updateNewMessage to the client and the client calls this method.
|
||||
|
||||
const auto peer = peerFromMTP(data.vto_id());
|
||||
if (!peerIsUser(peer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto history = _session->data().historyLoaded(peer);
|
||||
if (!history) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto i = _data.find(history);
|
||||
if (i == end(_data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &itemMap = i->second.itemById;
|
||||
const auto j = itemMap.find(data.vid().v);
|
||||
if (j == end(itemMap)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto existing = j->second;
|
||||
Assert(existing->date() == kScheduledUntilOnlineTimestamp);
|
||||
existing->updateSentContent({
|
||||
qs(data.vmessage()),
|
||||
Api::EntitiesFromMTP(data.ventities().value_or_empty())
|
||||
}, data.vmedia());
|
||||
existing->updateReplyMarkup(data.vreply_markup());
|
||||
existing->updateForwardedInfo(data.vfwd_from());
|
||||
_session->data().requestItemTextRefresh(existing);
|
||||
|
||||
existing->destroy();
|
||||
}
|
||||
|
||||
void ScheduledMessages::apply(
|
||||
const MTPDupdateDeleteScheduledMessages &update) {
|
||||
const auto peer = peerFromMTP(update.vpeer());
|
||||
|
|
|
|||
|
|
@ -29,8 +29,10 @@ public:
|
|||
~ScheduledMessages();
|
||||
|
||||
[[nodiscard]] MsgId lookupId(not_null<HistoryItem*> item) const;
|
||||
[[nodiscard]] HistoryItem *lookupItem(PeerId peer, MsgId msg) const;
|
||||
[[nodiscard]] int count(not_null<History*> history) const;
|
||||
|
||||
void checkEntitiesAndUpdate(const MTPDmessage &data);
|
||||
void apply(const MTPDupdateNewScheduledMessage &update);
|
||||
void apply(const MTPDupdateDeleteScheduledMessages &update);
|
||||
void apply(
|
||||
|
|
@ -40,6 +42,10 @@ public:
|
|||
void appendSending(not_null<HistoryItem*> item);
|
||||
void removeSending(not_null<HistoryItem*> item);
|
||||
|
||||
void sendNowSimpleMessage(
|
||||
const MTPDupdateShortSentMessage &update,
|
||||
not_null<HistoryItem*> local);
|
||||
|
||||
[[nodiscard]] rpl::producer<> updates(not_null<History*> history);
|
||||
[[nodiscard]] Data::MessagesSlice list(not_null<History*> history);
|
||||
|
||||
|
|
|
|||
|
|
@ -675,16 +675,17 @@ HistoryWidget::HistoryWidget(
|
|||
) | rpl::filter([=](const Api::SendAction &action) {
|
||||
return (action.history == _history);
|
||||
}) | rpl::start_with_next([=](const Api::SendAction &action) {
|
||||
const auto lastKeyboardUsed = lastForceReplyReplied(FullMsgId(
|
||||
action.history->channelId(),
|
||||
action.replyTo));
|
||||
if (action.options.scheduled) {
|
||||
cancelReply(lastKeyboardUsed);
|
||||
crl::on_main(this, [=, history = action.history]{
|
||||
controller->showSection(
|
||||
HistoryView::ScheduledMemento(history));
|
||||
});
|
||||
} else {
|
||||
fastShowAtEnd(action.history);
|
||||
const auto lastKeyboardUsed = lastForceReplyReplied(FullMsgId(
|
||||
action.history->channelId(),
|
||||
action.replyTo));
|
||||
if (cancelReply(lastKeyboardUsed) && !action.clearDraft) {
|
||||
onCloudDraftSave();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -688,7 +688,7 @@ void ScheduleBox(
|
|||
}, timeInput->lifetime());
|
||||
|
||||
box->setFocusCallback([=] { timeInput->setFocusFast(); });
|
||||
const auto submit = box->addButton(tr::lng_settings_save(), [=] {
|
||||
const auto submit = box->addButton(tr::lng_schedule_button(), [=] {
|
||||
save(false);
|
||||
});
|
||||
SetupSendMenuAndShortcuts(
|
||||
|
|
|
|||
|
|
@ -3807,14 +3807,19 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) {
|
|||
if (!IsServerMsgId(d.vid().v)) {
|
||||
LOG(("API Error: Bad msgId got from server: %1").arg(d.vid().v));
|
||||
} else if (randomId) {
|
||||
const auto sent = session().data().messageSentData(randomId);
|
||||
auto &owner = session().data();
|
||||
const auto sent = owner.messageSentData(randomId);
|
||||
const auto lookupMessage = [&] {
|
||||
return sent.peerId
|
||||
? session().data().message(
|
||||
peerToChannel(sent.peerId),
|
||||
d.vid().v)
|
||||
? owner.message(peerToChannel(sent.peerId), d.vid().v)
|
||||
: nullptr;
|
||||
};
|
||||
if (const auto id = owner.messageIdByRandomId(randomId)) {
|
||||
if (const auto local = owner.message(id);
|
||||
local->isScheduled()) {
|
||||
owner.scheduledMessages().sendNowSimpleMessage(d, local);
|
||||
}
|
||||
}
|
||||
const auto wasAlready = (lookupMessage() != nullptr);
|
||||
feedUpdate(MTP_updateMessageID(d.vid(), MTP_long(randomId))); // ignore real date
|
||||
if (const auto item = lookupMessage()) {
|
||||
|
|
|
|||
|
|
@ -234,7 +234,9 @@ void Panel::refreshList() {
|
|||
: nullptr;
|
||||
const auto media = item ? item->media() : nullptr;
|
||||
const auto document = media ? media->document() : nullptr;
|
||||
if (!document || !document->isSharedMediaMusic()) {
|
||||
if (!document
|
||||
|| !document->isSharedMediaMusic()
|
||||
|| !IsServerMsgId(item->id)) {
|
||||
return nullptr;
|
||||
}
|
||||
const auto result = item->history()->peer;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
namespace Platform {
|
||||
namespace {
|
||||
|
||||
constexpr auto kLauncherBasename = str_const(MACRO_TO_STRING(TDESKTOP_LAUNCHER_BASENAME) ".desktop");
|
||||
|
||||
bool noQtTrayIcon = false, tryAppIndicator = false;
|
||||
bool useGtkBase = false, useAppIndicator = false, useStatusIcon = false, trayIconChecked = false, useUnityCount = false;
|
||||
|
||||
|
|
@ -547,7 +549,7 @@ void MainWindow::psFirstShow() {
|
|||
auto snapName = QString::fromLatin1(qgetenv("SNAP_NAME"));
|
||||
if(snapName.isEmpty()) {
|
||||
std::vector<QString> possibleDesktopFiles = {
|
||||
MACRO_TO_STRING(TDESKTOP_LAUNCHER_BASENAME) ".desktop",
|
||||
str_const_toString(kLauncherBasename),
|
||||
"Kotatogram.desktop"
|
||||
};
|
||||
|
||||
|
|
@ -563,8 +565,12 @@ void MainWindow::psFirstShow() {
|
|||
LOG(("Could not get Unity Launcher entry!"));
|
||||
}
|
||||
} else {
|
||||
LOG(("SNAP Environment detected, setting Launcher entry to %1-kotatogramdesktop.desktop!").arg(snapName));
|
||||
_desktopFile = snapName + "_kotatogramdesktop.desktop";
|
||||
LOG(("SNAP Environment detected, setting Launcher entry to %1_%2.desktop!")
|
||||
.arg(snapName)
|
||||
.arg(str_const_toString(kLauncherBasename)));
|
||||
_desktopFile = snapName
|
||||
+ '_'
|
||||
+ str_const_toString(kLauncherBasename);
|
||||
useUnityCount=true;
|
||||
}
|
||||
_dbusPath = "/com/canonical/unity/launcherentry/" + QString::number(djbStringHash("application://" + _desktopFile));
|
||||
|
|
@ -573,25 +579,24 @@ void MainWindow::psFirstShow() {
|
|||
}
|
||||
#endif
|
||||
|
||||
bool showShadows = true;
|
||||
|
||||
show();
|
||||
//_private.enableShadow(winId());
|
||||
if (cWindowPos().maximized) {
|
||||
DEBUG_LOG(("Window Pos: First show, setting maximized."));
|
||||
setWindowState(Qt::WindowMaximized);
|
||||
}
|
||||
|
||||
if ((cLaunchMode() == LaunchModeAutoStart && cStartMinimized()) || cStartInTray()) {
|
||||
setWindowState(Qt::WindowMinimized);
|
||||
if (Global::WorkMode().value() == dbiwmTrayOnly || Global::WorkMode().value() == dbiwmWindowAndTray) {
|
||||
hide();
|
||||
} else {
|
||||
show();
|
||||
}
|
||||
showShadows = false;
|
||||
} else {
|
||||
show();
|
||||
// If I call hide() synchronously here after show() then on Ubuntu 14.04
|
||||
// it will show a window frame with transparent window body, without content.
|
||||
// And to be able to "Show from tray" one more hide() will be required.
|
||||
crl::on_main(this, [=] {
|
||||
setWindowState(Qt::WindowMinimized);
|
||||
if (Global::WorkMode().value() == dbiwmTrayOnly || Global::WorkMode().value() == dbiwmWindowAndTray) {
|
||||
hide();
|
||||
} else {
|
||||
show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setPositionInited();
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
#include <QtCore/QVersionNumber>
|
||||
#include <QtDBus/QDBusConnection>
|
||||
#include <QtDBus/QDBusReply>
|
||||
#include <QtDBus/QDBusMetaType>
|
||||
#endif
|
||||
|
|
@ -31,7 +30,7 @@ constexpr auto kInterface = kService;
|
|||
std::vector<QString> GetServerInformation(
|
||||
const std::shared_ptr<QDBusInterface> ¬ificationInterface) {
|
||||
std::vector<QString> serverInformation;
|
||||
auto serverInformationReply = notificationInterface
|
||||
const auto serverInformationReply = notificationInterface
|
||||
->call(qsl("GetServerInformation"));
|
||||
|
||||
if (serverInformationReply.type() == QDBusMessage::ReplyMessage) {
|
||||
|
|
@ -58,7 +57,7 @@ std::vector<QString> GetServerInformation(
|
|||
|
||||
QStringList GetCapabilities(
|
||||
const std::shared_ptr<QDBusInterface> ¬ificationInterface) {
|
||||
QDBusReply<QStringList> capabilitiesReply = notificationInterface
|
||||
const QDBusReply<QStringList> capabilitiesReply = notificationInterface
|
||||
->call(qsl("GetCapabilities"));
|
||||
|
||||
if (capabilitiesReply.isValid()) {
|
||||
|
|
@ -95,7 +94,7 @@ NotificationData::NotificationData(
|
|||
, _title(title)
|
||||
, _peerId(peerId)
|
||||
, _msgId(msgId) {
|
||||
auto capabilities = GetCapabilities(_notificationInterface);
|
||||
const auto capabilities = GetCapabilities(_notificationInterface);
|
||||
|
||||
if (capabilities.contains(qsl("body-markup"))) {
|
||||
_body = subtitle.isEmpty()
|
||||
|
|
@ -112,17 +111,25 @@ NotificationData::NotificationData(
|
|||
if (capabilities.contains(qsl("actions"))) {
|
||||
_actions << qsl("default") << QString();
|
||||
|
||||
connect(_notificationInterface.get(),
|
||||
SIGNAL(ActionInvoked(uint, QString)),
|
||||
this, SLOT(notificationClicked(uint)));
|
||||
_notificationInterface->connection().connect(
|
||||
str_const_toString(kService),
|
||||
str_const_toString(kObjectPath),
|
||||
str_const_toString(kInterface),
|
||||
qsl("ActionInvoked"),
|
||||
this,
|
||||
SLOT(notificationClicked(uint)));
|
||||
|
||||
if (capabilities.contains(qsl("inline-reply"))) {
|
||||
_actions << qsl("inline-reply")
|
||||
<< tr::lng_notification_reply(tr::now);
|
||||
|
||||
connect(_notificationInterface.get(),
|
||||
SIGNAL(NotificationReplied(uint,QString)),
|
||||
this, SLOT(notificationReplied(uint,QString)));
|
||||
_notificationInterface->connection().connect(
|
||||
str_const_toString(kService),
|
||||
str_const_toString(kObjectPath),
|
||||
str_const_toString(kInterface),
|
||||
qsl("NotificationReplied"),
|
||||
this,
|
||||
SLOT(notificationReplied(uint,QString)));
|
||||
} else {
|
||||
// icon name according to https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html
|
||||
_actions << qsl("mail-reply-sender")
|
||||
|
|
@ -153,15 +160,26 @@ NotificationData::NotificationData(
|
|||
_hints["desktop-entry"] =
|
||||
qsl(MACRO_TO_STRING(TDESKTOP_LAUNCHER_BASENAME));
|
||||
|
||||
connect(_notificationInterface.get(),
|
||||
SIGNAL(NotificationClosed(uint, uint)),
|
||||
this, SLOT(notificationClosed(uint)));
|
||||
_notificationInterface->connection().connect(
|
||||
str_const_toString(kService),
|
||||
str_const_toString(kObjectPath),
|
||||
str_const_toString(kInterface),
|
||||
qsl("NotificationClosed"),
|
||||
this,
|
||||
SLOT(notificationClosed(uint)));
|
||||
}
|
||||
|
||||
bool NotificationData::show() {
|
||||
QDBusReply<uint> notifyReply = _notificationInterface->call(qsl("Notify"),
|
||||
str_const_toString(AppName), uint(0), QString(), _title, _body,
|
||||
_actions, _hints, -1);
|
||||
const QDBusReply<uint> notifyReply = _notificationInterface->call(
|
||||
qsl("Notify"),
|
||||
str_const_toString(AppName),
|
||||
uint(0),
|
||||
QString(),
|
||||
_title,
|
||||
_body,
|
||||
_actions,
|
||||
_hints,
|
||||
-1);
|
||||
|
||||
if (notifyReply.isValid()) {
|
||||
_notificationId = notifyReply.value();
|
||||
|
|
@ -174,7 +192,7 @@ bool NotificationData::show() {
|
|||
}
|
||||
|
||||
bool NotificationData::close() {
|
||||
QDBusReply<void> closeReply = _notificationInterface
|
||||
const QDBusReply<void> closeReply = _notificationInterface
|
||||
->call(qsl("CloseNotification"), _notificationId);
|
||||
|
||||
if (!closeReply.isValid()) {
|
||||
|
|
@ -186,7 +204,7 @@ bool NotificationData::close() {
|
|||
}
|
||||
|
||||
void NotificationData::setImage(const QString &imagePath) {
|
||||
auto specificationVersion = ParseSpecificationVersion(
|
||||
const auto specificationVersion = ParseSpecificationVersion(
|
||||
GetServerInformation(_notificationInterface));
|
||||
|
||||
QString imageKey;
|
||||
|
|
@ -211,9 +229,16 @@ void NotificationData::setImage(const QString &imagePath) {
|
|||
return;
|
||||
}
|
||||
|
||||
auto image = QImage(imagePath).convertToFormat(QImage::Format_RGBA8888);
|
||||
QByteArray imageBytes((const char*)image.constBits(),
|
||||
const auto image = QImage(imagePath)
|
||||
.convertToFormat(QImage::Format_RGBA8888);
|
||||
|
||||
const QByteArray imageBytes(
|
||||
(const char*)image.constBits(),
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
|
||||
image.byteCount());
|
||||
#else
|
||||
image.sizeInBytes());
|
||||
#endif
|
||||
|
||||
ImageData imageData;
|
||||
imageData.width = image.width();
|
||||
|
|
@ -285,7 +310,7 @@ const QDBusArgument &operator>>(const QDBusArgument &argument,
|
|||
|
||||
bool Supported() {
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
static auto Available = QDBusInterface(
|
||||
static const auto Available = QDBusInterface(
|
||||
str_const_toString(kService),
|
||||
str_const_toString(kObjectPath),
|
||||
str_const_toString(kInterface)).isValid();
|
||||
|
|
@ -316,10 +341,10 @@ Manager::Private::Private(Manager *manager, Type type)
|
|||
str_const_toString(kInterface))) {
|
||||
qDBusRegisterMetaType<NotificationData::ImageData>();
|
||||
|
||||
auto specificationVersion = ParseSpecificationVersion(
|
||||
const auto specificationVersion = ParseSpecificationVersion(
|
||||
GetServerInformation(_notificationInterface));
|
||||
|
||||
auto capabilities = GetCapabilities(_notificationInterface);
|
||||
const auto capabilities = GetCapabilities(_notificationInterface);
|
||||
|
||||
if (!specificationVersion.isNull()) {
|
||||
LOG(("Notification daemon specification version: %1")
|
||||
|
|
|
|||
|
|
@ -24,6 +24,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include <QtCore/QProcess>
|
||||
#include <QtCore/QVersionNumber>
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
#include <QtDBus/QDBusInterface>
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <cstdlib>
|
||||
|
|
@ -38,6 +42,27 @@ using Platform::File::internal::EscapeShell;
|
|||
|
||||
namespace {
|
||||
|
||||
constexpr auto kDesktopFile = str_const(":/misc/kotatogramdesktop.desktop");
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
void SandboxAutostart(bool autostart) {
|
||||
QVariantMap options;
|
||||
options["reason"] = tr::lng_settings_auto_start(tr::now);
|
||||
options["autostart"] = autostart;
|
||||
options["commandline"] = QStringList({
|
||||
cExeName(),
|
||||
qsl("-autostart")
|
||||
});
|
||||
options["dbus-activatable"] = false;
|
||||
|
||||
QDBusInterface(
|
||||
qsl("org.freedesktop.portal.Desktop"),
|
||||
qsl("/org/freedesktop/portal/desktop"),
|
||||
qsl("/org/freedesktop/portal/desktop")
|
||||
).call(qsl("RequestBackground"), QString(), options);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool RunShellCommand(const QByteArray &command) {
|
||||
auto result = system(command.constData());
|
||||
if (result) {
|
||||
|
|
@ -87,6 +112,61 @@ void FallbackFontConfig() {
|
|||
#endif // !DESKTOP_APP_USE_PACKAGED
|
||||
}
|
||||
|
||||
bool GenerateDesktopFile(const QString &targetPath, const QString &args) {
|
||||
DEBUG_LOG(("App Info: placing .desktop file to %1").arg(targetPath));
|
||||
if (!QDir(targetPath).exists()) QDir().mkpath(targetPath);
|
||||
|
||||
const auto targetFile = targetPath
|
||||
+ qsl(MACRO_TO_STRING(TDESKTOP_LAUNCHER_BASENAME) ".desktop");
|
||||
|
||||
QString fileText;
|
||||
|
||||
QFile source(str_const_toString(kDesktopFile));
|
||||
if (source.open(QIODevice::ReadOnly)) {
|
||||
QTextStream s(&source);
|
||||
fileText = s.readAll();
|
||||
source.close();
|
||||
} else {
|
||||
LOG(("App Error: Could not open '%1' for read")
|
||||
.arg(str_const_toString(kDesktopFile)));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QFile target(targetFile);
|
||||
if (target.open(QIODevice::WriteOnly)) {
|
||||
#ifdef DESKTOP_APP_USE_PACKAGED
|
||||
fileText = fileText.replace(
|
||||
QRegularExpression(qsl("^Exec=(.*) -- %u$"),
|
||||
QRegularExpression::MultilineOption),
|
||||
qsl("Exec=\\1")
|
||||
+ (args.isEmpty() ? QString() : ' ' + args));
|
||||
#else
|
||||
fileText = fileText.replace(
|
||||
QRegularExpression(qsl("^TryExec=.*$"),
|
||||
QRegularExpression::MultilineOption),
|
||||
qsl("TryExec=")
|
||||
+ EscapeShell(QFile::encodeName(cExeDir() + cExeName())));
|
||||
fileText = fileText.replace(
|
||||
QRegularExpression(qsl("^Exec=.*$"),
|
||||
QRegularExpression::MultilineOption),
|
||||
qsl("Exec=")
|
||||
+ EscapeShell(QFile::encodeName(cExeDir() + cExeName()))
|
||||
+ (args.isEmpty() ? QString() : ' ' + args));
|
||||
#endif
|
||||
target.write(fileText.toUtf8());
|
||||
target.close();
|
||||
|
||||
DEBUG_LOG(("App Info: removing old .desktop file"));
|
||||
QFile(qsl("%1kotatogram.desktop").arg(targetPath)).remove();
|
||||
|
||||
return true;
|
||||
} else {
|
||||
LOG(("App Error: Could not open '%1' for write").arg(targetFile));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace Platform {
|
||||
|
|
@ -98,7 +178,7 @@ void SetApplicationIcon(const QIcon &icon) {
|
|||
bool InSandbox() {
|
||||
static const auto Sandbox = QFileInfo::exists(
|
||||
QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation)
|
||||
+ qsl("/flatpak-info"));
|
||||
+ qsl("/flatpak-info"));
|
||||
return Sandbox;
|
||||
}
|
||||
|
||||
|
|
@ -120,6 +200,8 @@ QString CurrentExecutablePath(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
QString SingleInstanceLocalServerName(const QString &hash) {
|
||||
const auto isSnap = !qgetenv("SNAP").isEmpty();
|
||||
|
||||
const auto runtimeDir = QStandardPaths::writableLocation(
|
||||
QStandardPaths::RuntimeLocation);
|
||||
|
||||
|
|
@ -128,6 +210,8 @@ QString SingleInstanceLocalServerName(const QString &hash) {
|
|||
+ qsl("/app/")
|
||||
+ QString::fromUtf8(qgetenv("FLATPAK_ID"))
|
||||
+ '/' + hash;
|
||||
} else if (QFileInfo::exists(runtimeDir) && isSnap) {
|
||||
return runtimeDir + '/' + hash;
|
||||
} else if (QFileInfo::exists(runtimeDir)) {
|
||||
return runtimeDir + '/' + hash + '-' + cGUIDStr();
|
||||
} else { // non-systemd distros
|
||||
|
|
@ -258,104 +342,45 @@ void finish() {
|
|||
void RegisterCustomScheme() {
|
||||
#ifndef TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME
|
||||
auto home = getHomeDir();
|
||||
if (home.isEmpty() || cAlphaVersion() || cExeName().isEmpty()) return; // don't update desktop file for alpha version
|
||||
if (home.isEmpty() || cAlphaVersion() || cExeName().isEmpty())
|
||||
return; // don't update desktop file for alpha version
|
||||
if (Core::UpdaterDisabled())
|
||||
return;
|
||||
|
||||
const auto applicationsPath = QStandardPaths::writableLocation(
|
||||
QStandardPaths::ApplicationsLocation) + '/';
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION
|
||||
DEBUG_LOG(("App Info: placing .desktop file"));
|
||||
if (QDir(home + qsl(".local/")).exists()) {
|
||||
QString apps = home + qsl(".local/share/applications/");
|
||||
QString icons = home + qsl(".local/share/icons/");
|
||||
if (!QDir(apps).exists()) QDir().mkpath(apps);
|
||||
if (!QDir(icons).exists()) QDir().mkpath(icons);
|
||||
GenerateDesktopFile(applicationsPath, qsl("-- %u"));
|
||||
|
||||
QString path = cWorkingDir() + qsl("tdata/"), file = path + qsl("kotatogramdesktop.desktop");
|
||||
QDir().mkpath(path);
|
||||
QFile f(file);
|
||||
if (f.open(QIODevice::WriteOnly)) {
|
||||
QString icon = icons + qsl("kotatogram.png");
|
||||
auto iconExists = QFile(icon).exists();
|
||||
if (Local::oldSettingsVersion() < 10021 && iconExists) {
|
||||
// Icon was changed.
|
||||
if (QFile(icon).remove()) {
|
||||
iconExists = false;
|
||||
}
|
||||
}
|
||||
if (!iconExists) {
|
||||
if (QFile(qsl(":/gui/art/logo_256.png")).copy(icon)) {
|
||||
DEBUG_LOG(("App Info: Icon copied to 'tdata'"));
|
||||
}
|
||||
}
|
||||
const auto icons =
|
||||
QStandardPaths::writableLocation(
|
||||
QStandardPaths::GenericDataLocation)
|
||||
+ qsl("/icons/");
|
||||
|
||||
QTextStream s(&f);
|
||||
s.setCodec("UTF-8");
|
||||
s << "[Desktop Entry]\n";
|
||||
s << "Version=1.0\n";
|
||||
s << "Name=Kotatogram Desktop\n";
|
||||
s << "Comment=Experimental Telegram Desktop fork\n";
|
||||
s << "TryExec=" << EscapeShell(QFile::encodeName(cExeDir() + cExeName())) << "\n";
|
||||
s << "Exec=" << EscapeShell(QFile::encodeName(cExeDir() + cExeName())) << " -- %u\n";
|
||||
s << "Icon=kotatogram\n";
|
||||
s << "Terminal=false\n";
|
||||
s << "StartupWMClass=KotatogramDesktop\n";
|
||||
s << "Type=Application\n";
|
||||
s << "Categories=Network;InstantMessaging;Qt;\n";
|
||||
s << "MimeType=x-scheme-handler/tg;\n";
|
||||
s << "Keywords=tg;chat;im;messaging;messenger;sms;tdesktop;\n";
|
||||
s << "X-GNOME-UsesNotifications=true\n";
|
||||
f.close();
|
||||
if (!QDir(icons).exists()) QDir().mkpath(icons);
|
||||
|
||||
if (RunShellCommand("desktop-file-install --dir=" + EscapeShell(QFile::encodeName(home + qsl(".local/share/applications"))) + " --delete-original " + EscapeShell(QFile::encodeName(file)))) {
|
||||
DEBUG_LOG(("App Info: removing old .desktop file"));
|
||||
QFile(qsl("%1.local/share/applications/kotatogram.desktop").arg(home)).remove();
|
||||
|
||||
RunShellCommand("update-desktop-database " + EscapeShell(QFile::encodeName(home + qsl(".local/share/applications"))));
|
||||
RunShellCommand("xdg-mime default kotatogramdesktop.desktop x-scheme-handler/tg");
|
||||
}
|
||||
} else {
|
||||
LOG(("App Error: Could not open '%1' for write").arg(file));
|
||||
const auto icon = icons + qsl("kotatogram.png");
|
||||
auto iconExists = QFile(icon).exists();
|
||||
if (Local::oldSettingsVersion() < 10021 && iconExists) {
|
||||
// Icon was changed.
|
||||
if (QFile(icon).remove()) {
|
||||
iconExists = false;
|
||||
}
|
||||
}
|
||||
if (!iconExists) {
|
||||
if (QFile(qsl(":/gui/art/logo_256.png")).copy(icon)) {
|
||||
DEBUG_LOG(("App Info: Icon copied to 'tdata'"));
|
||||
}
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION
|
||||
|
||||
DEBUG_LOG(("App Info: registerting for Gnome"));
|
||||
if (RunShellCommand("gconftool-2 -t string -s /desktop/gnome/url-handlers/tg/command " + EscapeShell(EscapeShell(QFile::encodeName(cExeDir() + cExeName())) + " -- %s"))) {
|
||||
RunShellCommand("gconftool-2 -t bool -s /desktop/gnome/url-handlers/tg/needs_terminal false");
|
||||
RunShellCommand("gconftool-2 -t bool -s /desktop/gnome/url-handlers/tg/enabled true");
|
||||
}
|
||||
RunShellCommand("update-desktop-database "
|
||||
+ EscapeShell(QFile::encodeName(applicationsPath)));
|
||||
|
||||
DEBUG_LOG(("App Info: placing .protocol file"));
|
||||
QString services;
|
||||
if (QDir(home + qsl(".kde4/")).exists()) {
|
||||
services = home + qsl(".kde4/share/kde4/services/");
|
||||
} else if (QDir(home + qsl(".kde/")).exists()) {
|
||||
services = home + qsl(".kde/share/kde4/services/");
|
||||
}
|
||||
if (!services.isEmpty()) {
|
||||
if (!QDir(services).exists()) QDir().mkpath(services);
|
||||
|
||||
QString path = services, file = path + qsl("tg.protocol");
|
||||
QFile f(file);
|
||||
if (f.open(QIODevice::WriteOnly)) {
|
||||
QTextStream s(&f);
|
||||
s.setCodec("UTF-8");
|
||||
s << "[Protocol]\n";
|
||||
s << "exec=" << QFile::decodeName(EscapeShell(QFile::encodeName(cExeDir() + cExeName()))) << " -- %u\n";
|
||||
s << "protocol=tg\n";
|
||||
s << "input=none\n";
|
||||
s << "output=none\n";
|
||||
s << "helper=true\n";
|
||||
s << "listing=false\n";
|
||||
s << "reading=false\n";
|
||||
s << "writing=false\n";
|
||||
s << "makedir=false\n";
|
||||
s << "deleting=false\n";
|
||||
f.close();
|
||||
} else {
|
||||
LOG(("App Error: Could not open '%1' for write").arg(file));
|
||||
}
|
||||
}
|
||||
RunShellCommand("xdg-mime default "
|
||||
MACRO_TO_STRING(TDESKTOP_LAUNCHER_BASENAME)
|
||||
".desktop x-scheme-handler/tg");
|
||||
#endif // !TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME
|
||||
}
|
||||
|
||||
|
|
@ -417,6 +442,28 @@ bool psShowOpenWithMenu(int x, int y, const QString &file) {
|
|||
}
|
||||
|
||||
void psAutoStart(bool start, bool silent) {
|
||||
auto home = getHomeDir();
|
||||
if (home.isEmpty() || cAlphaVersion() || cExeName().isEmpty())
|
||||
return;
|
||||
|
||||
if (InSandbox()) {
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
SandboxAutostart(start);
|
||||
#endif
|
||||
} else {
|
||||
const auto autostart =
|
||||
QStandardPaths::writableLocation(
|
||||
QStandardPaths::GenericConfigLocation)
|
||||
+ qsl("/autostart/");
|
||||
|
||||
if (start) {
|
||||
GenerateDesktopFile(autostart, qsl("-autostart"));
|
||||
} else {
|
||||
QFile::remove(autostart
|
||||
+ qsl(MACRO_TO_STRING(TDESKTOP_LAUNCHER_BASENAME)
|
||||
".desktop"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void psSendToMenu(bool send, bool silent) {
|
||||
|
|
|
|||
|
|
@ -358,7 +358,7 @@ void SetupTrayContent(not_null<Ui::VerticalLayout*> container) {
|
|||
}
|
||||
|
||||
#ifndef OS_WIN_STORE
|
||||
if (Platform::IsWindows()) {
|
||||
if (Platform::IsWindows() || Platform::IsLinux()) {
|
||||
const auto minimizedToggled = [] {
|
||||
return cStartMinimized() && !Global::LocalPasscode();
|
||||
};
|
||||
|
|
@ -369,9 +369,6 @@ void SetupTrayContent(not_null<Ui::VerticalLayout*> container) {
|
|||
const auto minimized = addSlidingCheckbox(
|
||||
tr::lng_settings_start_min(tr::now),
|
||||
minimizedToggled());
|
||||
const auto sendto = addCheckbox(
|
||||
tr::ktg_settings_add_sendto(tr::now),
|
||||
cSendToMenu());
|
||||
|
||||
autostart->checkedChanges(
|
||||
) | rpl::filter([](bool checked) {
|
||||
|
|
@ -408,6 +405,12 @@ void SetupTrayContent(not_null<Ui::VerticalLayout*> container) {
|
|||
) | rpl::start_with_next([=] {
|
||||
minimized->entity()->setChecked(minimizedToggled());
|
||||
}, minimized->lifetime());
|
||||
}
|
||||
|
||||
if (Platform::IsWindows()) {
|
||||
const auto sendto = addCheckbox(
|
||||
tr::ktg_settings_add_sendto(tr::now),
|
||||
cSendToMenu());
|
||||
|
||||
sendto->checkedChanges(
|
||||
) | rpl::filter([](bool checked) {
|
||||
|
|
|
|||
|
|
@ -401,10 +401,10 @@ void PreparedList::mergeToEnd(PreparedList &&other, bool cutToAlbumSize) {
|
|||
size_t(cutToAlbumSize ? kMaxAlbumCount : INT_MAX),
|
||||
files.size() + other.files.size()));
|
||||
for (auto &file : other.files) {
|
||||
files.push_back(std::move(file));
|
||||
if (cutToAlbumSize && files.size() == kMaxAlbumCount) {
|
||||
break;
|
||||
}
|
||||
files.push_back(std::move(file));
|
||||
}
|
||||
if (files.size() > 1 && files.size() <= kMaxAlbumCount) {
|
||||
const auto badIt = ranges::find(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
AppVersion 1009008
|
||||
AppVersion 1009009
|
||||
AppVersionStrMajor 1.9
|
||||
AppVersionStrSmall 1.9.8
|
||||
AppVersionStr 1.9.8
|
||||
AppVersionStrSmall 1.9.9
|
||||
AppVersionStr 1.9.9
|
||||
BetaChannel 0
|
||||
AlphaVersion 0
|
||||
AppVersionOriginal 1.9.8
|
||||
AppVersionOriginal 1.9.9
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit b1d635f9271040ae57c999fe9436c44470484372
|
||||
Subproject commit d37efd134a8040d85be4a52fc88fb87bd48130fe
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit f69cde56f1d3c0a0a7d83625f6f01a4e145eed14
|
||||
Subproject commit ffca05522fbe58d1ad098713d5327cb93c1bf2a2
|
||||
|
|
@ -1,3 +1,7 @@
|
|||
1.9.9 (28.01.20)
|
||||
|
||||
- Bug fixes and other minor improvements.
|
||||
|
||||
1.9.8 (24.01.20)
|
||||
|
||||
- Bug fixes and other minor improvements.
|
||||
|
|
|
|||
|
|
@ -1,66 +0,0 @@
|
|||
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
|
||||
#
|
||||
# Author: Marco Trevisan <marco@ubuntu.com>
|
||||
# Copyright (C) 2017-2018 Canonical Ltd
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 3 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import snapcraft
|
||||
|
||||
from snapcraft.internal import sources
|
||||
from snapcraft.plugins import autotools
|
||||
|
||||
class Dict2Object(object):
|
||||
def __init__(self, d):
|
||||
for k, v in d.items():
|
||||
setattr(self, k.replace('-', '_'), v)
|
||||
|
||||
|
||||
class AutotoolsSubsourcePlugin(autotools.AutotoolsPlugin):
|
||||
|
||||
@classmethod
|
||||
def schema(cls):
|
||||
schema = super().schema()
|
||||
|
||||
schema['properties']['sub-sources'] = {
|
||||
'type': 'array',
|
||||
'minitems': 0,
|
||||
'uniqueItems': True,
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'additionalProperties': True,
|
||||
},
|
||||
'default': [],
|
||||
}
|
||||
|
||||
return schema
|
||||
|
||||
@classmethod
|
||||
def get_pull_properties(cls):
|
||||
return [
|
||||
'sub-sources',
|
||||
]
|
||||
|
||||
def pull(self):
|
||||
super().pull()
|
||||
|
||||
for src in self.options.sub_sources:
|
||||
[name] = src.keys()
|
||||
[values] = src.values()
|
||||
|
||||
if 'source' in values:
|
||||
dest = values['dest'] if 'dest' in values else ''
|
||||
sources.get(os.path.join(self.sourcedir, dest),
|
||||
os.path.join(self.build_basedir, dest),
|
||||
Dict2Object(values))
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
|
||||
#
|
||||
# Author: Marco Trevisan <marco@ubuntu.com>
|
||||
# Copyright (C) 2017-2018 Canonical Ltd
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 3 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import snapcraft
|
||||
|
||||
from snapcraft.plugins import cmake
|
||||
|
||||
|
||||
class GypCMakePlugin(cmake.CMakePlugin):
|
||||
"""A basic plugin for snapcraft that generates CMake files from gyp"""
|
||||
|
||||
@classmethod
|
||||
def schema(cls):
|
||||
schema = super().schema()
|
||||
|
||||
schema['properties']['gyp-file'] = {
|
||||
'type': 'string'
|
||||
}
|
||||
|
||||
schema['properties']['build-type'] = {
|
||||
'type': 'string',
|
||||
'default': 'Release',
|
||||
'enum': ['Debug', 'Release'],
|
||||
}
|
||||
|
||||
schema['properties']['environment'] = {
|
||||
'type': 'array',
|
||||
'minitems': 0,
|
||||
'uniqueItems': True,
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'minitems': 0,
|
||||
'uniqueItems': True,
|
||||
'items': {
|
||||
'type': 'string',
|
||||
},
|
||||
},
|
||||
'default': [],
|
||||
}
|
||||
|
||||
schema['required'].append('gyp-file')
|
||||
|
||||
schema['build-properties'].extend([
|
||||
'build-type',
|
||||
'gyp-file',
|
||||
])
|
||||
|
||||
return schema
|
||||
|
||||
def __init__(self, name, options, project):
|
||||
super().__init__(name, options, project)
|
||||
self.build_packages.extend([
|
||||
'binutils',
|
||||
'python',
|
||||
])
|
||||
self.builddir = os.path.join(
|
||||
self.build_basedir, 'out', self.options.build_type)
|
||||
|
||||
def build(self):
|
||||
env = self._build_environment()
|
||||
gyp_path = os.path.join(self.sourcedir, os.path.dirname(self.options.gyp_file))
|
||||
|
||||
for environ in self.options.environment:
|
||||
[env_name] = list(environ)
|
||||
env[env_name] = str(environ[env_name])
|
||||
|
||||
if not os.path.exists(os.path.join(self.builddir, 'CMakeLists.txt')):
|
||||
gyp_command = ['gyp'] + self.options.configflags + ['--format=cmake']
|
||||
gyp_command.append('--generator-output={}'.format(self.build_basedir))
|
||||
gyp_command.append(os.path.basename(self.options.gyp_file))
|
||||
self.run(gyp_command, cwd=gyp_path)
|
||||
|
||||
if not os.path.exists(os.path.join(self.builddir, 'Makefile')):
|
||||
self.run(['cmake', '.'], env=env)
|
||||
|
||||
self.make(env=env)
|
||||
|
||||
if self.options.artifacts and self.options.build_type == 'Release':
|
||||
for artifact in self.options.artifacts:
|
||||
dest = os.path.join(self.installdir, artifact)
|
||||
if os.path.isfile(dest):
|
||||
mime_type = self.run_output(
|
||||
'file --mime-type -b {}'.format(dest).split())
|
||||
if 'application/x-executable' in mime_type:
|
||||
self.run(['strip', dest])
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
|
||||
#
|
||||
# Author: Marco Trevisan <marco@ubuntu.com>
|
||||
# Copyright (C) 2017-2018 Canonical Ltd
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 3 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import snapcraft
|
||||
import requests
|
||||
|
||||
from snapcraft.plugins import python
|
||||
|
||||
class PatchedPythonPlugin(python.PythonPlugin):
|
||||
|
||||
@classmethod
|
||||
def schema(cls):
|
||||
schema = super().schema()
|
||||
|
||||
schema['properties']['patches'] = {
|
||||
'type': 'array',
|
||||
'minitems': 0,
|
||||
'uniqueItems': True,
|
||||
'items': {
|
||||
'type': 'string',
|
||||
},
|
||||
'default': [],
|
||||
}
|
||||
|
||||
schema['pull-properties'].extend([
|
||||
'patches',
|
||||
])
|
||||
|
||||
return schema
|
||||
|
||||
def pull(self):
|
||||
super().pull()
|
||||
|
||||
for patch in self.options.patches:
|
||||
patch_name = os.path.basename(patch)
|
||||
patch_stamp = os.path.join(
|
||||
self.sourcedir, '.snapcraft-patched-{}'.format(patch_name))
|
||||
|
||||
if not os.path.exists(patch_stamp):
|
||||
if os.path.exists(patch):
|
||||
patch_file = os.path.join(os.getcwd(), patch)
|
||||
else:
|
||||
patch_file = os.path.join(
|
||||
self.sourcedir, 'snapcraft-patch-{}'.format(patch_name))
|
||||
with open(patch_file, 'wb') as file:
|
||||
file.write(requests.get(patch).content)
|
||||
|
||||
patch_cmd = 'git apply -v3 {}'.format(patch_file).split()
|
||||
self.run(patch_cmd, cwd=self.sourcedir)
|
||||
open(patch_stamp, 'a').close()
|
||||
|
|
@ -1,204 +0,0 @@
|
|||
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
|
||||
#
|
||||
# Author: Marco Trevisan <marco@ubuntu.com>
|
||||
# Copyright (C) 2017-2018 Canonical Ltd
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 3 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import snapcraft
|
||||
|
||||
from snapcraft.plugins import make
|
||||
|
||||
class QtBuilderPlugin(make.MakePlugin):
|
||||
|
||||
@classmethod
|
||||
def schema(cls):
|
||||
schema = super().schema()
|
||||
|
||||
schema['properties']['configflags'] = {
|
||||
'type': 'array',
|
||||
'minitems': 1,
|
||||
'uniqueItems': False,
|
||||
'items': {
|
||||
'type': 'string',
|
||||
},
|
||||
'default': [],
|
||||
}
|
||||
|
||||
schema['properties']['qt-source-git'] = {
|
||||
'type': 'string'
|
||||
}
|
||||
|
||||
schema['properties']['qt-source-depth'] = {
|
||||
'type': 'integer',
|
||||
'default': 1
|
||||
}
|
||||
|
||||
schema['properties']['qt-version'] = {
|
||||
'type': 'string'
|
||||
}
|
||||
|
||||
schema['properties']['qt-patches-base-url'] = {
|
||||
'type': 'string'
|
||||
}
|
||||
|
||||
schema['properties']['qt-patches-path'] = {
|
||||
'type': 'string'
|
||||
}
|
||||
|
||||
schema['properties']['qt-submodules'] = {
|
||||
'type': 'array',
|
||||
'minitems': 0,
|
||||
'uniqueItems': True,
|
||||
'items': {
|
||||
'type': 'string',
|
||||
},
|
||||
'default': [],
|
||||
}
|
||||
|
||||
schema['properties']['qt-extra-plugins'] = {
|
||||
'type': 'array',
|
||||
'minitems': 0,
|
||||
'uniqueItems': True,
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'minitems': 0,
|
||||
'uniqueItems': True,
|
||||
'items': {
|
||||
'type': 'string',
|
||||
},
|
||||
},
|
||||
'default': [],
|
||||
}
|
||||
|
||||
schema['properties']['environment'] = {
|
||||
'type': 'array',
|
||||
'minitems': 0,
|
||||
'uniqueItems': True,
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'minitems': 0,
|
||||
'uniqueItems': True,
|
||||
'items': {
|
||||
'type': 'string',
|
||||
},
|
||||
},
|
||||
'default': [],
|
||||
}
|
||||
|
||||
schema['required'].append('qt-source-git')
|
||||
|
||||
schema['build-properties'].append('configflags')
|
||||
|
||||
return schema
|
||||
|
||||
@classmethod
|
||||
def get_pull_properties(cls):
|
||||
return [
|
||||
'qt-version',
|
||||
'qt-patches-base-url',
|
||||
'qt-patches-path',
|
||||
'qt-submodules',
|
||||
'qt-extra-plugins',
|
||||
]
|
||||
|
||||
def __init__(self, name, options, project):
|
||||
super().__init__(name, options, project)
|
||||
self.build_packages.extend(['g++', 'patch', 'perl', 'wget'])
|
||||
self.options.source_depth = self.options.qt_source_depth
|
||||
|
||||
if self.options.qt_version:
|
||||
if self.options.qt_version[0] == 'v':
|
||||
self.options.source_branch = self.options.qt_version
|
||||
self.options.qt_version = self.options.qt_version[1:]
|
||||
else:
|
||||
self.options.source_branch = '.'.join(
|
||||
self.options.qt_version.split('.')[:-1])
|
||||
|
||||
|
||||
def pull(self):
|
||||
if not os.path.exists(os.path.join(self.sourcedir, '.git')) or \
|
||||
not os.path.exists(os.path.join(self.sourcedir, 'init-repository')):
|
||||
shutil.rmtree(self.sourcedir, ignore_errors=True)
|
||||
command = 'git clone {} {}'.format(
|
||||
self.options.qt_source_git, self.sourcedir).split()
|
||||
if self.options.source_branch:
|
||||
command.extend(['--branch', str(self.options.source_branch)])
|
||||
if self.options.source_depth:
|
||||
command.extend(['--depth', str(self.options.source_depth)])
|
||||
|
||||
self.run(command)
|
||||
|
||||
command = 'perl init-repository --branch -f'.split()
|
||||
if len(self.options.qt_submodules):
|
||||
command.extend('--module-subset={}'.format(
|
||||
','.join(self.options.qt_submodules)).split())
|
||||
self.run(command, cwd=self.sourcedir)
|
||||
|
||||
if self.options.qt_version:
|
||||
self.run("git submodule foreach git checkout v{}".format(
|
||||
self.options.qt_version).split(), self.sourcedir)
|
||||
|
||||
patch_file_template = '${{name}}{}.diff'.format(
|
||||
'_' + self.options.qt_version.replace('.', '_') \
|
||||
if self.options.qt_version else '')
|
||||
|
||||
if self.options.qt_patches_base_url:
|
||||
patch_uri_template = '{}/{}'.format(
|
||||
self.options.qt_patches_base_url, patch_file_template)
|
||||
|
||||
patch_cmd = 'git submodule foreach -q'.split() + \
|
||||
['[ -e {touch_file} ] || ' \
|
||||
'wget -q -O - {patch_uri_template} | patch -p1 && ' \
|
||||
'touch {touch_file}'.format(
|
||||
patch_uri_template=patch_uri_template,
|
||||
touch_file='.snapcraft-qt-patched')]
|
||||
|
||||
self.run(patch_cmd, cwd=self.sourcedir)
|
||||
|
||||
if self.options.qt_patches_path:
|
||||
patch_path_template = os.path.join(
|
||||
os.getcwd(), self.options.qt_patches_path, patch_file_template)
|
||||
|
||||
patch_cmd = 'git submodule foreach -q'.split() + \
|
||||
['[ -e {patch} ] && git apply -v3 {patch} || true'.format(
|
||||
patch=patch_path_template)]
|
||||
|
||||
self.run(patch_cmd, cwd=self.sourcedir)
|
||||
|
||||
for extra_plugin in self.options.qt_extra_plugins:
|
||||
[framework] = list(extra_plugin)
|
||||
|
||||
final_path = os.path.join(self.sourcedir, 'qtbase', 'src',
|
||||
'plugins', framework)
|
||||
|
||||
for repo in extra_plugin[framework]:
|
||||
repo_path = os.path.basename(repo)
|
||||
if repo_path.endswith('.git'):
|
||||
repo_path = repo_path[:-4]
|
||||
|
||||
if not os.path.exists(os.path.join(final_path, repo_path)):
|
||||
command = 'git clone {}'.format(repo).split()
|
||||
self.run(command, cwd=final_path)
|
||||
|
||||
def build(self):
|
||||
env = {}
|
||||
|
||||
for environ in self.options.environment:
|
||||
[env_name] = list(environ)
|
||||
env[env_name] = str(environ[env_name])
|
||||
|
||||
self.run(['./configure'] + self.options.configflags, env=env)
|
||||
super().build()
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
default_downloaddir="$SNAP_USER_DATA/Telegram Desktop"
|
||||
|
||||
if [ -d "$default_downloaddir" ] && [ ! -L "$default_downloaddir" ]; then
|
||||
dest_downloaddir="$SNAP_USER_COMMON/$(basename "$default_downloaddir")"
|
||||
if [ -d "$dest_downloaddir" ]; then
|
||||
mv -v "$default_downloaddir/*" "$dest_downloaddir/"
|
||||
rmdir "$default_downloaddir"
|
||||
else
|
||||
mv -v "$default_downloaddir" "$SNAP_USER_COMMON"
|
||||
fi
|
||||
ln -sv "$dest_downloaddir" "$default_downloaddir"
|
||||
fi
|
||||
|
||||
default_im_module="xim"
|
||||
|
||||
if [ -n "$TELEGRAM_QT_IM_MODULE" ]; then
|
||||
export QT_IM_MODULE="$TELEGRAM_QT_IM_MODULE"
|
||||
elif [ -z "$QT_IM_MODULE" ] || [ "$QT_IM_MODULE" == "ibus" ]; then
|
||||
export QT_IM_MODULE="$default_im_module"
|
||||
fi
|
||||
|
||||
exec desktop-launch Telegram $*
|
||||
|
|
@ -1,438 +1,221 @@
|
|||
name: telegram-desktop
|
||||
version: git
|
||||
adopt-info: telegram
|
||||
description: |
|
||||
Telegram is a popular messaging protocol with encryption and security as
|
||||
its key focus.
|
||||
|
||||
Fast and secure desktop app, perfectly synced with your mobile phone.
|
||||
icon: Telegram/Resources/art/icon512@2x.png
|
||||
|
||||
base: core18
|
||||
grade: stable
|
||||
confinement: strict
|
||||
|
||||
version-script: |
|
||||
set -x
|
||||
version_file=Telegram/build/version
|
||||
version=$(sed -n "s/AppVersionStr[ ]\+\(.*\)\+/\1/p" $version_file)
|
||||
beta=$(sed -n "s/BetaChannel[ ]\+\(.*\)\+/\1/p" $version_file)
|
||||
|
||||
if [ "$beta" != "0" ]; then
|
||||
version="$version-beta"
|
||||
fi
|
||||
|
||||
version="${version}$(git describe --tags | sed 's,^v[^-]\+,,')"
|
||||
|
||||
echo $version
|
||||
|
||||
apps:
|
||||
telegram-desktop:
|
||||
command: telegram-launch
|
||||
command: bin/desktop-launch telegram-desktop
|
||||
common-id: org.telegram.desktop
|
||||
desktop: share/applications/telegramdesktop.desktop
|
||||
environment:
|
||||
DISABLE_WAYLAND: 1
|
||||
WAYLAND_DISPLAY: no-display
|
||||
QTCOMPOSE: $SNAP/usr/share/X11/locale
|
||||
HOME: "$SNAP_USER_COMMON"
|
||||
# Use GTK3 cursor theme, icon theme and open/save file dialogs.
|
||||
QT_QPA_PLATFORMTHEME: gtk3
|
||||
plugs:
|
||||
- desktop
|
||||
- desktop-legacy
|
||||
- gsettings
|
||||
- home
|
||||
- network
|
||||
- network-bind
|
||||
- network-manager
|
||||
- pulseaudio
|
||||
- removable-media
|
||||
- unity7
|
||||
|
||||
plugs:
|
||||
# Support for common GTK themes
|
||||
# https://forum.snapcraft.io/t/how-to-use-the-system-gtk-theme-via-the-gtk-common-themes-snap/6235
|
||||
gsettings:
|
||||
gtk-3-themes:
|
||||
interface: content
|
||||
target: $SNAP/usr/share/themes
|
||||
target: $SNAP/data-dir/themes
|
||||
default-provider: gtk-common-themes
|
||||
icon-themes:
|
||||
interface: content
|
||||
target: $SNAP/usr/share/icons
|
||||
target: $SNAP/data-dir/icons
|
||||
default-provider: gtk-common-themes
|
||||
sound-themes:
|
||||
interface: content
|
||||
target: $SNAP/usr/share/sounds
|
||||
target: $SNAP/data-dir/sounds
|
||||
default-provider: gtk-common-themes
|
||||
|
||||
parts:
|
||||
telegram:
|
||||
plugin: gyp-cmake
|
||||
plugin: cmake
|
||||
source: .
|
||||
source-type: git
|
||||
parse-info: [lib/xdg/telegramdesktop.appdata.xml]
|
||||
build-packages:
|
||||
- libappindicator-dev
|
||||
- libappindicator3-dev
|
||||
- libenchant-dev
|
||||
- libexif-dev
|
||||
- libicu-dev
|
||||
- liblzma-dev
|
||||
- libssl-dev
|
||||
- libdee-dev
|
||||
- zlib1g-dev
|
||||
gyp-file: Telegram/gyp/Telegram.gyp
|
||||
build-type: 'Release'
|
||||
artifacts: ['Telegram']
|
||||
environment:
|
||||
- CC: gcc-8
|
||||
- CXX: g++-8
|
||||
organize:
|
||||
Telegram: bin/Telegram
|
||||
configflags:
|
||||
- -Dapi_id=611335
|
||||
- -Dapi_hash=d524b414d21f4d37f08684c1df41ac9c
|
||||
- -Dlinux_path_breakpad=$SNAPCRAFT_STAGE
|
||||
- -Dlinux_path_range=$SNAPCRAFT_STAGE/range-v3
|
||||
- -Dlinux_path_ffmpeg=$SNAPCRAFT_STAGE
|
||||
- -Dlinux_path_libexif_lib=$SNAPCRAFT_STAGE
|
||||
- -Dlinux_path_openal=$SNAPCRAFT_STAGE
|
||||
- -Dlinux_path_opus_include=$SNAPCRAFT_STAGE/include/opus
|
||||
- -Dlinux_path_qt=$SNAPCRAFT_STAGE
|
||||
- -Dlinux_path_va=$SNAPCRAFT_STAGE
|
||||
- -Dlinux_path_vdpau=$SNAPCRAFT_STAGE
|
||||
- -Dlinux_path_xkbcommon=$SNAPCRAFT_STAGE
|
||||
- -Dlinux_lib_ssl=-lssl
|
||||
- -Dlinux_lib_crypto=-lcrypto
|
||||
- -Dlinux_lib_icu=-licuuc -licutu -licui18n
|
||||
- -Dbuild_defines=TDESKTOP_DISABLE_AUTOUPDATE,
|
||||
TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME,
|
||||
TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION
|
||||
- --depth=.
|
||||
override-build: |
|
||||
set -xe
|
||||
snapcraftctl build
|
||||
part_src=$SNAPCRAFT_PART_INSTALL/../src
|
||||
snap_gui=$SNAPCRAFT_STAGE/../snap/gui
|
||||
mkdir -vp $snap_gui
|
||||
cp -v $part_src/lib/xdg/telegramdesktop.desktop $snap_gui
|
||||
cp -v $part_src/Telegram/Resources/art/icon512@2x.png $snap_gui/icon.png
|
||||
sed -i "s|^Icon=.*|Icon=\${SNAP}/meta/gui/icon.png|g" $snap_gui/telegramdesktop.desktop
|
||||
after:
|
||||
- breakpad
|
||||
- ffmpeg
|
||||
- gyp
|
||||
- libva
|
||||
- openal
|
||||
- qt
|
||||
- range-v3
|
||||
- gcc8
|
||||
|
||||
telegram-launcher:
|
||||
plugin: dump
|
||||
source: snap/scripts
|
||||
organize:
|
||||
telegram-launch: bin/telegram-launch
|
||||
|
||||
desktop-integration:
|
||||
plugin: nil
|
||||
stage-packages:
|
||||
- libappindicator3-1
|
||||
- libnotify4
|
||||
- libpulse0
|
||||
after: [desktop-gtk3]
|
||||
stage:
|
||||
- -./usr/share/fonts/**
|
||||
- -./usr/share/themes/**
|
||||
- -./usr/share/icons/**
|
||||
- -./usr/share/sounds/**
|
||||
|
||||
desktop-gtk3:
|
||||
stage:
|
||||
- -./usr/share/fonts/**
|
||||
- -./usr/share/themes/**
|
||||
- -./usr/share/icons/**
|
||||
- -./usr/share/sounds/**
|
||||
override-build: |
|
||||
set -xe
|
||||
snapcraftctl build
|
||||
export XDG_DATA_DIRS=$SNAPCRAFT_PART_INSTALL/usr/share
|
||||
update-mime-database $SNAPCRAFT_PART_INSTALL/usr/share/mime
|
||||
|
||||
for dir in $SNAPCRAFT_PART_INSTALL/usr/share/icons/*/; do
|
||||
if [ -f $dir/index.theme ]; then
|
||||
gtk-update-icon-cache-3.0 -q $dir
|
||||
fi
|
||||
done
|
||||
|
||||
libva:
|
||||
source: https://github.com/01org/libva.git
|
||||
source-depth: 1
|
||||
plugin: autotools
|
||||
build-packages:
|
||||
- libdrm-dev
|
||||
- libegl1-mesa-dev
|
||||
- libgl1-mesa-dev
|
||||
- libx11-dev
|
||||
- libxext-dev
|
||||
- libxfixes-dev
|
||||
configflags:
|
||||
- --enable-static
|
||||
prime: [-./*]
|
||||
|
||||
libvdpau:
|
||||
source: https://gitlab.freedesktop.org/vdpau/libvdpau.git
|
||||
source-depth: 1
|
||||
source-branch: libvdpau-1.2
|
||||
plugin: autotools
|
||||
build-packages:
|
||||
- libx11-dev
|
||||
- x11proto-dri2-dev
|
||||
- libxext-dev
|
||||
configflags:
|
||||
- --enable-static
|
||||
prime: [-./*]
|
||||
|
||||
opus:
|
||||
source: https://github.com/xiph/opus.git
|
||||
source-depth: 1
|
||||
source-branch: v1.2.1
|
||||
plugin: autotools
|
||||
prime: [-./*]
|
||||
|
||||
ffmpeg:
|
||||
source: https://github.com/FFmpeg/FFmpeg.git
|
||||
source-depth: 1
|
||||
source-branch: release/3.4
|
||||
plugin: autotools
|
||||
build-packages:
|
||||
- libass-dev
|
||||
- libfreetype6-dev
|
||||
- libgpac-dev
|
||||
- liblzma-dev
|
||||
- libsdl1.2-dev
|
||||
- libtheora-dev
|
||||
- libtool
|
||||
- libvorbis-dev
|
||||
- libxcb1-dev
|
||||
- libxcb-shm0-dev
|
||||
- libxcb-xfixes0-dev
|
||||
- pkg-config
|
||||
- texi2html
|
||||
- yasm
|
||||
- zlib1g-dev
|
||||
configflags:
|
||||
- --prefix=/
|
||||
- --disable-debug
|
||||
- --disable-programs
|
||||
- --disable-doc
|
||||
- --disable-everything
|
||||
- --enable-gpl
|
||||
- --enable-version3
|
||||
- --enable-libopus
|
||||
- --enable-decoder=aac
|
||||
- --enable-decoder=aac_latm
|
||||
- --enable-decoder=aasc
|
||||
- --enable-decoder=flac
|
||||
- --enable-decoder=gif
|
||||
- --enable-decoder=h264
|
||||
- --enable-decoder=h264_vdpau
|
||||
- --enable-decoder=mp1
|
||||
- --enable-decoder=mp1float
|
||||
- --enable-decoder=mp2
|
||||
- --enable-decoder=mp2float
|
||||
- --enable-decoder=mp3
|
||||
- --enable-decoder=mp3adu
|
||||
- --enable-decoder=mp3adufloat
|
||||
- --enable-decoder=mp3float
|
||||
- --enable-decoder=mp3on4
|
||||
- --enable-decoder=mp3on4float
|
||||
- --enable-decoder=mpeg4
|
||||
- --enable-decoder=mpeg4_vdpau
|
||||
- --enable-decoder=msmpeg4v2
|
||||
- --enable-decoder=msmpeg4v3
|
||||
- --enable-decoder=opus
|
||||
- --enable-decoder=vorbis
|
||||
- --enable-decoder=wavpack
|
||||
- --enable-decoder=wmalossless
|
||||
- --enable-decoder=wmapro
|
||||
- --enable-decoder=wmav1
|
||||
- --enable-decoder=wmav2
|
||||
- --enable-decoder=wmavoice
|
||||
- --enable-encoder=libopus
|
||||
- --enable-hwaccel=h264_vaapi
|
||||
- --enable-hwaccel=h264_vdpau
|
||||
- --enable-hwaccel=mpeg4_vaapi
|
||||
- --enable-hwaccel=mpeg4_vdpau
|
||||
- --enable-parser=aac
|
||||
- --enable-parser=aac_latm
|
||||
- --enable-parser=flac
|
||||
- --enable-parser=h264
|
||||
- --enable-parser=mpeg4video
|
||||
- --enable-parser=mpegaudio
|
||||
- --enable-parser=opus
|
||||
- --enable-parser=vorbis
|
||||
- --enable-demuxer=aac
|
||||
- --enable-demuxer=flac
|
||||
- --enable-demuxer=gif
|
||||
- --enable-demuxer=h264
|
||||
- --enable-demuxer=mov
|
||||
- --enable-demuxer=mp3
|
||||
- --enable-demuxer=ogg
|
||||
- --enable-demuxer=wav
|
||||
- --enable-muxer=ogg
|
||||
- --enable-muxer=opus
|
||||
after:
|
||||
- libva
|
||||
- libvdpau
|
||||
- opus
|
||||
prime: [-./*]
|
||||
|
||||
openal:
|
||||
source: https://github.com/kcat/openal-soft.git
|
||||
source-depth: 1
|
||||
source-tag: openal-soft-1.19.1
|
||||
plugin: cmake
|
||||
build-packages:
|
||||
- oss4-dev
|
||||
- portaudio19-dev
|
||||
configflags:
|
||||
- -DCMAKE_BUILD_TYPE=Release
|
||||
- -DALSOFT_EXAMPLES=OFF
|
||||
- -DALSOFT_TESTS=OFF
|
||||
- -DALSOFT_UTILS=OFF
|
||||
- -DLIBTYPE=STATIC
|
||||
after:
|
||||
- ffmpeg
|
||||
prime: [-./*]
|
||||
|
||||
libxkbcommon:
|
||||
source: https://github.com/xkbcommon/libxkbcommon.git
|
||||
source-depth: 1
|
||||
source-tag: xkbcommon-0.8.4
|
||||
plugin: autotools
|
||||
build-packages:
|
||||
- xutils-dev
|
||||
- bison
|
||||
- python-xcbgen
|
||||
prime: [-./*]
|
||||
|
||||
qt:
|
||||
plugin: qtbuilder
|
||||
qt-version: 5.12.5
|
||||
qt-source-git: https://code.qt.io/qt/qt5.git
|
||||
qt-submodules: ['qtbase', 'qtimageformats']
|
||||
qt-patches-base-url: https://raw.githubusercontent.com/desktop-app/patches/master
|
||||
qt-extra-plugins:
|
||||
- platforminputcontexts:
|
||||
- https://github.com/telegramdesktop/fcitx.git
|
||||
- https://github.com/telegramdesktop/hime.git
|
||||
- https://github.com/telegramdesktop/nimf.git
|
||||
environment:
|
||||
- CC: gcc-8
|
||||
- CXX: g++-8
|
||||
- QMAKE_CC: gcc-8
|
||||
- QMAKE_CXX: g++-8
|
||||
parse-info: [share/metainfo/telegramdesktop.appdata.xml]
|
||||
build-packages:
|
||||
- gcc-8
|
||||
- g++-8
|
||||
- qtbase5-private-dev
|
||||
- libayatana-appindicator3-dev
|
||||
- libgtk-3-dev
|
||||
- libasound2-dev
|
||||
- libdbusmenu-glib-dev
|
||||
- libffi-dev
|
||||
- libavcodec-dev
|
||||
- libavformat-dev
|
||||
- libavutil-dev
|
||||
- libswscale-dev
|
||||
- libswresample-dev
|
||||
- liblz4-dev
|
||||
- liblzma-dev
|
||||
- libminizip-dev
|
||||
- libopenal-dev
|
||||
- libopus-dev
|
||||
- libpulse-dev
|
||||
- libssl-dev
|
||||
- libx11-xcb-dev
|
||||
- libxcb-xkb-dev
|
||||
- libxcb-icccm4-dev
|
||||
- libxcb-image0-dev
|
||||
- libxcb-keysyms1-dev
|
||||
- libxcb-randr0-dev
|
||||
- libxcb-render-util0-dev
|
||||
- libxcb-sync-dev
|
||||
- libxcb-util0-dev
|
||||
- libxcb-xfixes0-dev
|
||||
- libxcb1-dev
|
||||
- libxrender-dev
|
||||
- zlib1g-dev
|
||||
stage-packages:
|
||||
- qt5-image-formats-plugins
|
||||
- libayatana-appindicator3-1
|
||||
- libasound2
|
||||
- libavcodec57
|
||||
- libavformat57
|
||||
- libavutil55
|
||||
- libswscale4
|
||||
- libswresample2
|
||||
- liblz4-1
|
||||
- liblzma5
|
||||
- libminizip1
|
||||
- libopenal1
|
||||
- libopus0
|
||||
- libpulse0
|
||||
- libssl1.1
|
||||
- zlib1g
|
||||
configflags:
|
||||
- -prefix
|
||||
- $SNAPCRAFT_STAGE
|
||||
- -release
|
||||
- -force-debug-info
|
||||
- -opensource
|
||||
- -confirm-license
|
||||
- -qt-zlib
|
||||
- -qt-libpng
|
||||
- -qt-libjpeg
|
||||
- -qt-harfbuzz
|
||||
- -qt-pcre
|
||||
- -qt-xcb
|
||||
- -no-gtk
|
||||
- -no-mirclient
|
||||
- -system-freetype
|
||||
- -fontconfig
|
||||
- -no-opengl
|
||||
- -static
|
||||
- -dbus-runtime
|
||||
- -openssl-linked
|
||||
- -nomake
|
||||
- examples
|
||||
- -nomake
|
||||
- tests
|
||||
- -DCMAKE_C_COMPILER=gcc-8
|
||||
- -DCMAKE_CXX_COMPILER=g++-8
|
||||
- -DCMAKE_BUILD_TYPE=Release
|
||||
- -DTDESKTOP_API_ID=611335
|
||||
- -DTDESKTOP_API_HASH=d524b414d21f4d37f08684c1df41ac9c
|
||||
- -DDESKTOP_APP_USE_PACKAGED_FONTS=OFF
|
||||
- -DDESKTOP_APP_USE_PACKAGED_RLOTTIE=OFF
|
||||
- -DTDESKTOP_USE_PACKAGED_TGVOIP=OFF
|
||||
override-pull: |
|
||||
snapcraftctl pull
|
||||
|
||||
version_file=Telegram/build/version
|
||||
version=$(sed -n "s/AppVersionStr[ ]\+\(.*\)\+/\1/p" $version_file)
|
||||
beta=$(sed -n "s/BetaChannel[ ]\+\(.*\)\+/\1/p" $version_file)
|
||||
|
||||
if [ "$beta" != "0" ]; then
|
||||
version="$version-beta"
|
||||
fi
|
||||
|
||||
version="${version}$(git describe --tags | sed 's,^v[^-]\+,,')"
|
||||
|
||||
snapcraftctl set-version "$version"
|
||||
|
||||
sed -i 's|^Icon=.*|Icon=/share/icons/hicolor/512x512/apps/telegram.png|g' lib/xdg/telegramdesktop.desktop
|
||||
after:
|
||||
- libxkbcommon
|
||||
- gcc8
|
||||
- cmake
|
||||
- desktop-qt5
|
||||
- enchant
|
||||
- range-v3
|
||||
- xxhash
|
||||
|
||||
spellchecking:
|
||||
plugin: nil
|
||||
stage-packages:
|
||||
- hunspell-de-de
|
||||
- hunspell-en-au
|
||||
- hunspell-en-ca
|
||||
- hunspell-en-gb
|
||||
- hunspell-en-us
|
||||
- hunspell-en-za
|
||||
- hunspell-fr-classical
|
||||
- hunspell-it
|
||||
- hunspell-pl
|
||||
- hunspell-es
|
||||
- hunspell-pt-br
|
||||
- hunspell-pt-pt
|
||||
|
||||
desktop-qt5:
|
||||
source: https://github.com/ubuntu/snapcraft-desktop-helpers.git
|
||||
source-subdir: qt
|
||||
plugin: make
|
||||
make-parameters: ["FLAVOR=qt5"]
|
||||
build-packages:
|
||||
- build-essential
|
||||
- qtbase5-dev
|
||||
- dpkg-dev
|
||||
stage-packages:
|
||||
- libxkbcommon0
|
||||
- ttf-ubuntu-font-family
|
||||
- dmz-cursor-theme
|
||||
- light-themes
|
||||
- adwaita-icon-theme
|
||||
- gnome-themes-standard
|
||||
- shared-mime-info
|
||||
- libqt5gui5
|
||||
- libgdk-pixbuf2.0-0
|
||||
- libqt5svg5 # for loading icon themes which are svg
|
||||
- try: [appmenu-qt5] # not available on core18
|
||||
- locales-all
|
||||
- xdg-user-dirs
|
||||
- fcitx-frontend-qt5
|
||||
|
||||
qt5-gtk-platform:
|
||||
plugin: nil
|
||||
stage-packages:
|
||||
- qt5-gtk-platformtheme
|
||||
|
||||
cmake:
|
||||
source: "https://gitlab.kitware.com/cmake/cmake.git"
|
||||
source-depth: 1
|
||||
source-branch: master
|
||||
source-type: git
|
||||
plugin: make
|
||||
override-build: |
|
||||
${SNAPCRAFT_PART_SRC}/bootstrap \
|
||||
--parallel=${SNAPCRAFT_PARALLEL_BUILD_COUNT} \
|
||||
-- \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX=/ \
|
||||
-DBUILD_TESTING=OFF
|
||||
snapcraftctl build
|
||||
build-packages:
|
||||
- build-essential
|
||||
- libssl-dev
|
||||
- libncurses5-dev
|
||||
stage-packages:
|
||||
- libssl1.1
|
||||
- libncurses5
|
||||
- libtinfo5
|
||||
prime: [-./*]
|
||||
|
||||
breakpad:
|
||||
plugin: autotools-subsource
|
||||
source: https://chromium.googlesource.com/breakpad/breakpad
|
||||
source-type: git
|
||||
source-commit: bc8fb886
|
||||
sub-sources:
|
||||
- linux-syscall-support:
|
||||
dest: src/third_party/lss
|
||||
source: https://chromium.googlesource.com/linux-syscall-support
|
||||
source-type: git
|
||||
source-commit: a91633d1
|
||||
prime: [-./*]
|
||||
enchant:
|
||||
source: https://github.com/AbiWord/enchant.git
|
||||
source-depth: 1
|
||||
source-tag: v2.2.7
|
||||
plugin: autotools
|
||||
build-packages:
|
||||
- libglib2.0-dev
|
||||
- libhunspell-dev
|
||||
stage-packages:
|
||||
- libglib2.0-0
|
||||
- libhunspell-1.6-0
|
||||
configflags:
|
||||
- --enable-relocatable
|
||||
prime: [-./bin/*]
|
||||
|
||||
range-v3:
|
||||
source: https://github.com/ericniebler/range-v3.git
|
||||
source-depth: 1
|
||||
source-tag: 0.10.0
|
||||
plugin: nil
|
||||
override-build: |
|
||||
set -x
|
||||
snapcraftctl build
|
||||
mkdir $SNAPCRAFT_PART_INSTALL/range-v3
|
||||
cp -rv * $SNAPCRAFT_PART_INSTALL/range-v3
|
||||
plugin: cmake
|
||||
configflags:
|
||||
- -DRANGE_V3_TESTS=OFF
|
||||
- -DRANGE_V3_EXAMPLES=OFF
|
||||
- -DRANGE_V3_DOCS=OFF
|
||||
prime: [-./*]
|
||||
|
||||
gyp:
|
||||
plugin: patched-python
|
||||
source: https://chromium.googlesource.com/external/gyp
|
||||
source-type: git
|
||||
source-commit: 702ac58e47
|
||||
python-version: python2
|
||||
patches:
|
||||
- Telegram/Patches/gyp.diff
|
||||
prime: [-./*]
|
||||
|
||||
# Since this is supposed to be built against ubuntu 16.04, we need to manually
|
||||
# install gcc8, and this is a workaround to achieve this.
|
||||
# This part can be safely removed when build.snapcraft.io will allow
|
||||
# to build against 18.04.
|
||||
gcc8:
|
||||
plugin: nil
|
||||
build-packages:
|
||||
- libmpc-dev
|
||||
- libcloog-ppl-dev
|
||||
override-pull: |
|
||||
set -x
|
||||
echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu xenial main" | \
|
||||
sudo tee /etc/apt/sources.list.d/ubuntu-toolchain-r.list
|
||||
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 60C317803A41BA51845E371A1E9377A2BA9EF27F
|
||||
sudo apt-get update \
|
||||
-o Dir::Etc::sourcelist="sources.list.d/ubuntu-toolchain-r.list" \
|
||||
-o Dir::Etc::sourceparts="-" -o APT::Get::List-Cleanup="0"
|
||||
snapcraftctl pull
|
||||
override-build: |
|
||||
set -x
|
||||
snapcraftctl build
|
||||
sudo apt install gcc-8 g++-8 -o Debug::pkgProblemResolver=yes --no-install-recommends -y
|
||||
sudo apt-mark auto gcc-8 g++-8
|
||||
sudo rm -f /etc/apt/sources.list.d/ubuntu-toolchain-r.list
|
||||
prime: [-./*]
|
||||
xxhash:
|
||||
source: https://github.com/Cyan4973/xxHash.git
|
||||
source-depth: 1
|
||||
source-tag: v0.7.2
|
||||
plugin: make
|
||||
make-parameters: [PREFIX=]
|
||||
prime: [-./bin/*]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue