diff --git a/.github/workflows/issue_closer.yml b/.github/workflows/issue_closer.yml index 4ad34baa7..8e5984df0 100644 --- a/.github/workflows/issue_closer.yml +++ b/.github/workflows/issue_closer.yml @@ -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); diff --git a/.github/workflows/snap.yml b/.github/workflows/snap.yml new file mode 100644 index 000000000..ed4fe99d8 --- /dev/null +++ b/.github/workflows/snap.yml @@ -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} diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 8839d8bbc..1c64970ff 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -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 +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 diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 7987616af..dc26cfd32 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -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."; diff --git a/Telegram/Resources/qrc/telegram/telegram.qrc b/Telegram/Resources/qrc/telegram/telegram.qrc index f197964ad..34dae207e 100644 --- a/Telegram/Resources/qrc/telegram/telegram.qrc +++ b/Telegram/Resources/qrc/telegram/telegram.qrc @@ -60,5 +60,6 @@ ../../langs/rewrites/ru.json + ../../../../lib/xdg/kotatogramdesktop.desktop diff --git a/Telegram/Resources/uwp/AppX/AppxManifest.xml b/Telegram/Resources/uwp/AppX/AppxManifest.xml index 6f4ffc088..998d2eda2 100644 --- a/Telegram/Resources/uwp/AppX/AppxManifest.xml +++ b/Telegram/Resources/uwp/AppX/AppxManifest.xml @@ -9,7 +9,7 @@ + Version="1.9.9.0" /> Telegram Desktop Telegram FZ-LLC diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 3866d85b8..121dccca2 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -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(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( diff --git a/Telegram/SourceFiles/boxes/create_poll_box.cpp b/Telegram/SourceFiles/boxes/create_poll_box.cpp index 4b37d38c6..040f5fd09 100644 --- a/Telegram/SourceFiles/boxes/create_poll_box.cpp +++ b/Telegram/SourceFiles/boxes/create_poll_box.cpp @@ -873,7 +873,7 @@ object_ptr CreatePollBox::setupContent() { ) | rpl::filter([=](not_null 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()); } diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index cb9075432..04376241a 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -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, diff --git a/Telegram/SourceFiles/core/version.h b/Telegram/SourceFiles/core/version.h index d9b84909a..4cc78b495 100644 --- a/Telegram/SourceFiles/core/version.h +++ b/Telegram/SourceFiles/core/version.h @@ -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; diff --git a/Telegram/SourceFiles/data/data_scheduled_messages.cpp b/Telegram/SourceFiles/data/data_scheduled_messages.cpp index 288359fee..7bbce72fa 100644 --- a/Telegram/SourceFiles/data/data_scheduled_messages.cpp +++ b/Telegram/SourceFiles/data/data_scheduled_messages.cpp @@ -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 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) const { const auto i = _data.find(history); return (i != end(_data)) ? i->second.items.size() : 0; } +void ScheduledMessages::sendNowSimpleMessage( + const MTPDupdateShortSentMessage &update, + not_null 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()), + 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()); diff --git a/Telegram/SourceFiles/data/data_scheduled_messages.h b/Telegram/SourceFiles/data/data_scheduled_messages.h index 68c586f42..57b7b74eb 100644 --- a/Telegram/SourceFiles/data/data_scheduled_messages.h +++ b/Telegram/SourceFiles/data/data_scheduled_messages.h @@ -29,8 +29,10 @@ public: ~ScheduledMessages(); [[nodiscard]] MsgId lookupId(not_null item) const; + [[nodiscard]] HistoryItem *lookupItem(PeerId peer, MsgId msg) const; [[nodiscard]] int count(not_null 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 item); void removeSending(not_null item); + void sendNowSimpleMessage( + const MTPDupdateShortSentMessage &update, + not_null local); + [[nodiscard]] rpl::producer<> updates(not_null history); [[nodiscard]] Data::MessagesSlice list(not_null history); diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index b674e85f0..aee9f0fd7 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -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(); } diff --git a/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp b/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp index d543948b7..13abb00e7 100644 --- a/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp +++ b/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp @@ -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( diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index f37ad10f1..7fde147f6 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -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()) { diff --git a/Telegram/SourceFiles/media/player/media_player_panel.cpp b/Telegram/SourceFiles/media/player/media_player_panel.cpp index 5eb81aa4c..6eb44bf44 100644 --- a/Telegram/SourceFiles/media/player/media_player_panel.cpp +++ b/Telegram/SourceFiles/media/player/media_player_panel.cpp @@ -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; diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index fedfc20aa..c4ff5ca17 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -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 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(); diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp index 794b205ef..0a75776aa 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp @@ -13,7 +13,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION #include -#include #include #include #endif @@ -31,7 +30,7 @@ constexpr auto kInterface = kService; std::vector GetServerInformation( const std::shared_ptr ¬ificationInterface) { std::vector serverInformation; - auto serverInformationReply = notificationInterface + const auto serverInformationReply = notificationInterface ->call(qsl("GetServerInformation")); if (serverInformationReply.type() == QDBusMessage::ReplyMessage) { @@ -58,7 +57,7 @@ std::vector GetServerInformation( QStringList GetCapabilities( const std::shared_ptr ¬ificationInterface) { - QDBusReply capabilitiesReply = notificationInterface + const QDBusReply 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 notifyReply = _notificationInterface->call(qsl("Notify"), - str_const_toString(AppName), uint(0), QString(), _title, _body, - _actions, _hints, -1); + const QDBusReply 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 closeReply = _notificationInterface + const QDBusReply 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(); - 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") diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index 536f24d43..72b287abd 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -24,6 +24,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include +#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION +#include +#endif + #include #include #include @@ -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) { diff --git a/Telegram/SourceFiles/settings/settings_advanced.cpp b/Telegram/SourceFiles/settings/settings_advanced.cpp index b417e0bcc..6777ea0f1 100644 --- a/Telegram/SourceFiles/settings/settings_advanced.cpp +++ b/Telegram/SourceFiles/settings/settings_advanced.cpp @@ -358,7 +358,7 @@ void SetupTrayContent(not_null 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 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 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) { diff --git a/Telegram/SourceFiles/storage/storage_media_prepare.cpp b/Telegram/SourceFiles/storage/storage_media_prepare.cpp index 1a28101cc..9cd6a86e6 100644 --- a/Telegram/SourceFiles/storage/storage_media_prepare.cpp +++ b/Telegram/SourceFiles/storage/storage_media_prepare.cpp @@ -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( diff --git a/Telegram/build/version b/Telegram/build/version index ea84f929e..dbd0c7634 100644 --- a/Telegram/build/version +++ b/Telegram/build/version @@ -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 diff --git a/Telegram/lib_spellcheck b/Telegram/lib_spellcheck index b1d635f92..d37efd134 160000 --- a/Telegram/lib_spellcheck +++ b/Telegram/lib_spellcheck @@ -1 +1 @@ -Subproject commit b1d635f9271040ae57c999fe9436c44470484372 +Subproject commit d37efd134a8040d85be4a52fc88fb87bd48130fe diff --git a/Telegram/lib_ui b/Telegram/lib_ui index f69cde56f..ffca05522 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit f69cde56f1d3c0a0a7d83625f6f01a4e145eed14 +Subproject commit ffca05522fbe58d1ad098713d5327cb93c1bf2a2 diff --git a/changelog.txt b/changelog.txt index 0f1df5d4f..b3d3c07fc 100644 --- a/changelog.txt +++ b/changelog.txt @@ -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. diff --git a/snap/plugins/x-autotools-subsource.py b/snap/plugins/x-autotools-subsource.py deleted file mode 100644 index 330ea0b1b..000000000 --- a/snap/plugins/x-autotools-subsource.py +++ /dev/null @@ -1,66 +0,0 @@ -# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- -# -# Author: Marco Trevisan -# 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 . - -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)) diff --git a/snap/plugins/x-gyp-cmake.py b/snap/plugins/x-gyp-cmake.py deleted file mode 100644 index 94a5ba1a8..000000000 --- a/snap/plugins/x-gyp-cmake.py +++ /dev/null @@ -1,100 +0,0 @@ -# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- -# -# Author: Marco Trevisan -# 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 . - -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]) diff --git a/snap/plugins/x-patched-python.py b/snap/plugins/x-patched-python.py deleted file mode 100644 index 0444ac667..000000000 --- a/snap/plugins/x-patched-python.py +++ /dev/null @@ -1,65 +0,0 @@ -# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- -# -# Author: Marco Trevisan -# 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 . - -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() diff --git a/snap/plugins/x-qtbuilder.py b/snap/plugins/x-qtbuilder.py deleted file mode 100644 index 860cd448a..000000000 --- a/snap/plugins/x-qtbuilder.py +++ /dev/null @@ -1,204 +0,0 @@ -# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- -# -# Author: Marco Trevisan -# 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 . - -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() diff --git a/snap/scripts/telegram-launch b/snap/scripts/telegram-launch deleted file mode 100755 index 8fe62b1fe..000000000 --- a/snap/scripts/telegram-launch +++ /dev/null @@ -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 $* diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 6461bba7b..0b4c5a3ac 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -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/*]