diff --git a/CMakeLists.txt b/CMakeLists.txt index a7294e4f9..15152d5dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,8 @@ elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Android") set(MZ_PLATFORM_NAME "android") elseif(${CMAKE_SYSTEM_NAME} STREQUAL "iOS") set(MZ_PLATFORM_NAME "ios") +elseif(${CMAKE_SYSTEM_NAME} STREQUAL "tvOS") + set(MZ_PLATFORM_NAME "ios") elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten") set(MZ_PLATFORM_NAME "wasm") endif() @@ -39,12 +41,22 @@ set(QT_BUILD_TOOLS_WHEN_CROSS_COMPILING ON) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) +if(APPLE) + if(IOS OR CMAKE_SYSTEM_NAME STREQUAL "tvOS") + set(CMAKE_OSX_ARCHITECTURES "arm64") + elseif(MACOS_NE) + set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64") + else() + set(CMAKE_OSX_ARCHITECTURES "x86_64") + endif() +endif() + add_subdirectory(client) -if(NOT IOS AND NOT ANDROID AND NOT MACOS_NE) +if(NOT IOS AND NOT ANDROID AND NOT MACOS_NE AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") add_subdirectory(service) endif() -if ((LINUX AND NOT ANDROID) OR (APPLE AND NOT IOS AND NOT MACOS_NE) OR (WIN32)) +if ((LINUX AND NOT ANDROID) OR (APPLE AND NOT IOS AND NOT MACOS_NE AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") OR (WIN32)) include(${CMAKE_SOURCE_DIR}/cmake/CPack.cmake) endif() diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index eb4c81258..df8558621 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -33,7 +33,7 @@ add_definitions(-DDEV_S3_ENDPOINT="$ENV{DEV_S3_ENDPOINT}") add_definitions(-DFREE_V2_ENDPOINT="$ENV{FREE_V2_ENDPOINT}") add_definitions(-DPREM_V1_ENDPOINT="$ENV{PREM_V1_ENDPOINT}") -if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID)) +if(WIN32 OR (APPLE AND NOT IOS AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") OR (LINUX AND NOT ANDROID)) set(PACKAGES ${PACKAGES} Widgets) endif() @@ -46,7 +46,7 @@ set(LIBS ${LIBS} Qt6::Core5Compat Qt6::Concurrent ) -if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID)) +if(WIN32 OR (APPLE AND NOT IOS AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") OR (LINUX AND NOT ANDROID)) set(LIBS ${LIBS} Qt6::Widgets) endif() @@ -56,7 +56,7 @@ target_include_directories(${PROJECT} PUBLIC $ ) -if(WIN32 OR (APPLE AND NOT IOS AND NOT MACOS_NE) OR (LINUX AND NOT ANDROID)) +if(WIN32 OR (APPLE AND NOT IOS AND NOT MACOS_NE AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") OR (LINUX AND NOT ANDROID)) qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_interface.rep) qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_process_interface.rep) endif() @@ -175,7 +175,7 @@ if(LINUX AND NOT ANDROID) link_directories(${CMAKE_CURRENT_LIST_DIR}/platforms/linux) endif() -if(WIN32 OR (APPLE AND NOT IOS AND NOT MACOS_NE) OR (LINUX AND NOT ANDROID)) +if(WIN32 OR (APPLE AND NOT IOS AND NOT MACOS_NE AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") OR (LINUX AND NOT ANDROID)) add_compile_definitions(AMNEZIA_DESKTOP) endif() @@ -183,7 +183,7 @@ if(ANDROID) include(cmake/android.cmake) endif() -if(IOS) +if(IOS OR CMAKE_SYSTEM_NAME STREQUAL "tvOS") option(AMNEZIA_IOS_ENABLE_APPLETV_TARGET "Enable Apple TV target settings for iOS/Xcode projects" OFF) include(cmake/ios.cmake) include(cmake/ios-arch-fixup.cmake) diff --git a/client/amnezia_application.cpp b/client/amnezia_application.cpp index c53059302..ee78587e0 100644 --- a/client/amnezia_application.cpp +++ b/client/amnezia_application.cpp @@ -250,7 +250,7 @@ bool AmneziaApplication::parseCommands() return true; } -#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(MACOS_NE) +#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE) void AmneziaApplication::startLocalServer() { const QString serverName("AmneziaVPNInstance"); QLocalServer::removeServer(serverName); @@ -271,7 +271,7 @@ void AmneziaApplication::startLocalServer() { bool AmneziaApplication::eventFilter(QObject *watched, QEvent *event) { if (event->type() == QEvent::Close) { -#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(Q_OS_TVOS) quit(); #else if (m_forceQuit) { diff --git a/client/amnezia_application.h b/client/amnezia_application.h index c2f790354..980eff8d6 100644 --- a/client/amnezia_application.h +++ b/client/amnezia_application.h @@ -6,7 +6,7 @@ #include #include #include -#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(Q_OS_TVOS) #include #else #include @@ -19,7 +19,7 @@ #define amnApp (static_cast(QCoreApplication::instance())) -#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(Q_OS_TVOS) #define AMNEZIA_BASE_CLASS QGuiApplication #else #define AMNEZIA_BASE_CLASS QApplication @@ -37,7 +37,7 @@ public: void loadFonts(); bool parseCommands(); -#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(MACOS_NE) +#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE) void startLocalServer(); #endif diff --git a/client/cmake/ios.cmake b/client/cmake/ios.cmake index c1d0fa95b..a71506517 100644 --- a/client/cmake/ios.cmake +++ b/client/cmake/ios.cmake @@ -7,8 +7,12 @@ if(AMNEZIA_IOS_APPLETV) set(CMAKE_OSX_DEPLOYMENT_TARGET 17.0) set(QT_NO_SET_DEFAULT_IOS_LAUNCH_SCREEN TRUE) set(QT_NO_ADD_IOS_LAUNCH_SCREEN_TO_BUNDLE TRUE) + set(IOS_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/Info-tvOS.plist.in) + set(IOS_LAUNCHSCREEN_STORYBOARD ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/tvOS/AmneziaVPNLaunchScreen.storyboard) else() message("Apple TV target mode is OFF") + set(IOS_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/Info.plist.in) + set(IOS_LAUNCHSCREEN_STORYBOARD ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/AmneziaVPNLaunchScreen.storyboard) endif() enable_language(OBJC) @@ -18,13 +22,21 @@ enable_language(Swift) find_package(Qt6 REQUIRED COMPONENTS ShaderTools) set(LIBS ${LIBS} Qt6::ShaderTools) -find_library(FW_AUTHENTICATIONSERVICES AuthenticationServices) -find_library(FW_UIKIT UIKit) -find_library(FW_AVFOUNDATION AVFoundation) -find_library(FW_FOUNDATION Foundation) -find_library(FW_STOREKIT StoreKit) -find_library(FW_USERNOTIFICATIONS UserNotifications) -if(NOT AMNEZIA_IOS_APPLETV) +if(AMNEZIA_IOS_APPLETV) + # Use framework linker flags directly for tvOS to avoid iPhoneOS SDK absolute paths. + set(FW_AUTHENTICATIONSERVICES "-framework AuthenticationServices") + set(FW_UIKIT "-framework UIKit") + set(FW_AVFOUNDATION "-framework AVFoundation") + set(FW_FOUNDATION "-framework Foundation") + set(FW_STOREKIT "-framework StoreKit") + set(FW_USERNOTIFICATIONS "-framework UserNotifications") +else() + find_library(FW_AUTHENTICATIONSERVICES AuthenticationServices) + find_library(FW_UIKIT UIKit) + find_library(FW_AVFOUNDATION AVFoundation) + find_library(FW_FOUNDATION Foundation) + find_library(FW_STOREKIT StoreKit) + find_library(FW_USERNOTIFICATIONS UserNotifications) find_library(FW_NETWORKEXTENSION NetworkExtension) endif() @@ -70,7 +82,7 @@ target_include_directories(${PROJECT} PRIVATE ${Qt6Gui_PRIVATE_INCLUDE_DIRS}) set_target_properties(${PROJECT} PROPERTIES XCODE_LINK_BUILD_PHASE_MODE KNOWN_LOCATION - MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/Info.plist.in + MACOSX_BUNDLE_INFO_PLIST ${IOS_INFO_PLIST} MACOSX_BUNDLE_ICON_FILE "AppIcon" MACOSX_BUNDLE_INFO_STRING "AmneziaVPN" MACOSX_BUNDLE_BUNDLE_NAME "AmneziaVPN" @@ -103,6 +115,11 @@ if(AMNEZIA_IOS_APPLETV) XCODE_ATTRIBUTE_LIBRARY_SEARCH_PATHS "$(inherited) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)" XCODE_ATTRIBUTE_LIBRARY_SEARCH_PATHS[sdk=appletvos*] "$(inherited) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)" XCODE_ATTRIBUTE_LIBRARY_SEARCH_PATHS[sdk=appletvsimulator*] "$(inherited) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)" + XCODE_ATTRIBUTE_EXCLUDED_LIBRARY_SEARCH_PATHS "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS*.sdk/usr/lib/swift" + XCODE_ATTRIBUTE_EXCLUDED_FRAMEWORK_SEARCH_PATHS "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS*.sdk/System/Library/Frameworks" + ) + set_target_properties(${PROJECT} PROPERTIES + QT_IOS_PERMISSIONS "" ) else() set_target_properties(${PROJECT} PROPERTIES @@ -141,6 +158,59 @@ target_compile_options(${PROJECT} PRIVATE -DVPN_NE_BUNDLEID=\"${BUILD_IOS_APP_IDENTIFIER}.network-extension\" ) +if(AMNEZIA_IOS_APPLETV) + # qscnetworkreachability plugin links IOKit, which is unavailable on tvOS. + qt_import_plugins(${PROJECT} + NO_DEFAULT + INCLUDE + QIOSIntegrationPlugin + QJpegPlugin + QSvgPlugin + QGifPlugin + QICOPlugin + QSvgIconPlugin + QSecureTransportBackendPlugin + EXCLUDE + QSCNetworkReachabilityNetworkInformationPlugin + QDarwinCameraPermissionPlugin + ) + + # Static tvOS Qt build doesn't auto-link these plugin archives into the + # Xcode target, but the app entry point lives in QIOSIntegrationPlugin. + set(_amnezia_tvos_static_plugins + Qt6::QIOSIntegrationPlugin + Qt6::QIOSIntegrationPlugin_init + Qt6::QJpegPlugin + Qt6::QJpegPlugin_init + Qt6::QSvgPlugin + Qt6::QSvgPlugin_init + Qt6::QGifPlugin + Qt6::QGifPlugin_init + Qt6::QICOPlugin + Qt6::QICOPlugin_init + Qt6::QSvgIconPlugin + Qt6::QSvgIconPlugin_init + Qt6::QSecureTransportBackendPlugin + Qt6::QSecureTransportBackendPlugin_init + ) + foreach(_amnezia_tvos_static_plugin IN LISTS _amnezia_tvos_static_plugins) + if(TARGET ${_amnezia_tvos_static_plugin}) + target_link_libraries(${PROJECT} PRIVATE ${_amnezia_tvos_static_plugin}) + endif() + endforeach() + unset(_amnezia_tvos_static_plugin) + unset(_amnezia_tvos_static_plugins) + + # Qt 6.9.2 iOS package links IOKit via Qt6::Core interface, but tvOS SDK + # does not provide IOKit. Strip this single framework for Apple TV builds. + get_target_property(_qtcore_iface_libs Qt6::Core INTERFACE_LINK_LIBRARIES) + if(_qtcore_iface_libs) + string(REPLACE "-framework IOKit;" "" _qtcore_iface_libs "${_qtcore_iface_libs}") + string(REPLACE ";-framework IOKit" "" _qtcore_iface_libs "${_qtcore_iface_libs}") + set_property(TARGET Qt6::Core PROPERTY INTERFACE_LINK_LIBRARIES "${_qtcore_iface_libs}") + endif() +endif() + set(WG_APPLE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rd/amneziawg-apple/Sources) target_sources(${PROJECT} PRIVATE @@ -153,17 +223,29 @@ target_sources(${PROJECT} PRIVATE ${CLIENT_ROOT_DIR}/platforms/ios/VPNCController.swift ) -target_sources(${PROJECT} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/AmneziaVPNLaunchScreen.storyboard - ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/Media.xcassets - ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/PrivacyInfo.xcprivacy -) +if(IOS_LAUNCHSCREEN_STORYBOARD) + target_sources(${PROJECT} PRIVATE + ${IOS_LAUNCHSCREEN_STORYBOARD} + ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/Media.xcassets + ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/PrivacyInfo.xcprivacy + ) -set_property(TARGET ${PROJECT} APPEND PROPERTY RESOURCE - ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/AmneziaVPNLaunchScreen.storyboard - ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/Media.xcassets - ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/PrivacyInfo.xcprivacy -) + set_property(TARGET ${PROJECT} APPEND PROPERTY RESOURCE + ${IOS_LAUNCHSCREEN_STORYBOARD} + ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/Media.xcassets + ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/PrivacyInfo.xcprivacy + ) +else() + target_sources(${PROJECT} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/Media.xcassets + ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/PrivacyInfo.xcprivacy + ) + + set_property(TARGET ${PROJECT} APPEND PROPERTY RESOURCE + ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/Media.xcassets + ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/PrivacyInfo.xcprivacy + ) +endif() add_subdirectory(ios/networkextension) add_dependencies(${PROJECT} networkextension) diff --git a/client/cmake/sources.cmake b/client/cmake/sources.cmake index cc6532894..1b7c4bec5 100644 --- a/client/cmake/sources.cmake +++ b/client/cmake/sources.cmake @@ -39,7 +39,7 @@ set(HEADERS ${HEADERS} ${CLIENT_ROOT_DIR}/mozilla/controllerimpl.h ) -if(NOT IOS AND NOT MACOS_NE) +if(NOT IOS AND NOT MACOS_NE AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") set(HEADERS ${HEADERS} ${CLIENT_ROOT_DIR}/platforms/ios/QRCodeReaderBase.h ) @@ -89,14 +89,14 @@ set(SOURCES ${SOURCES} ${CLIENT_ROOT_DIR}/mozilla/shared/leakdetector.cpp ) -if(NOT IOS AND NOT MACOS_NE) +if(NOT IOS AND NOT MACOS_NE AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") set(SOURCES ${SOURCES} ${CLIENT_ROOT_DIR}/platforms/ios/QRCodeReaderBase.cpp ) endif() # Include native macOS platform helpers (dock/status-item) -if(APPLE AND NOT IOS) +if(APPLE AND NOT IOS AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") list(APPEND HEADERS ${CLIENT_ROOT_DIR}/platforms/macos/macosutils.h ${CLIENT_ROOT_DIR}/platforms/macos/macosstatusicon.h @@ -175,7 +175,7 @@ if(WIN32) ) endif() -if(WIN32 OR (APPLE AND NOT IOS AND NOT MACOS_NE) OR (LINUX AND NOT ANDROID)) +if(WIN32 OR (APPLE AND NOT IOS AND NOT MACOS_NE AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") OR (LINUX AND NOT ANDROID)) message("Client desktop build") add_compile_definitions(AMNEZIA_DESKTOP) diff --git a/client/configurators/openvpn_configurator.cpp b/client/configurators/openvpn_configurator.cpp index 75c611d76..06e3e5771 100644 --- a/client/configurators/openvpn_configurator.cpp +++ b/client/configurators/openvpn_configurator.cpp @@ -1,17 +1,13 @@ #include "openvpn_configurator.h" #include +#include #include #include #include #include #include #include -#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) - #include -#else - #include -#endif #include "core/networkUtilities.h" #include "containers/containers_defs.h" @@ -165,7 +161,7 @@ QString OpenVpnConfigurator::processConfigWithLocalSettings(const QPairapplicationDirPath()); + .arg(QCoreApplication::applicationDirPath()); config.append(dnsConf); #endif diff --git a/client/configurators/ssh_configurator.cpp b/client/configurators/ssh_configurator.cpp index 8e190103d..4fc01abd3 100644 --- a/client/configurators/ssh_configurator.cpp +++ b/client/configurators/ssh_configurator.cpp @@ -1,6 +1,7 @@ #include "ssh_configurator.h" #include +#include #include #include #include @@ -8,11 +9,6 @@ #include #include #include -#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(MACOS_NE) - #include -#else - #include -#endif #include "core/server_defs.h" #include "utilities.h" @@ -24,7 +20,7 @@ SshConfigurator::SshConfigurator(std::shared_ptr settings, const QShar QString SshConfigurator::convertOpenSShKey(const QString &key) { -#if !defined(Q_OS_IOS) && !defined(MACOS_NE) +#if !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE) QProcess p; p.setProcessChannelMode(QProcess::MergedChannels); @@ -70,13 +66,13 @@ QString SshConfigurator::convertOpenSShKey(const QString &key) // DEAD CODE. void SshConfigurator::openSshTerminal(const ServerCredentials &credentials) { -#if !defined(Q_OS_IOS) && !defined(MACOS_NE) +#if !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE) QProcess *p = new QProcess(); p->setProcessChannelMode(QProcess::SeparateChannels); #ifdef Q_OS_WIN p->setProcessEnvironment(prepareEnv()); - p->setProgram(qApp->applicationDirPath() + "\\cygwin\\putty.exe"); + p->setProgram(QCoreApplication::applicationDirPath() + "\\cygwin\\putty.exe"); if (credentials.secretData.contains("PRIVATE KEY")) { // todo: connect by key @@ -100,10 +96,10 @@ QProcessEnvironment SshConfigurator::prepareEnv() #ifdef Q_OS_WIN pathEnvVar.clear(); - pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "\\cygwin;"); - pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "\\openvpn;"); + pathEnvVar.prepend(QDir::toNativeSeparators(QCoreApplication::applicationDirPath()) + "\\cygwin;"); + pathEnvVar.prepend(QDir::toNativeSeparators(QCoreApplication::applicationDirPath()) + "\\openvpn;"); #elif defined(Q_OS_MACX) && !defined(MACOS_NE) - pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "/Contents/MacOS"); + pathEnvVar.prepend(QDir::toNativeSeparators(QCoreApplication::applicationDirPath()) + "/Contents/MacOS"); #endif env.insert("PATH", pathEnvVar); diff --git a/client/core/controllers/coreController.cpp b/client/core/controllers/coreController.cpp index 26267219a..2a5bc8acd 100644 --- a/client/core/controllers/coreController.cpp +++ b/client/core/controllers/coreController.cpp @@ -8,7 +8,7 @@ #include "platforms/android/android_controller.h" #endif -#if defined(Q_OS_IOS) +#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) #include "platforms/ios/ios_controller.h" #include #endif @@ -196,7 +196,7 @@ void CoreController::initAndroidController() void CoreController::initAppleController() { -#ifdef Q_OS_IOS +#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) IosController::Instance()->initialize(); connect(IosController::Instance(), &IosController::importConfigFromOutside, this, [this](QString data) { emit m_pageController->goToPageHome(); @@ -233,7 +233,7 @@ void CoreController::initSignalHandlers() void CoreController::initNotificationHandler() { -#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) +#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) m_notificationHandler.reset(NotificationHandler::create(nullptr)); connect(m_vpnConnection.get(), &VpnConnection::connectionStateChanged, m_notificationHandler.get(), @@ -248,7 +248,7 @@ void CoreController::initNotificationHandler() auto* trayHandler = qobject_cast(m_notificationHandler.get()); connect(this, &CoreController::websiteUrlChanged, trayHandler, &SystemTrayNotificationHandler::updateWebsiteUrl); -#endif +#endif } void CoreController::updateTranslator(const QLocale &locale) diff --git a/client/core/controllers/coreController.h b/client/core/controllers/coreController.h index 998e7d8d0..a4840d68e 100644 --- a/client/core/controllers/coreController.h +++ b/client/core/controllers/coreController.h @@ -5,7 +5,7 @@ #include #include -#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) +#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) #include "ui/systemtray_notificationhandler.h" #endif @@ -49,7 +49,7 @@ #include "ui/models/sites_model.h" #include "ui/models/newsModel.h" -#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) +#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) #include "ui/notificationhandler.h" #endif @@ -99,7 +99,7 @@ private: QSharedPointer m_vpnConnection; QSharedPointer m_translator; -#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) +#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) QScopedPointer m_notificationHandler; #endif diff --git a/client/core/networkUtilities.cpp b/client/core/networkUtilities.cpp index 1a52a974a..4c270b6d8 100644 --- a/client/core/networkUtilities.cpp +++ b/client/core/networkUtilities.cpp @@ -24,7 +24,7 @@ #include #include #endif -#if defined(Q_OS_MAC) && !defined(Q_OS_IOS) && !defined(MACOS_NE) +#if defined(Q_OS_MAC) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE) #include #include #include @@ -404,7 +404,7 @@ QPair NetworkUtilities::getGatewayAndIface() close(sock); return { gateway_address, QNetworkInterface::interfaceFromName(interface) }; #endif -#if defined(Q_OS_MAC) && !defined(Q_OS_IOS) && !defined(MACOS_NE) +#if defined(Q_OS_MAC) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE) QString gateway; int index = -1; diff --git a/client/ios/app/Info-tvOS.plist.in b/client/ios/app/Info-tvOS.plist.in new file mode 100644 index 000000000..c17a8b588 --- /dev/null +++ b/client/ios/app/Info-tvOS.plist.in @@ -0,0 +1,54 @@ + + + + + CFBundleAllowMixedLocalizations + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${QT_INTERNAL_DOLLAR_VAR}{PRODUCT_NAME} + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + CFBundleIdentifier + ${MACOSX_BUNDLE_GUI_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${MACOSX_BUNDLE_BUNDLE_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + ${MACOSX_BUNDLE_SHORT_VERSION_STRING} + CFBundleVersion + ${MACOSX_BUNDLE_BUNDLE_VERSION} + NSHumanReadableCopyright + ${MACOSX_BUNDLE_COPYRIGHT} + ITSAppUsesNonExemptEncryption + + UIRequiredDeviceCapabilities + + UIRequiresFullScreen + + UISupportedInterfaceOrientations + + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UILaunchStoryboardName + AmneziaVPNLaunchScreen + UIUserInterfaceStyle + Light + com.wireguard.ios.app_group_id + group.org.amnezia.AmneziaVPN + UIViewControllerBasedStatusBarAppearance + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + NSAllowsLocalNetworking + + + + diff --git a/client/ios/app/tvOS/AmneziaVPNLaunchScreen.storyboard b/client/ios/app/tvOS/AmneziaVPNLaunchScreen.storyboard new file mode 100644 index 000000000..71a8d1c09 --- /dev/null +++ b/client/ios/app/tvOS/AmneziaVPNLaunchScreen.storyboard @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/main.cpp b/client/main.cpp index 338189c43..5f62f3059 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -12,11 +12,11 @@ #include "Windows.h" #endif -#if defined(Q_OS_IOS) +#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) #include "platforms/ios/QtAppDelegate-C-Interface.h" #endif -#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(MACOS_NE) +#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE) bool isAnotherInstanceRunning() { QLocalSocket socket; @@ -47,7 +47,7 @@ int main(int argc, char *argv[]) AmneziaApplication app(argc, argv); OsSignalHandler::setup(); -#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(MACOS_NE) +#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE) if (isAnotherInstanceRunning()) { QTimer::singleShot(1000, &app, [&]() { app.quit(); }); return app.exec(); diff --git a/client/platforms/ios/QRCodeReaderBase.mm b/client/platforms/ios/QRCodeReaderBase.mm index 963c35a85..aa2221282 100644 --- a/client/platforms/ios/QRCodeReaderBase.mm +++ b/client/platforms/ios/QRCodeReaderBase.mm @@ -1,4 +1,4 @@ -#if !MACOS_NE +#if !MACOS_NE && !TARGET_OS_TV #include "QRCodeReaderBase.h" #import diff --git a/client/platforms/ios/ios_controller.mm b/client/platforms/ios/ios_controller.mm index 9302680bd..72636d6c7 100644 --- a/client/platforms/ios/ios_controller.mm +++ b/client/platforms/ios/ios_controller.mm @@ -959,6 +959,10 @@ void IosController::sendVpnExtensionMessage(NSDictionary* message, std::function } bool IosController::shareText(const QStringList& filesToSend) { +#if defined(Q_OS_TVOS) + Q_UNUSED(filesToSend) + return false; +#else NSMutableArray *sharingItems = [NSMutableArray new]; for (int i = 0; i < filesToSend.size(); i++) { @@ -967,7 +971,7 @@ bool IosController::shareText(const QStringList& filesToSend) { } #if !MACOS_NE UIViewController *qtController = getViewController(); - if (!qtController) return; + if (!qtController) return false; UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:sharingItems applicationActivities:nil]; #endif @@ -991,23 +995,25 @@ bool IosController::shareText(const QStringList& filesToSend) { wait.exec(); return isAccepted; +#endif } QString IosController::openFile() { -#if !MACOS_NE +#if defined(Q_OS_TVOS) + return QString(); +#elif !MACOS_NE UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:@[@"public.item"] inMode:UIDocumentPickerModeOpen]; DocumentPickerDelegate *documentPickerDelegate = [[DocumentPickerDelegate alloc] init]; documentPicker.delegate = documentPickerDelegate; UIViewController *qtController = getViewController(); - if (!qtController) return; + if (!qtController) return QString(); [qtController presentViewController:documentPicker animated:YES completion:nil]; - #endif __block QString filePath; -#if !MACOS_NE +#if !MACOS_NE && !defined(Q_OS_TVOS) documentPickerDelegate.documentPickerClosedCallback = ^(NSString *path) { if (path) { filePath = QString::fromUtf8(path.UTF8String); diff --git a/client/platforms/ios/ios_controller_wrapper.h b/client/platforms/ios/ios_controller_wrapper.h index ab3251546..bf569beb1 100644 --- a/client/platforms/ios/ios_controller_wrapper.h +++ b/client/platforms/ios/ios_controller_wrapper.h @@ -1,6 +1,7 @@ #import #import #import +#include #if !MACOS_NE #include @@ -21,7 +22,7 @@ class IosController; @end typedef void (^DocumentPickerClosedCallback)(NSString *path); -#if !MACOS_NE +#if !MACOS_NE && !TARGET_OS_TV @interface DocumentPickerDelegate : NSObject @property (nonatomic, copy) DocumentPickerClosedCallback documentPickerClosedCallback; diff --git a/client/platforms/ios/ios_controller_wrapper.mm b/client/platforms/ios/ios_controller_wrapper.mm index 38eb2d228..37d0a4140 100644 --- a/client/platforms/ios/ios_controller_wrapper.mm +++ b/client/platforms/ios/ios_controller_wrapper.mm @@ -26,7 +26,7 @@ @end -#if !MACOS_NE +#if !MACOS_NE && !TARGET_OS_TV @implementation DocumentPickerDelegate - (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray *)urls { diff --git a/client/platforms/ios/iosnotificationhandler.mm b/client/platforms/ios/iosnotificationhandler.mm index 773c6297a..98c17ffbd 100644 --- a/client/platforms/ios/iosnotificationhandler.mm +++ b/client/platforms/ios/iosnotificationhandler.mm @@ -7,6 +7,24 @@ #import #import +#if defined(Q_OS_TVOS) + +IOSNotificationHandler::IOSNotificationHandler(QObject* parent) : NotificationHandler(parent) {} + +IOSNotificationHandler::~IOSNotificationHandler() {} + +void IOSNotificationHandler::notify(NotificationHandler::Message type, + const QString& title, + const QString& message, + int timerMsec) { + Q_UNUSED(type) + Q_UNUSED(title) + Q_UNUSED(message) + Q_UNUSED(timerMsec) +} + +#else + #if !MACOS_NE #import @@ -172,3 +190,5 @@ void IOSNotificationHandler::notify(NotificationHandler::Message type, const QSt }]; } #endif + +#endif // Q_OS_TVOS diff --git a/client/protocols/protocols_defs.h b/client/protocols/protocols_defs.h index c1cd868d8..42313a621 100644 --- a/client/protocols/protocols_defs.h +++ b/client/protocols/protocols_defs.h @@ -190,7 +190,7 @@ namespace amnezia constexpr char defaultPort[] = "51820"; -#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(MACOS_NE) +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) constexpr char defaultMtu[] = "1280"; #else constexpr char defaultMtu[] = "1376"; @@ -210,7 +210,7 @@ namespace amnezia namespace awg { constexpr char defaultPort[] = "55424"; -#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(MACOS_NE) +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) constexpr char defaultMtu[] = "1280"; #else constexpr char defaultMtu[] = "1376"; diff --git a/client/protocols/vpnprotocol.cpp b/client/protocols/vpnprotocol.cpp index 318b5d92b..f373932e4 100644 --- a/client/protocols/vpnprotocol.cpp +++ b/client/protocols/vpnprotocol.cpp @@ -4,7 +4,7 @@ #include "core/errorstrings.h" #include "vpnprotocol.h" -#if defined(Q_OS_WINDOWS) || defined(Q_OS_MACX) and !defined MACOS_NE || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) +#if defined(Q_OS_WINDOWS) || (defined(Q_OS_MACX) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE)) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) #include "openvpnovercloakprotocol.h" #include "openvpnprotocol.h" #include "shadowsocksvpnprotocol.h" @@ -114,7 +114,7 @@ VpnProtocol *VpnProtocol::factory(DockerContainer container, const QJsonObject & #if defined(Q_OS_WINDOWS) case DockerContainer::Ipsec: return new Ikev2Protocol(configuration); #endif -#if defined(Q_OS_WINDOWS) || defined(Q_OS_MACX) and !defined MACOS_NE || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) +#if defined(Q_OS_WINDOWS) || (defined(Q_OS_MACX) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE)) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) case DockerContainer::OpenVpn: return new OpenVpnProtocol(configuration); case DockerContainer::Cloak: return new OpenVpnOverCloakProtocol(configuration); case DockerContainer::ShadowSocks: return new ShadowSocksVpnProtocol(configuration); diff --git a/client/ui/controllers/connectionController.cpp b/client/ui/controllers/connectionController.cpp index 23f43bc1f..3a0b249fd 100644 --- a/client/ui/controllers/connectionController.cpp +++ b/client/ui/controllers/connectionController.cpp @@ -1,11 +1,5 @@ #include "connectionController.h" -#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(MACOS_NE) - #include -#else - #include -#endif - #include "utilities.h" #include "core/controllers/vpnConfigurationController.h" #include "version.h" @@ -33,7 +27,7 @@ ConnectionController::ConnectionController(const QSharedPointer &s void ConnectionController::openConnection() { -#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(MACOS_NE) +#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE) if (!Utils::processIsRunning(Utils::executable(SERVICE_NAME, false), true)) { emit connectionErrorOccurred(ErrorCode::AmneziaServiceNotRunning); diff --git a/client/ui/controllers/importController.cpp b/client/ui/controllers/importController.cpp index 91d7ec3b5..024fe84e8 100644 --- a/client/ui/controllers/importController.cpp +++ b/client/ui/controllers/importController.cpp @@ -19,7 +19,7 @@ #ifdef Q_OS_ANDROID #include "platforms/android/android_controller.h" #endif -#if defined(Q_OS_IOS) || defined(MACOS_NE) +#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) #include #endif @@ -604,14 +604,14 @@ bool ImportController::decodeQrCode(const QString &code) } #endif -#if defined Q_OS_ANDROID || defined Q_OS_IOS +#if defined Q_OS_ANDROID || defined Q_OS_IOS || defined(Q_OS_TVOS) void ImportController::startDecodingQr() { m_qrCodeChunks.clear(); m_totalQrCodeChunksCount = 0; m_receivedQrCodeChunksCount = 0; - #if defined(Q_OS_IOS) || defined(MACOS_NE) + #if defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) m_isQrCodeProcessed = true; #endif #if defined Q_OS_ANDROID diff --git a/client/ui/controllers/importController.h b/client/ui/controllers/importController.h index c2da0b8bd..361272844 100644 --- a/client/ui/controllers/importController.h +++ b/client/ui/controllers/importController.h @@ -38,7 +38,7 @@ public slots: QString getConfigFileName(); QString getMaliciousWarningText(); -#if defined Q_OS_ANDROID || defined Q_OS_IOS +#if defined Q_OS_ANDROID || defined Q_OS_IOS || defined(Q_OS_TVOS) void startDecodingQr(); bool parseQrCodeChunk(const QString &code); @@ -70,7 +70,7 @@ private: void processAmneziaConfig(QJsonObject &config); -#if defined Q_OS_ANDROID || defined Q_OS_IOS +#if defined Q_OS_ANDROID || defined Q_OS_IOS || defined(Q_OS_TVOS) void stopDecodingQr(); #endif @@ -83,7 +83,7 @@ private: ConfigTypes m_configType; QString m_maliciousWarningText; -#if defined Q_OS_ANDROID || defined Q_OS_IOS +#if defined Q_OS_ANDROID || defined Q_OS_IOS || defined(Q_OS_TVOS) QMap m_qrCodeChunks; bool m_isQrCodeProcessed; int m_totalQrCodeChunksCount; diff --git a/client/ui/controllers/installController.h b/client/ui/controllers/installController.h index d18ba946d..4350dc7ea 100644 --- a/client/ui/controllers/installController.h +++ b/client/ui/controllers/installController.h @@ -2,7 +2,9 @@ #define INSTALLCONTROLLER_H #include -#include +#if !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) + #include +#endif #include "containers/containers_defs.h" #include "core/defs.h" @@ -111,7 +113,7 @@ private: QString m_privateKeyPassphrase; -#ifndef Q_OS_IOS +#if !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) QList> m_sftpMountProcesses; #endif }; diff --git a/client/ui/controllers/pageController.cpp b/client/ui/controllers/pageController.cpp index 3f3319c6d..a34b8d103 100644 --- a/client/ui/controllers/pageController.cpp +++ b/client/ui/controllers/pageController.cpp @@ -1,11 +1,12 @@ #include "pageController.h" #include "utils/converter.h" #include "core/errorstrings.h" +#include #if defined(MACOS_NE) #include "platforms/ios/ios_controller.h" #endif -#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(MACOS_NE) +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) #include #else #include @@ -14,7 +15,7 @@ #ifdef Q_OS_ANDROID #include "platforms/android/android_controller.h" #endif -#if defined Q_OS_MAC +#if defined(Q_OS_MACX) && !defined(Q_OS_TVOS) #include "ui/macos_util.h" #endif @@ -27,7 +28,7 @@ PageController::PageController(const QSharedPointer &serversModel, AndroidController::instance()->setNavigationBarColor(initialPageNavigationBarColor); #endif -#if defined Q_OS_MACX +#if defined(Q_OS_MACX) && !defined(Q_OS_TVOS) connect(this, &PageController::raiseMainWindow, []() { setDockIconVisible(true); }); @@ -64,7 +65,7 @@ QString PageController::getPagePath(PageLoader::PageEnum page) void PageController::closeWindow() { // On mobile platforms, quit app on close; on desktop, just hide window -#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(Q_OS_TVOS) qApp->quit(); #else emit hideMainWindow(); @@ -118,7 +119,7 @@ void PageController::showOnStartup() } else { #if defined(Q_OS_WIN) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) emit hideMainWindow(); -#elif defined(Q_OS_MACX) +#elif defined(Q_OS_MACX) && !defined(Q_OS_TVOS) setDockIconVisible(false); #endif } diff --git a/client/ui/controllers/settingsController.cpp b/client/ui/controllers/settingsController.cpp index 4a779e890..efd4228cb4 100644 --- a/client/ui/controllers/settingsController.cpp +++ b/client/ui/controllers/settingsController.cpp @@ -12,7 +12,7 @@ #include "platforms/android/android_controller.h" #endif -#if defined(Q_OS_IOS) || defined(MACOS_NE) +#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) #include #endif @@ -57,6 +57,8 @@ QString getPlatformName() return "Windows"; #elif defined(Q_OS_ANDROID) return "Android"; +#elif defined(Q_OS_TVOS) + return "tvOS"; #elif defined(Q_OS_LINUX) return "Linux"; #elif defined(Q_OS_MACX) @@ -109,7 +111,7 @@ bool SettingsController::isLoggingEnabled() void SettingsController::toggleLogging(bool enable) { m_settings->setSaveLogs(enable); -#if defined(Q_OS_IOS) +#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) AmneziaVPN::toggleLogging(enable); #endif if (enable == true) { @@ -192,7 +194,7 @@ void SettingsController::restoreAppConfigFromData(const QByteArray &data) if (ok) { QJsonObject newConfigData = QJsonDocument::fromJson(data).object(); -#if defined(Q_OS_WINDOWS) || defined(Q_OS_LINUX) || defined(Q_OS_MACX) +#if defined(Q_OS_WINDOWS) || defined(Q_OS_LINUX) || (defined(Q_OS_MACX) && !defined(Q_OS_TVOS)) bool autoStart = false; if (newConfigData.contains("Conf/autoStart")) { autoStart = newConfigData["Conf/autoStart"].toBool(); @@ -229,7 +231,7 @@ void SettingsController::restoreAppConfigFromData(const QByteArray &data) m_sitesModel->setRouteMode(siteSplitTunnelingRouteMode); m_sitesModel->toggleSplitTunneling(siteSplittunnelingEnabled); -#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(Q_OS_TVOS) m_settings->setAutoConnect(false); m_settings->setStartMinimized(false); m_settings->setKillSwitchEnabled(false); @@ -268,7 +270,7 @@ void SettingsController::clearSettings() emit changeSettingsFinished(tr("All settings have been reset to default values")); -#if defined(Q_OS_IOS) || defined(MACOS_NE) +#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) AmneziaVPN::clearSettings(); #endif } diff --git a/client/ui/controllers/systemController.cpp b/client/ui/controllers/systemController.cpp index 12b869903..61a1e16c8 100644 --- a/client/ui/controllers/systemController.cpp +++ b/client/ui/controllers/systemController.cpp @@ -14,7 +14,7 @@ #include "platforms/android/android_controller.h" #endif -#if defined(Q_OS_IOS) || defined(MACOS_NE) +#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) #include "platforms/ios/ios_controller.h" #include #endif @@ -31,7 +31,7 @@ void SystemController::saveFile(const QString &fileName, const QString &data) return; #endif -#ifdef Q_OS_IOS +#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) QUrl fileUrl = QDir::tempPath() + "/" + fileName; QFile file(fileUrl.toString()); #else @@ -43,7 +43,7 @@ void SystemController::saveFile(const QString &fileName, const QString &data) file.write(data.toUtf8()); file.close(); -#ifdef Q_OS_IOS +#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) QStringList filesToSend; filesToSend.append(fileUrl.toString()); // todo check if save successful @@ -98,7 +98,7 @@ QString SystemController::getFileName(const QString &acceptLabel, const QString return AndroidController::instance()->openFile(nameFilter); #endif -#ifdef Q_OS_IOS +#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) fileName = IosController::Instance()->openFile(); if (fileName.isEmpty()) { diff --git a/client/ui/notificationhandler.cpp b/client/ui/notificationhandler.cpp index 4ccdcdf16..a308d89c5 100644 --- a/client/ui/notificationhandler.cpp +++ b/client/ui/notificationhandler.cpp @@ -5,7 +5,7 @@ #include #include "notificationhandler.h" -#if defined(Q_OS_IOS) +#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) # include "platforms/ios/iosnotificationhandler.h" #else # include "systemtray_notificationhandler.h" @@ -14,7 +14,7 @@ // static NotificationHandler* NotificationHandler::create(QObject* parent) { -#if defined(Q_OS_IOS) +#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) return new IOSNotificationHandler(parent); #else return new SystemTrayNotificationHandler(parent); diff --git a/client/ui/qautostart.cpp b/client/ui/qautostart.cpp index b0165dc4d..86a85bb00 100644 --- a/client/ui/qautostart.cpp +++ b/client/ui/qautostart.cpp @@ -58,7 +58,7 @@ QString Autostart::appPath() { return QCoreApplication::applicationFilePath() + " --autostart"; } -#elif defined Q_OS_MACX +#elif defined(Q_OS_MACX) && !defined(Q_OS_TVOS) bool Autostart::isAutostart() { QProcess process; diff --git a/client/utilities.cpp b/client/utilities.cpp index 0acf83677..82dd45cbc 100755 --- a/client/utilities.cpp +++ b/client/utilities.cpp @@ -190,7 +190,7 @@ bool Utils::processIsRunning(const QString &fileName, const bool fullFlag) CloseHandle(hSnapshot); return false; -#elif defined(Q_OS_IOS) || defined(Q_OS_ANDROID) || defined(MACOS_NE) +#elif defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(Q_OS_ANDROID) || defined(MACOS_NE) return false; #else QProcess process; @@ -250,7 +250,7 @@ bool Utils::killProcessByName(const QString &name) CloseHandle(hSnapshot); return success; -#elif defined Q_OS_IOS || defined(Q_OS_ANDROID) +#elif defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(Q_OS_ANDROID) return false; #else return QProcess::execute("pkill", { name }) == 0; diff --git a/client/vpnconnection.cpp b/client/vpnconnection.cpp index e6db217ff..f46b6ea8e 100644 --- a/client/vpnconnection.cpp +++ b/client/vpnconnection.cpp @@ -27,7 +27,7 @@ #endif -#if defined(Q_OS_IOS) || defined(MACOS_NE) +#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) #include "platforms/ios/ios_controller.h" #endif @@ -37,7 +37,7 @@ VpnConnection::VpnConnection(std::shared_ptr settings, QObject *parent) : QObject(parent), m_settings(settings), m_checkTimer(new QTimer(this)) { -#if defined(Q_OS_IOS) || defined(MACOS_NE) +#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) m_checkTimer.setInterval(1000); connect(IosController::Instance(), &IosController::connectionStateChanged, this, &VpnConnection::onConnectionStateChanged); connect(IosController::Instance(), &IosController::bytesChanged, this, &VpnConnection::onBytesChanged); @@ -127,7 +127,7 @@ void VpnConnection::onConnectionStateChanged(Vpn::ConnectionState state) }); #endif -#if defined(Q_OS_IOS) || defined(MACOS_NE) +#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) if (state == Vpn::ConnectionState::Connected || state == Vpn::ConnectionState::Connecting || state == Vpn::ConnectionState::Reconnecting) { @@ -243,7 +243,7 @@ void VpnConnection::connectToVpn(int serverIndex, const ServerCredentials &crede appendSplitTunnelingConfig(); -#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(MACOS_NE) +#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE) m_vpnProtocol.reset(VpnProtocol::factory(container, m_vpnConfiguration)); if (!m_vpnProtocol) { setConnectionState(Vpn::ConnectionState::Error); @@ -255,7 +255,7 @@ void VpnConnection::connectToVpn(int serverIndex, const ServerCredentials &crede createAndroidConnections(); m_vpnProtocol.reset(androidVpnProtocol); -#elif defined Q_OS_IOS || defined(MACOS_NE) +#elif defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) Proto proto = ContainerProps::defaultProtocol(container); IosController::Instance()->connectVpn(proto, m_vpnConfiguration); connect(&m_checkTimer, &QTimer::timeout, IosController::Instance(), &IosController::checkStatus); @@ -446,7 +446,7 @@ void VpnConnection::reconnectToVpn() { void VpnConnection::disconnectFromVpn() { -#if defined(Q_OS_IOS) || defined(MACOS_NE) +#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) // iOS/macOS NE use IosController directly; m_vpnProtocol is not set there. IosController::Instance()->disconnectVpn(); disconnect(&m_checkTimer, &QTimer::timeout, IosController::Instance(), &IosController::checkStatus);