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;
|
let body = context.payload.issue.body;
|
||||||
|
|
||||||
console.log("Body of issue:\n" + 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);
|
let index2 = body.indexOf(item2);
|
||||||
index2 = (index2 == -1) ? Number.MAX_SAFE_INTEGER : index2;
|
index2 = (index2 == -1) ? Number.MAX_SAFE_INTEGER : index2;
|
||||||
|
|
||||||
|
|
@ -46,7 +46,7 @@ jobs:
|
||||||
return version[0].split(".")[0];
|
return version[0].split(".")[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
let issueVer = parseVersion(body.substring(index1, index2));
|
let issueVer = parseVersion(body.substring(index1 + item1.length, index2));
|
||||||
|
|
||||||
if (issueVer == undefined) {
|
if (issueVer == undefined) {
|
||||||
console.log(errorStr);
|
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(lib_qr)
|
||||||
add_subdirectory(codegen)
|
add_subdirectory(codegen)
|
||||||
|
|
||||||
|
include(CheckCXXSourceCompiles)
|
||||||
include(lib_ui/cmake/generate_styles.cmake)
|
include(lib_ui/cmake/generate_styles.cmake)
|
||||||
include(cmake/generate_lang.cmake)
|
include(cmake/generate_lang.cmake)
|
||||||
include(cmake/generate_numbers.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)
|
target_link_libraries(Telegram PRIVATE desktop-app::external_opus)
|
||||||
endif()
|
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)
|
target_precompile_headers(Telegram PRIVATE ${src_loc}/stdafx.h)
|
||||||
nice_target_sources(Telegram ${src_loc}
|
nice_target_sources(Telegram ${src_loc}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
|
|
|
||||||
|
|
@ -1268,6 +1268,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_cant_invite_make_admin" = "Make admin";
|
"lng_cant_invite_make_admin" = "Make admin";
|
||||||
|
|
||||||
"lng_send_button" = "Send";
|
"lng_send_button" = "Send";
|
||||||
|
"lng_schedule_button" = "Schedule";
|
||||||
"lng_send_silent_message" = "Send without sound";
|
"lng_send_silent_message" = "Send without sound";
|
||||||
"lng_schedule_message" = "Schedule message";
|
"lng_schedule_message" = "Schedule message";
|
||||||
"lng_reminder_message" = "Set a reminder";
|
"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_limit#other" = "You can add {count} more options.";
|
||||||
"lng_polls_create_maximum" = "You have added the maximum number of options.";
|
"lng_polls_create_maximum" = "You have added the maximum number of options.";
|
||||||
"lng_polls_create_settings" = "Settings";
|
"lng_polls_create_settings" = "Settings";
|
||||||
"lng_polls_create_hint" = "Tap to select the right option";
|
|
||||||
"lng_polls_create_anonymous" = "Anonymous Votes";
|
"lng_polls_create_anonymous" = "Anonymous Votes";
|
||||||
"lng_polls_create_multiple_choice" = "Multiple Answers";
|
"lng_polls_create_multiple_choice" = "Multiple Answers";
|
||||||
"lng_polls_create_quiz_mode" = "Quiz Mode";
|
"lng_polls_create_quiz_mode" = "Quiz Mode";
|
||||||
"lng_polls_create_button" = "Create";
|
"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_question" = "Please enter a question.";
|
||||||
"lng_polls_choose_answers" = "Please enter at least two options.";
|
"lng_polls_choose_answers" = "Please enter at least two options.";
|
||||||
"lng_polls_choose_correct" = "Please choose the correct answer.";
|
"lng_polls_choose_correct" = "Please choose the correct answer.";
|
||||||
|
|
|
||||||
|
|
@ -60,5 +60,6 @@
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/ktg_lang">
|
<qresource prefix="/ktg_lang">
|
||||||
<file alias="ru.json">../../langs/rewrites/ru.json</file>
|
<file alias="ru.json">../../langs/rewrites/ru.json</file>
|
||||||
|
<file alias="kotatogramdesktop.desktop">../../../../lib/xdg/kotatogramdesktop.desktop</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
|
||||||
|
|
@ -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.8.0" />
|
Version="1.9.9.0" />
|
||||||
<Properties>
|
<Properties>
|
||||||
<DisplayName>Telegram Desktop</DisplayName>
|
<DisplayName>Telegram Desktop</DisplayName>
|
||||||
<PublisherDisplayName>Telegram FZ-LLC</PublisherDisplayName>
|
<PublisherDisplayName>Telegram FZ-LLC</PublisherDisplayName>
|
||||||
|
|
|
||||||
|
|
@ -579,6 +579,13 @@ void ApiWrap::sendMessageFail(
|
||||||
requestFullPeer(peer);
|
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)) {
|
if (const auto item = _session->data().message(itemId)) {
|
||||||
Assert(randomId != 0);
|
Assert(randomId != 0);
|
||||||
|
|
@ -3652,10 +3659,22 @@ void ApiWrap::applyUpdateNoPtsCheck(const MTPUpdate &update) {
|
||||||
auto &d = update.c_updateNewMessage();
|
auto &d = update.c_updateNewMessage();
|
||||||
auto needToAdd = true;
|
auto needToAdd = true;
|
||||||
if (d.vmessage().type() == mtpc_message) { // index forwarded messages to links _overview
|
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!"));
|
LOG(("Skipping message, because it is already in blocks!"));
|
||||||
needToAdd = false;
|
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) {
|
if (needToAdd) {
|
||||||
_session->data().addNewMessage(
|
_session->data().addNewMessage(
|
||||||
|
|
|
||||||
|
|
@ -873,7 +873,7 @@ object_ptr<Ui::RpWidget> CreatePollBox::setupContent() {
|
||||||
) | rpl::filter([=](not_null<QEvent*> e) {
|
) | rpl::filter([=](not_null<QEvent*> e) {
|
||||||
return (e->type() == QEvent::MouseButtonPress) && quiz->checked();
|
return (e->type() == QEvent::MouseButtonPress) && quiz->checked();
|
||||||
}) | rpl::start_with_next([=] {
|
}) | 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());
|
}, multiple->lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1832,7 +1832,11 @@ void SendFilesBox::setupShadows(
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendFilesBox::prepare() {
|
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) {
|
if (_sendType == Api::SendType::Normal) {
|
||||||
SetupSendMenuAndShortcuts(
|
SetupSendMenuAndShortcuts(
|
||||||
_send,
|
_send,
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#define TDESKTOP_ALPHA_VERSION (0ULL)
|
#define TDESKTOP_ALPHA_VERSION (0ULL)
|
||||||
#endif // TDESKTOP_ALLOW_CLOSED_ALPHA
|
#endif // TDESKTOP_ALLOW_CLOSED_ALPHA
|
||||||
|
|
||||||
constexpr auto AppVersion = 1009008;
|
constexpr auto AppVersion = 1009009;
|
||||||
constexpr auto AppVersionStr = "1.9.8";
|
constexpr auto AppVersionStr = "1.9.9";
|
||||||
constexpr auto AppBetaVersion = false;
|
constexpr auto AppBetaVersion = false;
|
||||||
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
||||||
constexpr auto AppKotatoVersion = 1001005;
|
constexpr auto AppKotatoVersion = 1001005;
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "history/history_item_components.h"
|
#include "history/history_item_components.h"
|
||||||
|
#include "history/history_message.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
|
|
@ -111,11 +112,82 @@ MsgId ScheduledMessages::lookupId(not_null<HistoryItem*> item) const {
|
||||||
return j->second;
|
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 {
|
int ScheduledMessages::count(not_null<History*> history) const {
|
||||||
const auto i = _data.find(history);
|
const auto i = _data.find(history);
|
||||||
return (i != end(_data)) ? i->second.items.size() : 0;
|
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) {
|
void ScheduledMessages::apply(const MTPDupdateNewScheduledMessage &update) {
|
||||||
const auto &message = update.vmessage();
|
const auto &message = update.vmessage();
|
||||||
const auto peer = PeerFromMessage(message);
|
const auto peer = PeerFromMessage(message);
|
||||||
|
|
@ -132,6 +204,45 @@ void ScheduledMessages::apply(const MTPDupdateNewScheduledMessage &update) {
|
||||||
_updates.fire_copy(history);
|
_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(
|
void ScheduledMessages::apply(
|
||||||
const MTPDupdateDeleteScheduledMessages &update) {
|
const MTPDupdateDeleteScheduledMessages &update) {
|
||||||
const auto peer = peerFromMTP(update.vpeer());
|
const auto peer = peerFromMTP(update.vpeer());
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,10 @@ public:
|
||||||
~ScheduledMessages();
|
~ScheduledMessages();
|
||||||
|
|
||||||
[[nodiscard]] MsgId lookupId(not_null<HistoryItem*> item) const;
|
[[nodiscard]] MsgId lookupId(not_null<HistoryItem*> item) const;
|
||||||
|
[[nodiscard]] HistoryItem *lookupItem(PeerId peer, MsgId msg) const;
|
||||||
[[nodiscard]] int count(not_null<History*> history) const;
|
[[nodiscard]] int count(not_null<History*> history) const;
|
||||||
|
|
||||||
|
void checkEntitiesAndUpdate(const MTPDmessage &data);
|
||||||
void apply(const MTPDupdateNewScheduledMessage &update);
|
void apply(const MTPDupdateNewScheduledMessage &update);
|
||||||
void apply(const MTPDupdateDeleteScheduledMessages &update);
|
void apply(const MTPDupdateDeleteScheduledMessages &update);
|
||||||
void apply(
|
void apply(
|
||||||
|
|
@ -40,6 +42,10 @@ public:
|
||||||
void appendSending(not_null<HistoryItem*> item);
|
void appendSending(not_null<HistoryItem*> item);
|
||||||
void removeSending(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]] rpl::producer<> updates(not_null<History*> history);
|
||||||
[[nodiscard]] Data::MessagesSlice list(not_null<History*> history);
|
[[nodiscard]] Data::MessagesSlice list(not_null<History*> history);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -675,16 +675,17 @@ HistoryWidget::HistoryWidget(
|
||||||
) | rpl::filter([=](const Api::SendAction &action) {
|
) | rpl::filter([=](const Api::SendAction &action) {
|
||||||
return (action.history == _history);
|
return (action.history == _history);
|
||||||
}) | rpl::start_with_next([=](const Api::SendAction &action) {
|
}) | rpl::start_with_next([=](const Api::SendAction &action) {
|
||||||
|
const auto lastKeyboardUsed = lastForceReplyReplied(FullMsgId(
|
||||||
|
action.history->channelId(),
|
||||||
|
action.replyTo));
|
||||||
if (action.options.scheduled) {
|
if (action.options.scheduled) {
|
||||||
|
cancelReply(lastKeyboardUsed);
|
||||||
crl::on_main(this, [=, history = action.history]{
|
crl::on_main(this, [=, history = action.history]{
|
||||||
controller->showSection(
|
controller->showSection(
|
||||||
HistoryView::ScheduledMemento(history));
|
HistoryView::ScheduledMemento(history));
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
fastShowAtEnd(action.history);
|
fastShowAtEnd(action.history);
|
||||||
const auto lastKeyboardUsed = lastForceReplyReplied(FullMsgId(
|
|
||||||
action.history->channelId(),
|
|
||||||
action.replyTo));
|
|
||||||
if (cancelReply(lastKeyboardUsed) && !action.clearDraft) {
|
if (cancelReply(lastKeyboardUsed) && !action.clearDraft) {
|
||||||
onCloudDraftSave();
|
onCloudDraftSave();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -688,7 +688,7 @@ void ScheduleBox(
|
||||||
}, timeInput->lifetime());
|
}, timeInput->lifetime());
|
||||||
|
|
||||||
box->setFocusCallback([=] { timeInput->setFocusFast(); });
|
box->setFocusCallback([=] { timeInput->setFocusFast(); });
|
||||||
const auto submit = box->addButton(tr::lng_settings_save(), [=] {
|
const auto submit = box->addButton(tr::lng_schedule_button(), [=] {
|
||||||
save(false);
|
save(false);
|
||||||
});
|
});
|
||||||
SetupSendMenuAndShortcuts(
|
SetupSendMenuAndShortcuts(
|
||||||
|
|
|
||||||
|
|
@ -3807,14 +3807,19 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) {
|
||||||
if (!IsServerMsgId(d.vid().v)) {
|
if (!IsServerMsgId(d.vid().v)) {
|
||||||
LOG(("API Error: Bad msgId got from server: %1").arg(d.vid().v));
|
LOG(("API Error: Bad msgId got from server: %1").arg(d.vid().v));
|
||||||
} else if (randomId) {
|
} else if (randomId) {
|
||||||
const auto sent = session().data().messageSentData(randomId);
|
auto &owner = session().data();
|
||||||
|
const auto sent = owner.messageSentData(randomId);
|
||||||
const auto lookupMessage = [&] {
|
const auto lookupMessage = [&] {
|
||||||
return sent.peerId
|
return sent.peerId
|
||||||
? session().data().message(
|
? owner.message(peerToChannel(sent.peerId), d.vid().v)
|
||||||
peerToChannel(sent.peerId),
|
|
||||||
d.vid().v)
|
|
||||||
: nullptr;
|
: 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);
|
const auto wasAlready = (lookupMessage() != nullptr);
|
||||||
feedUpdate(MTP_updateMessageID(d.vid(), MTP_long(randomId))); // ignore real date
|
feedUpdate(MTP_updateMessageID(d.vid(), MTP_long(randomId))); // ignore real date
|
||||||
if (const auto item = lookupMessage()) {
|
if (const auto item = lookupMessage()) {
|
||||||
|
|
|
||||||
|
|
@ -234,7 +234,9 @@ void Panel::refreshList() {
|
||||||
: nullptr;
|
: nullptr;
|
||||||
const auto media = item ? item->media() : nullptr;
|
const auto media = item ? item->media() : nullptr;
|
||||||
const auto document = media ? media->document() : nullptr;
|
const auto document = media ? media->document() : nullptr;
|
||||||
if (!document || !document->isSharedMediaMusic()) {
|
if (!document
|
||||||
|
|| !document->isSharedMediaMusic()
|
||||||
|
|| !IsServerMsgId(item->id)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
const auto result = item->history()->peer;
|
const auto result = item->history()->peer;
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
namespace Platform {
|
namespace Platform {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
constexpr auto kLauncherBasename = str_const(MACRO_TO_STRING(TDESKTOP_LAUNCHER_BASENAME) ".desktop");
|
||||||
|
|
||||||
bool noQtTrayIcon = false, tryAppIndicator = false;
|
bool noQtTrayIcon = false, tryAppIndicator = false;
|
||||||
bool useGtkBase = false, useAppIndicator = false, useStatusIcon = false, trayIconChecked = false, useUnityCount = 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"));
|
auto snapName = QString::fromLatin1(qgetenv("SNAP_NAME"));
|
||||||
if(snapName.isEmpty()) {
|
if(snapName.isEmpty()) {
|
||||||
std::vector<QString> possibleDesktopFiles = {
|
std::vector<QString> possibleDesktopFiles = {
|
||||||
MACRO_TO_STRING(TDESKTOP_LAUNCHER_BASENAME) ".desktop",
|
str_const_toString(kLauncherBasename),
|
||||||
"Kotatogram.desktop"
|
"Kotatogram.desktop"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -563,8 +565,12 @@ void MainWindow::psFirstShow() {
|
||||||
LOG(("Could not get Unity Launcher entry!"));
|
LOG(("Could not get Unity Launcher entry!"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG(("SNAP Environment detected, setting Launcher entry to %1-kotatogramdesktop.desktop!").arg(snapName));
|
LOG(("SNAP Environment detected, setting Launcher entry to %1_%2.desktop!")
|
||||||
_desktopFile = snapName + "_kotatogramdesktop.desktop";
|
.arg(snapName)
|
||||||
|
.arg(str_const_toString(kLauncherBasename)));
|
||||||
|
_desktopFile = snapName
|
||||||
|
+ '_'
|
||||||
|
+ str_const_toString(kLauncherBasename);
|
||||||
useUnityCount=true;
|
useUnityCount=true;
|
||||||
}
|
}
|
||||||
_dbusPath = "/com/canonical/unity/launcherentry/" + QString::number(djbStringHash("application://" + _desktopFile));
|
_dbusPath = "/com/canonical/unity/launcherentry/" + QString::number(djbStringHash("application://" + _desktopFile));
|
||||||
|
|
@ -573,25 +579,24 @@ void MainWindow::psFirstShow() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool showShadows = true;
|
|
||||||
|
|
||||||
show();
|
show();
|
||||||
//_private.enableShadow(winId());
|
|
||||||
if (cWindowPos().maximized) {
|
if (cWindowPos().maximized) {
|
||||||
DEBUG_LOG(("Window Pos: First show, setting maximized."));
|
DEBUG_LOG(("Window Pos: First show, setting maximized."));
|
||||||
setWindowState(Qt::WindowMaximized);
|
setWindowState(Qt::WindowMaximized);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((cLaunchMode() == LaunchModeAutoStart && cStartMinimized()) || cStartInTray()) {
|
if ((cLaunchMode() == LaunchModeAutoStart && cStartMinimized()) || cStartInTray()) {
|
||||||
setWindowState(Qt::WindowMinimized);
|
// If I call hide() synchronously here after show() then on Ubuntu 14.04
|
||||||
if (Global::WorkMode().value() == dbiwmTrayOnly || Global::WorkMode().value() == dbiwmWindowAndTray) {
|
// it will show a window frame with transparent window body, without content.
|
||||||
hide();
|
// And to be able to "Show from tray" one more hide() will be required.
|
||||||
} else {
|
crl::on_main(this, [=] {
|
||||||
show();
|
setWindowState(Qt::WindowMinimized);
|
||||||
}
|
if (Global::WorkMode().value() == dbiwmTrayOnly || Global::WorkMode().value() == dbiwmWindowAndTray) {
|
||||||
showShadows = false;
|
hide();
|
||||||
} else {
|
} else {
|
||||||
show();
|
show();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setPositionInited();
|
setPositionInited();
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||||
#include <QtCore/QVersionNumber>
|
#include <QtCore/QVersionNumber>
|
||||||
#include <QtDBus/QDBusConnection>
|
|
||||||
#include <QtDBus/QDBusReply>
|
#include <QtDBus/QDBusReply>
|
||||||
#include <QtDBus/QDBusMetaType>
|
#include <QtDBus/QDBusMetaType>
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -31,7 +30,7 @@ constexpr auto kInterface = kService;
|
||||||
std::vector<QString> GetServerInformation(
|
std::vector<QString> GetServerInformation(
|
||||||
const std::shared_ptr<QDBusInterface> ¬ificationInterface) {
|
const std::shared_ptr<QDBusInterface> ¬ificationInterface) {
|
||||||
std::vector<QString> serverInformation;
|
std::vector<QString> serverInformation;
|
||||||
auto serverInformationReply = notificationInterface
|
const auto serverInformationReply = notificationInterface
|
||||||
->call(qsl("GetServerInformation"));
|
->call(qsl("GetServerInformation"));
|
||||||
|
|
||||||
if (serverInformationReply.type() == QDBusMessage::ReplyMessage) {
|
if (serverInformationReply.type() == QDBusMessage::ReplyMessage) {
|
||||||
|
|
@ -58,7 +57,7 @@ std::vector<QString> GetServerInformation(
|
||||||
|
|
||||||
QStringList GetCapabilities(
|
QStringList GetCapabilities(
|
||||||
const std::shared_ptr<QDBusInterface> ¬ificationInterface) {
|
const std::shared_ptr<QDBusInterface> ¬ificationInterface) {
|
||||||
QDBusReply<QStringList> capabilitiesReply = notificationInterface
|
const QDBusReply<QStringList> capabilitiesReply = notificationInterface
|
||||||
->call(qsl("GetCapabilities"));
|
->call(qsl("GetCapabilities"));
|
||||||
|
|
||||||
if (capabilitiesReply.isValid()) {
|
if (capabilitiesReply.isValid()) {
|
||||||
|
|
@ -95,7 +94,7 @@ NotificationData::NotificationData(
|
||||||
, _title(title)
|
, _title(title)
|
||||||
, _peerId(peerId)
|
, _peerId(peerId)
|
||||||
, _msgId(msgId) {
|
, _msgId(msgId) {
|
||||||
auto capabilities = GetCapabilities(_notificationInterface);
|
const auto capabilities = GetCapabilities(_notificationInterface);
|
||||||
|
|
||||||
if (capabilities.contains(qsl("body-markup"))) {
|
if (capabilities.contains(qsl("body-markup"))) {
|
||||||
_body = subtitle.isEmpty()
|
_body = subtitle.isEmpty()
|
||||||
|
|
@ -112,17 +111,25 @@ NotificationData::NotificationData(
|
||||||
if (capabilities.contains(qsl("actions"))) {
|
if (capabilities.contains(qsl("actions"))) {
|
||||||
_actions << qsl("default") << QString();
|
_actions << qsl("default") << QString();
|
||||||
|
|
||||||
connect(_notificationInterface.get(),
|
_notificationInterface->connection().connect(
|
||||||
SIGNAL(ActionInvoked(uint, QString)),
|
str_const_toString(kService),
|
||||||
this, SLOT(notificationClicked(uint)));
|
str_const_toString(kObjectPath),
|
||||||
|
str_const_toString(kInterface),
|
||||||
|
qsl("ActionInvoked"),
|
||||||
|
this,
|
||||||
|
SLOT(notificationClicked(uint)));
|
||||||
|
|
||||||
if (capabilities.contains(qsl("inline-reply"))) {
|
if (capabilities.contains(qsl("inline-reply"))) {
|
||||||
_actions << qsl("inline-reply")
|
_actions << qsl("inline-reply")
|
||||||
<< tr::lng_notification_reply(tr::now);
|
<< tr::lng_notification_reply(tr::now);
|
||||||
|
|
||||||
connect(_notificationInterface.get(),
|
_notificationInterface->connection().connect(
|
||||||
SIGNAL(NotificationReplied(uint,QString)),
|
str_const_toString(kService),
|
||||||
this, SLOT(notificationReplied(uint,QString)));
|
str_const_toString(kObjectPath),
|
||||||
|
str_const_toString(kInterface),
|
||||||
|
qsl("NotificationReplied"),
|
||||||
|
this,
|
||||||
|
SLOT(notificationReplied(uint,QString)));
|
||||||
} else {
|
} else {
|
||||||
// icon name according to https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html
|
// icon name according to https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html
|
||||||
_actions << qsl("mail-reply-sender")
|
_actions << qsl("mail-reply-sender")
|
||||||
|
|
@ -153,15 +160,26 @@ NotificationData::NotificationData(
|
||||||
_hints["desktop-entry"] =
|
_hints["desktop-entry"] =
|
||||||
qsl(MACRO_TO_STRING(TDESKTOP_LAUNCHER_BASENAME));
|
qsl(MACRO_TO_STRING(TDESKTOP_LAUNCHER_BASENAME));
|
||||||
|
|
||||||
connect(_notificationInterface.get(),
|
_notificationInterface->connection().connect(
|
||||||
SIGNAL(NotificationClosed(uint, uint)),
|
str_const_toString(kService),
|
||||||
this, SLOT(notificationClosed(uint)));
|
str_const_toString(kObjectPath),
|
||||||
|
str_const_toString(kInterface),
|
||||||
|
qsl("NotificationClosed"),
|
||||||
|
this,
|
||||||
|
SLOT(notificationClosed(uint)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NotificationData::show() {
|
bool NotificationData::show() {
|
||||||
QDBusReply<uint> notifyReply = _notificationInterface->call(qsl("Notify"),
|
const QDBusReply<uint> notifyReply = _notificationInterface->call(
|
||||||
str_const_toString(AppName), uint(0), QString(), _title, _body,
|
qsl("Notify"),
|
||||||
_actions, _hints, -1);
|
str_const_toString(AppName),
|
||||||
|
uint(0),
|
||||||
|
QString(),
|
||||||
|
_title,
|
||||||
|
_body,
|
||||||
|
_actions,
|
||||||
|
_hints,
|
||||||
|
-1);
|
||||||
|
|
||||||
if (notifyReply.isValid()) {
|
if (notifyReply.isValid()) {
|
||||||
_notificationId = notifyReply.value();
|
_notificationId = notifyReply.value();
|
||||||
|
|
@ -174,7 +192,7 @@ bool NotificationData::show() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NotificationData::close() {
|
bool NotificationData::close() {
|
||||||
QDBusReply<void> closeReply = _notificationInterface
|
const QDBusReply<void> closeReply = _notificationInterface
|
||||||
->call(qsl("CloseNotification"), _notificationId);
|
->call(qsl("CloseNotification"), _notificationId);
|
||||||
|
|
||||||
if (!closeReply.isValid()) {
|
if (!closeReply.isValid()) {
|
||||||
|
|
@ -186,7 +204,7 @@ bool NotificationData::close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotificationData::setImage(const QString &imagePath) {
|
void NotificationData::setImage(const QString &imagePath) {
|
||||||
auto specificationVersion = ParseSpecificationVersion(
|
const auto specificationVersion = ParseSpecificationVersion(
|
||||||
GetServerInformation(_notificationInterface));
|
GetServerInformation(_notificationInterface));
|
||||||
|
|
||||||
QString imageKey;
|
QString imageKey;
|
||||||
|
|
@ -211,9 +229,16 @@ void NotificationData::setImage(const QString &imagePath) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto image = QImage(imagePath).convertToFormat(QImage::Format_RGBA8888);
|
const auto image = QImage(imagePath)
|
||||||
QByteArray imageBytes((const char*)image.constBits(),
|
.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());
|
image.sizeInBytes());
|
||||||
|
#endif
|
||||||
|
|
||||||
ImageData imageData;
|
ImageData imageData;
|
||||||
imageData.width = image.width();
|
imageData.width = image.width();
|
||||||
|
|
@ -285,7 +310,7 @@ const QDBusArgument &operator>>(const QDBusArgument &argument,
|
||||||
|
|
||||||
bool Supported() {
|
bool Supported() {
|
||||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||||
static auto Available = QDBusInterface(
|
static const auto Available = QDBusInterface(
|
||||||
str_const_toString(kService),
|
str_const_toString(kService),
|
||||||
str_const_toString(kObjectPath),
|
str_const_toString(kObjectPath),
|
||||||
str_const_toString(kInterface)).isValid();
|
str_const_toString(kInterface)).isValid();
|
||||||
|
|
@ -316,10 +341,10 @@ Manager::Private::Private(Manager *manager, Type type)
|
||||||
str_const_toString(kInterface))) {
|
str_const_toString(kInterface))) {
|
||||||
qDBusRegisterMetaType<NotificationData::ImageData>();
|
qDBusRegisterMetaType<NotificationData::ImageData>();
|
||||||
|
|
||||||
auto specificationVersion = ParseSpecificationVersion(
|
const auto specificationVersion = ParseSpecificationVersion(
|
||||||
GetServerInformation(_notificationInterface));
|
GetServerInformation(_notificationInterface));
|
||||||
|
|
||||||
auto capabilities = GetCapabilities(_notificationInterface);
|
const auto capabilities = GetCapabilities(_notificationInterface);
|
||||||
|
|
||||||
if (!specificationVersion.isNull()) {
|
if (!specificationVersion.isNull()) {
|
||||||
LOG(("Notification daemon specification version: %1")
|
LOG(("Notification daemon specification version: %1")
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include <QtCore/QProcess>
|
#include <QtCore/QProcess>
|
||||||
#include <QtCore/QVersionNumber>
|
#include <QtCore/QVersionNumber>
|
||||||
|
|
||||||
|
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||||
|
#include <QtDBus/QDBusInterface>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
@ -38,6 +42,27 @@ using Platform::File::internal::EscapeShell;
|
||||||
|
|
||||||
namespace {
|
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) {
|
bool RunShellCommand(const QByteArray &command) {
|
||||||
auto result = system(command.constData());
|
auto result = system(command.constData());
|
||||||
if (result) {
|
if (result) {
|
||||||
|
|
@ -87,6 +112,61 @@ void FallbackFontConfig() {
|
||||||
#endif // !DESKTOP_APP_USE_PACKAGED
|
#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
|
||||||
|
|
||||||
namespace Platform {
|
namespace Platform {
|
||||||
|
|
@ -98,7 +178,7 @@ void SetApplicationIcon(const QIcon &icon) {
|
||||||
bool InSandbox() {
|
bool InSandbox() {
|
||||||
static const auto Sandbox = QFileInfo::exists(
|
static const auto Sandbox = QFileInfo::exists(
|
||||||
QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation)
|
QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation)
|
||||||
+ qsl("/flatpak-info"));
|
+ qsl("/flatpak-info"));
|
||||||
return Sandbox;
|
return Sandbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,6 +200,8 @@ QString CurrentExecutablePath(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SingleInstanceLocalServerName(const QString &hash) {
|
QString SingleInstanceLocalServerName(const QString &hash) {
|
||||||
|
const auto isSnap = !qgetenv("SNAP").isEmpty();
|
||||||
|
|
||||||
const auto runtimeDir = QStandardPaths::writableLocation(
|
const auto runtimeDir = QStandardPaths::writableLocation(
|
||||||
QStandardPaths::RuntimeLocation);
|
QStandardPaths::RuntimeLocation);
|
||||||
|
|
||||||
|
|
@ -128,6 +210,8 @@ QString SingleInstanceLocalServerName(const QString &hash) {
|
||||||
+ qsl("/app/")
|
+ qsl("/app/")
|
||||||
+ QString::fromUtf8(qgetenv("FLATPAK_ID"))
|
+ QString::fromUtf8(qgetenv("FLATPAK_ID"))
|
||||||
+ '/' + hash;
|
+ '/' + hash;
|
||||||
|
} else if (QFileInfo::exists(runtimeDir) && isSnap) {
|
||||||
|
return runtimeDir + '/' + hash;
|
||||||
} else if (QFileInfo::exists(runtimeDir)) {
|
} else if (QFileInfo::exists(runtimeDir)) {
|
||||||
return runtimeDir + '/' + hash + '-' + cGUIDStr();
|
return runtimeDir + '/' + hash + '-' + cGUIDStr();
|
||||||
} else { // non-systemd distros
|
} else { // non-systemd distros
|
||||||
|
|
@ -258,104 +342,45 @@ void finish() {
|
||||||
void RegisterCustomScheme() {
|
void RegisterCustomScheme() {
|
||||||
#ifndef TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME
|
#ifndef TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME
|
||||||
auto home = getHomeDir();
|
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())
|
if (Core::UpdaterDisabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
const auto applicationsPath = QStandardPaths::writableLocation(
|
||||||
|
QStandardPaths::ApplicationsLocation) + '/';
|
||||||
|
|
||||||
#ifndef TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION
|
#ifndef TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION
|
||||||
DEBUG_LOG(("App Info: placing .desktop file"));
|
GenerateDesktopFile(applicationsPath, qsl("-- %u"));
|
||||||
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);
|
|
||||||
|
|
||||||
QString path = cWorkingDir() + qsl("tdata/"), file = path + qsl("kotatogramdesktop.desktop");
|
const auto icons =
|
||||||
QDir().mkpath(path);
|
QStandardPaths::writableLocation(
|
||||||
QFile f(file);
|
QStandardPaths::GenericDataLocation)
|
||||||
if (f.open(QIODevice::WriteOnly)) {
|
+ qsl("/icons/");
|
||||||
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'"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QTextStream s(&f);
|
if (!QDir(icons).exists()) QDir().mkpath(icons);
|
||||||
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 (RunShellCommand("desktop-file-install --dir=" + EscapeShell(QFile::encodeName(home + qsl(".local/share/applications"))) + " --delete-original " + EscapeShell(QFile::encodeName(file)))) {
|
const auto icon = icons + qsl("kotatogram.png");
|
||||||
DEBUG_LOG(("App Info: removing old .desktop file"));
|
auto iconExists = QFile(icon).exists();
|
||||||
QFile(qsl("%1.local/share/applications/kotatogram.desktop").arg(home)).remove();
|
if (Local::oldSettingsVersion() < 10021 && iconExists) {
|
||||||
|
// Icon was changed.
|
||||||
RunShellCommand("update-desktop-database " + EscapeShell(QFile::encodeName(home + qsl(".local/share/applications"))));
|
if (QFile(icon).remove()) {
|
||||||
RunShellCommand("xdg-mime default kotatogramdesktop.desktop x-scheme-handler/tg");
|
iconExists = false;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
LOG(("App Error: Could not open '%1' for write").arg(file));
|
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
|
#endif // !TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION
|
||||||
|
|
||||||
DEBUG_LOG(("App Info: registerting for Gnome"));
|
RunShellCommand("update-desktop-database "
|
||||||
if (RunShellCommand("gconftool-2 -t string -s /desktop/gnome/url-handlers/tg/command " + EscapeShell(EscapeShell(QFile::encodeName(cExeDir() + cExeName())) + " -- %s"))) {
|
+ EscapeShell(QFile::encodeName(applicationsPath)));
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_LOG(("App Info: placing .protocol file"));
|
RunShellCommand("xdg-mime default "
|
||||||
QString services;
|
MACRO_TO_STRING(TDESKTOP_LAUNCHER_BASENAME)
|
||||||
if (QDir(home + qsl(".kde4/")).exists()) {
|
".desktop x-scheme-handler/tg");
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // !TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME
|
#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) {
|
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) {
|
void psSendToMenu(bool send, bool silent) {
|
||||||
|
|
|
||||||
|
|
@ -358,7 +358,7 @@ void SetupTrayContent(not_null<Ui::VerticalLayout*> container) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef OS_WIN_STORE
|
#ifndef OS_WIN_STORE
|
||||||
if (Platform::IsWindows()) {
|
if (Platform::IsWindows() || Platform::IsLinux()) {
|
||||||
const auto minimizedToggled = [] {
|
const auto minimizedToggled = [] {
|
||||||
return cStartMinimized() && !Global::LocalPasscode();
|
return cStartMinimized() && !Global::LocalPasscode();
|
||||||
};
|
};
|
||||||
|
|
@ -369,9 +369,6 @@ void SetupTrayContent(not_null<Ui::VerticalLayout*> container) {
|
||||||
const auto minimized = addSlidingCheckbox(
|
const auto minimized = addSlidingCheckbox(
|
||||||
tr::lng_settings_start_min(tr::now),
|
tr::lng_settings_start_min(tr::now),
|
||||||
minimizedToggled());
|
minimizedToggled());
|
||||||
const auto sendto = addCheckbox(
|
|
||||||
tr::ktg_settings_add_sendto(tr::now),
|
|
||||||
cSendToMenu());
|
|
||||||
|
|
||||||
autostart->checkedChanges(
|
autostart->checkedChanges(
|
||||||
) | rpl::filter([](bool checked) {
|
) | rpl::filter([](bool checked) {
|
||||||
|
|
@ -408,6 +405,12 @@ void SetupTrayContent(not_null<Ui::VerticalLayout*> container) {
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
minimized->entity()->setChecked(minimizedToggled());
|
minimized->entity()->setChecked(minimizedToggled());
|
||||||
}, minimized->lifetime());
|
}, minimized->lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Platform::IsWindows()) {
|
||||||
|
const auto sendto = addCheckbox(
|
||||||
|
tr::ktg_settings_add_sendto(tr::now),
|
||||||
|
cSendToMenu());
|
||||||
|
|
||||||
sendto->checkedChanges(
|
sendto->checkedChanges(
|
||||||
) | rpl::filter([](bool checked) {
|
) | rpl::filter([](bool checked) {
|
||||||
|
|
|
||||||
|
|
@ -401,10 +401,10 @@ void PreparedList::mergeToEnd(PreparedList &&other, bool cutToAlbumSize) {
|
||||||
size_t(cutToAlbumSize ? kMaxAlbumCount : INT_MAX),
|
size_t(cutToAlbumSize ? kMaxAlbumCount : INT_MAX),
|
||||||
files.size() + other.files.size()));
|
files.size() + other.files.size()));
|
||||||
for (auto &file : other.files) {
|
for (auto &file : other.files) {
|
||||||
files.push_back(std::move(file));
|
|
||||||
if (cutToAlbumSize && files.size() == kMaxAlbumCount) {
|
if (cutToAlbumSize && files.size() == kMaxAlbumCount) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
files.push_back(std::move(file));
|
||||||
}
|
}
|
||||||
if (files.size() > 1 && files.size() <= kMaxAlbumCount) {
|
if (files.size() > 1 && files.size() <= kMaxAlbumCount) {
|
||||||
const auto badIt = ranges::find(
|
const auto badIt = ranges::find(
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
AppVersion 1009008
|
AppVersion 1009009
|
||||||
AppVersionStrMajor 1.9
|
AppVersionStrMajor 1.9
|
||||||
AppVersionStrSmall 1.9.8
|
AppVersionStrSmall 1.9.9
|
||||||
AppVersionStr 1.9.8
|
AppVersionStr 1.9.9
|
||||||
BetaChannel 0
|
BetaChannel 0
|
||||||
AlphaVersion 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)
|
1.9.8 (24.01.20)
|
||||||
|
|
||||||
- Bug fixes and other minor improvements.
|
- 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
|
name: telegram-desktop
|
||||||
version: git
|
|
||||||
adopt-info: telegram
|
adopt-info: telegram
|
||||||
description: |
|
icon: Telegram/Resources/art/icon512@2x.png
|
||||||
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.
|
|
||||||
|
|
||||||
|
base: core18
|
||||||
grade: stable
|
grade: stable
|
||||||
confinement: strict
|
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:
|
apps:
|
||||||
telegram-desktop:
|
telegram-desktop:
|
||||||
command: telegram-launch
|
command: bin/desktop-launch telegram-desktop
|
||||||
common-id: org.telegram.desktop
|
common-id: org.telegram.desktop
|
||||||
|
desktop: share/applications/telegramdesktop.desktop
|
||||||
environment:
|
environment:
|
||||||
DISABLE_WAYLAND: 1
|
# Use GTK3 cursor theme, icon theme and open/save file dialogs.
|
||||||
WAYLAND_DISPLAY: no-display
|
QT_QPA_PLATFORMTHEME: gtk3
|
||||||
QTCOMPOSE: $SNAP/usr/share/X11/locale
|
|
||||||
HOME: "$SNAP_USER_COMMON"
|
|
||||||
plugs:
|
plugs:
|
||||||
- desktop
|
- desktop
|
||||||
- desktop-legacy
|
- desktop-legacy
|
||||||
- gsettings
|
|
||||||
- home
|
- home
|
||||||
- network
|
- network
|
||||||
- network-bind
|
|
||||||
- network-manager
|
- network-manager
|
||||||
- pulseaudio
|
- pulseaudio
|
||||||
- removable-media
|
- removable-media
|
||||||
- unity7
|
- unity7
|
||||||
|
|
||||||
plugs:
|
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:
|
gtk-3-themes:
|
||||||
interface: content
|
interface: content
|
||||||
target: $SNAP/usr/share/themes
|
target: $SNAP/data-dir/themes
|
||||||
default-provider: gtk-common-themes
|
default-provider: gtk-common-themes
|
||||||
icon-themes:
|
icon-themes:
|
||||||
interface: content
|
interface: content
|
||||||
target: $SNAP/usr/share/icons
|
target: $SNAP/data-dir/icons
|
||||||
default-provider: gtk-common-themes
|
default-provider: gtk-common-themes
|
||||||
sound-themes:
|
sound-themes:
|
||||||
interface: content
|
interface: content
|
||||||
target: $SNAP/usr/share/sounds
|
target: $SNAP/data-dir/sounds
|
||||||
default-provider: gtk-common-themes
|
default-provider: gtk-common-themes
|
||||||
|
|
||||||
parts:
|
parts:
|
||||||
telegram:
|
telegram:
|
||||||
plugin: gyp-cmake
|
plugin: cmake
|
||||||
source: .
|
source: .
|
||||||
source-type: git
|
source-type: git
|
||||||
parse-info: [lib/xdg/telegramdesktop.appdata.xml]
|
parse-info: [share/metainfo/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
|
|
||||||
build-packages:
|
build-packages:
|
||||||
|
- gcc-8
|
||||||
|
- g++-8
|
||||||
|
- qtbase5-private-dev
|
||||||
|
- libayatana-appindicator3-dev
|
||||||
|
- libgtk-3-dev
|
||||||
- libasound2-dev
|
- libasound2-dev
|
||||||
- libdbusmenu-glib-dev
|
- libavcodec-dev
|
||||||
- libffi-dev
|
- libavformat-dev
|
||||||
|
- libavutil-dev
|
||||||
|
- libswscale-dev
|
||||||
|
- libswresample-dev
|
||||||
|
- liblz4-dev
|
||||||
- liblzma-dev
|
- liblzma-dev
|
||||||
|
- libminizip-dev
|
||||||
|
- libopenal-dev
|
||||||
|
- libopus-dev
|
||||||
- libpulse-dev
|
- libpulse-dev
|
||||||
- libssl-dev
|
- libssl-dev
|
||||||
- libx11-xcb-dev
|
- zlib1g-dev
|
||||||
- libxcb-xkb-dev
|
stage-packages:
|
||||||
- libxcb-icccm4-dev
|
- qt5-image-formats-plugins
|
||||||
- libxcb-image0-dev
|
- libayatana-appindicator3-1
|
||||||
- libxcb-keysyms1-dev
|
- libasound2
|
||||||
- libxcb-randr0-dev
|
- libavcodec57
|
||||||
- libxcb-render-util0-dev
|
- libavformat57
|
||||||
- libxcb-sync-dev
|
- libavutil55
|
||||||
- libxcb-util0-dev
|
- libswscale4
|
||||||
- libxcb-xfixes0-dev
|
- libswresample2
|
||||||
- libxcb1-dev
|
- liblz4-1
|
||||||
- libxrender-dev
|
- liblzma5
|
||||||
|
- libminizip1
|
||||||
|
- libopenal1
|
||||||
|
- libopus0
|
||||||
|
- libpulse0
|
||||||
|
- libssl1.1
|
||||||
|
- zlib1g
|
||||||
configflags:
|
configflags:
|
||||||
- -prefix
|
- -DCMAKE_C_COMPILER=gcc-8
|
||||||
- $SNAPCRAFT_STAGE
|
- -DCMAKE_CXX_COMPILER=g++-8
|
||||||
- -release
|
- -DCMAKE_BUILD_TYPE=Release
|
||||||
- -force-debug-info
|
- -DTDESKTOP_API_ID=611335
|
||||||
- -opensource
|
- -DTDESKTOP_API_HASH=d524b414d21f4d37f08684c1df41ac9c
|
||||||
- -confirm-license
|
- -DDESKTOP_APP_USE_PACKAGED_FONTS=OFF
|
||||||
- -qt-zlib
|
- -DDESKTOP_APP_USE_PACKAGED_RLOTTIE=OFF
|
||||||
- -qt-libpng
|
- -DTDESKTOP_USE_PACKAGED_TGVOIP=OFF
|
||||||
- -qt-libjpeg
|
override-pull: |
|
||||||
- -qt-harfbuzz
|
snapcraftctl pull
|
||||||
- -qt-pcre
|
|
||||||
- -qt-xcb
|
version_file=Telegram/build/version
|
||||||
- -no-gtk
|
version=$(sed -n "s/AppVersionStr[ ]\+\(.*\)\+/\1/p" $version_file)
|
||||||
- -no-mirclient
|
beta=$(sed -n "s/BetaChannel[ ]\+\(.*\)\+/\1/p" $version_file)
|
||||||
- -system-freetype
|
|
||||||
- -fontconfig
|
if [ "$beta" != "0" ]; then
|
||||||
- -no-opengl
|
version="$version-beta"
|
||||||
- -static
|
fi
|
||||||
- -dbus-runtime
|
|
||||||
- -openssl-linked
|
version="${version}$(git describe --tags | sed 's,^v[^-]\+,,')"
|
||||||
- -nomake
|
|
||||||
- examples
|
snapcraftctl set-version "$version"
|
||||||
- -nomake
|
|
||||||
- tests
|
sed -i 's|^Icon=.*|Icon=/share/icons/hicolor/512x512/apps/telegram.png|g' lib/xdg/telegramdesktop.desktop
|
||||||
after:
|
after:
|
||||||
- libxkbcommon
|
- cmake
|
||||||
- gcc8
|
- 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: [-./*]
|
prime: [-./*]
|
||||||
|
|
||||||
breakpad:
|
enchant:
|
||||||
plugin: autotools-subsource
|
source: https://github.com/AbiWord/enchant.git
|
||||||
source: https://chromium.googlesource.com/breakpad/breakpad
|
source-depth: 1
|
||||||
source-type: git
|
source-tag: v2.2.7
|
||||||
source-commit: bc8fb886
|
plugin: autotools
|
||||||
sub-sources:
|
build-packages:
|
||||||
- linux-syscall-support:
|
- libglib2.0-dev
|
||||||
dest: src/third_party/lss
|
- libhunspell-dev
|
||||||
source: https://chromium.googlesource.com/linux-syscall-support
|
stage-packages:
|
||||||
source-type: git
|
- libglib2.0-0
|
||||||
source-commit: a91633d1
|
- libhunspell-1.6-0
|
||||||
prime: [-./*]
|
configflags:
|
||||||
|
- --enable-relocatable
|
||||||
|
prime: [-./bin/*]
|
||||||
|
|
||||||
range-v3:
|
range-v3:
|
||||||
source: https://github.com/ericniebler/range-v3.git
|
source: https://github.com/ericniebler/range-v3.git
|
||||||
source-depth: 1
|
source-depth: 1
|
||||||
source-tag: 0.10.0
|
source-tag: 0.10.0
|
||||||
plugin: nil
|
plugin: cmake
|
||||||
override-build: |
|
configflags:
|
||||||
set -x
|
- -DRANGE_V3_TESTS=OFF
|
||||||
snapcraftctl build
|
- -DRANGE_V3_EXAMPLES=OFF
|
||||||
mkdir $SNAPCRAFT_PART_INSTALL/range-v3
|
- -DRANGE_V3_DOCS=OFF
|
||||||
cp -rv * $SNAPCRAFT_PART_INSTALL/range-v3
|
|
||||||
prime: [-./*]
|
prime: [-./*]
|
||||||
|
|
||||||
gyp:
|
xxhash:
|
||||||
plugin: patched-python
|
source: https://github.com/Cyan4973/xxHash.git
|
||||||
source: https://chromium.googlesource.com/external/gyp
|
source-depth: 1
|
||||||
source-type: git
|
source-tag: v0.7.2
|
||||||
source-commit: 702ac58e47
|
plugin: make
|
||||||
python-version: python2
|
make-parameters: [PREFIX=]
|
||||||
patches:
|
prime: [-./bin/*]
|
||||||
- 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: [-./*]
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue