diff --git a/Telegram/BUILD b/Telegram/BUILD
index 7a9fbddf7d..361d602ad8 100644
--- a/Telegram/BUILD
+++ b/Telegram/BUILD
@@ -123,6 +123,7 @@ swift_library(
"//submodules/Postbox:Postbox",
"//submodules/SyncCore:SyncCore",
"//submodules/TelegramCore:TelegramCore",
+ "//submodules/AccountContext:AccountContext",
],
)
diff --git a/Wallet/BUILD b/Wallet/BUILD
index cab7075b2d..00f4365394 100644
--- a/Wallet/BUILD
+++ b/Wallet/BUILD
@@ -87,6 +87,7 @@ swift_library(
"//submodules/rlottie:RLottieBinding",
"//submodules/AnimatedStickerNode:AnimatedStickerNode",
"//submodules/WalletUI:WalletUI",
+ "//submodules/ffmpeg:FFMpeg",
],
)
diff --git a/submodules/AccountContext/BUCK b/submodules/AccountContext/BUCK
index 6a3a3d431f..120fec2a7e 100644
--- a/submodules/AccountContext/BUCK
+++ b/submodules/AccountContext/BUCK
@@ -16,7 +16,7 @@ static_library(
"//submodules/Postbox:Postbox#shared",
"//submodules/TelegramCore:TelegramCore#shared",
"//submodules/SyncCore:SyncCore#shared",
- #"//submodules/WalletCore:WalletCore",
+ "//submodules/WalletCore:WalletCore",
],
frameworks = [
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
diff --git a/submodules/AccountContext/BUILD b/submodules/AccountContext/BUILD
new file mode 100644
index 0000000000..fd5976b7f7
--- /dev/null
+++ b/submodules/AccountContext/BUILD
@@ -0,0 +1,25 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "AccountContext",
+ module_name = "AccountContext",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/TelegramAudio:TelegramAudio",
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/TemporaryCachedPeerDataManager:TemporaryCachedPeerDataManager",
+ "//submodules/DeviceLocationManager:DeviceLocationManager",
+ "//submodules/MediaPlayer:UniversalMediaPlayer",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ "//submodules/Postbox:Postbox",
+ "//submodules/TelegramCore:TelegramCore",
+ "//submodules/SyncCore:SyncCore",
+ "//submodules/WalletCore:WalletCore",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/AccountUtils/BUILD b/submodules/AccountUtils/BUILD
new file mode 100644
index 0000000000..4edfde468a
--- /dev/null
+++ b/submodules/AccountUtils/BUILD
@@ -0,0 +1,20 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "AccountUtils",
+ module_name = "AccountUtils",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ "//submodules/Postbox:Postbox",
+ "//submodules/TelegramCore:TelegramCore",
+ "//submodules/SyncCore:SyncCore",
+ "//submodules/AccountContext:AccountContext",
+ "//submodules/TelegramUIPreferences:TelegramUIPreferences",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/ActionSheetPeerItem/BUILD b/submodules/ActionSheetPeerItem/BUILD
new file mode 100644
index 0000000000..e2840eb207
--- /dev/null
+++ b/submodules/ActionSheetPeerItem/BUILD
@@ -0,0 +1,22 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "ActionSheetPeerItem",
+ module_name = "ActionSheetPeerItem",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/Postbox:Postbox",
+ "//submodules/TelegramCore:TelegramCore",
+ "//submodules/SyncCore:SyncCore",
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/AvatarNode:AvatarNode",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/AccountContext:AccountContext",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/ActionSheetPeerItem/Info.plist b/submodules/ActionSheetPeerItem/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/ActionSheetPeerItem/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/ActionSheetPeerItem/Sources/ActionSheetPeerItem.h b/submodules/ActionSheetPeerItem/Sources/ActionSheetPeerItem.h
deleted file mode 100644
index 43128d709d..0000000000
--- a/submodules/ActionSheetPeerItem/Sources/ActionSheetPeerItem.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// ActionSheetPeerItem.h
-// ActionSheetPeerItem
-//
-// Created by Peter on 8/5/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for ActionSheetPeerItem.
-FOUNDATION_EXPORT double ActionSheetPeerItemVersionNumber;
-
-//! Project version string for ActionSheetPeerItem.
-FOUNDATION_EXPORT const unsigned char ActionSheetPeerItemVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/ActivityIndicator/Info.plist b/submodules/ActivityIndicator/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/ActivityIndicator/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/ActivityIndicator/Sources/ActivityIndicator.h b/submodules/ActivityIndicator/Sources/ActivityIndicator.h
deleted file mode 100644
index d1f730c19a..0000000000
--- a/submodules/ActivityIndicator/Sources/ActivityIndicator.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// ActivityIndicator.h
-// ActivityIndicator
-//
-// Created by Peter on 8/1/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for ActivityIndicator.
-FOUNDATION_EXPORT double ActivityIndicatorVersionNumber;
-
-//! Project version string for ActivityIndicator.
-FOUNDATION_EXPORT const unsigned char ActivityIndicatorVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/AlertUI/Info.plist b/submodules/AlertUI/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/AlertUI/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/AnimationUI/BUILD b/submodules/AnimationUI/BUILD
new file mode 100644
index 0000000000..adc0b2a210
--- /dev/null
+++ b/submodules/AnimationUI/BUILD
@@ -0,0 +1,28 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "AnimationUI",
+ module_name = "AnimationUI",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ "//submodules/Postbox:Postbox",
+ "//submodules/TelegramCore:TelegramCore",
+ "//submodules/SyncCore:SyncCore",
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/YuvConversion:YuvConversion",
+ "//submodules/StickerResources:StickerResources",
+ "//submodules/MediaResources:MediaResources",
+ "//submodules/Tuples:Tuples",
+ "//submodules/GZip:GZip",
+ "//submodules/rlottie:RLottieBinding",
+ "//submodules/lottie-ios:Lottie",
+ "//submodules/AppBundle:AppBundle",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/AnimationUI/Info.plist b/submodules/AnimationUI/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/AnimationUI/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/AppBundle/Info.plist b/submodules/AppBundle/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/AppBundle/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/AppLock/BUILD b/submodules/AppLock/BUILD
new file mode 100644
index 0000000000..ae89bbf200
--- /dev/null
+++ b/submodules/AppLock/BUILD
@@ -0,0 +1,25 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "AppLock",
+ module_name = "AppLock",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ "//submodules/Postbox:Postbox",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/MonotonicTime:MonotonicTime",
+ "//submodules/PasscodeUI:PasscodeUI",
+ "//submodules/TelegramUIPreferences:TelegramUIPreferences",
+ "//submodules/ImageBlur:ImageBlur",
+ "//submodules/AccountContext:AccountContext",
+ "//submodules/AppLockState:AppLockState",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/AppLockState/BUILD b/submodules/AppLockState/BUILD
new file mode 100644
index 0000000000..d87c6ecb7f
--- /dev/null
+++ b/submodules/AppLockState/BUILD
@@ -0,0 +1,15 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "AppLockState",
+ module_name = "AppLockState",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/MonotonicTime:MonotonicTime",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/ArchivedStickerPacksNotice/BUILD b/submodules/ArchivedStickerPacksNotice/BUILD
new file mode 100644
index 0000000000..296ed10c8d
--- /dev/null
+++ b/submodules/ArchivedStickerPacksNotice/BUILD
@@ -0,0 +1,29 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "ArchivedStickerPacksNotice",
+ module_name = "ArchivedStickerPacksNotice",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/Postbox:Postbox",
+ "//submodules/TelegramCore:TelegramCore",
+ "//submodules/SyncCore:SyncCore",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/AccountContext:AccountContext",
+ "//submodules/TelegramUIPreferences:TelegramUIPreferences",
+ "//submodules/StickerResources:StickerResources",
+ "//submodules/AlertUI:AlertUI",
+ "//submodules/PresentationDataUtils:PresentationDataUtils",
+ "//submodules/MergeLists:MergeLists",
+ "//submodules/ItemListUI:ItemListUI",
+ "//submodules/ItemListStickerPackItem:ItemListStickerPackItem",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/AuthTransferUI/BUILD b/submodules/AuthTransferUI/BUILD
new file mode 100644
index 0000000000..df8e758fa6
--- /dev/null
+++ b/submodules/AuthTransferUI/BUILD
@@ -0,0 +1,34 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "AuthTransferUI",
+ module_name = "AuthTransferUI",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/TelegramCore:TelegramCore",
+ "//submodules/SyncCore:SyncCore",
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/AccountContext:AccountContext",
+ "//submodules/QrCode:QrCode",
+ "//submodules/Camera:Camera",
+ "//submodules/GlassButtonNode:GlassButtonNode",
+ "//submodules/AlertUI:AlertUI",
+ "//submodules/AppBundle:AppBundle",
+ "//submodules/SolidRoundedButtonNode:SolidRoundedButtonNode",
+ "//submodules/OverlayStatusController:OverlayStatusController",
+ "//submodules/AnimatedStickerNode:AnimatedStickerNode",
+ "//submodules/Markdown:Markdown",
+ "//submodules/AnimationUI:AnimationUI",
+ "//submodules/PresentationDataUtils:PresentationDataUtils",
+ "//submodules/DeviceAccess:DeviceAccess",
+ "//submodules/UndoUI:UndoUI",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/AuthorizationUI/BUILD b/submodules/AuthorizationUI/BUILD
new file mode 100644
index 0000000000..9e15b1858d
--- /dev/null
+++ b/submodules/AuthorizationUI/BUILD
@@ -0,0 +1,21 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "AuthorizationUI",
+ module_name = "AuthorizationUI",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/TelegramCore:TelegramCore",
+ "//submodules/SyncCore:SyncCore",
+ "//submodules/Display:Display",
+ "//submodules/TextFormat:TextFormat",
+ "//submodules/Markdown:Markdown",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/AuthorizationUI/Info.plist b/submodules/AuthorizationUI/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/AuthorizationUI/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/AuthorizationUI/Sources/AuthorizationUI.h b/submodules/AuthorizationUI/Sources/AuthorizationUI.h
deleted file mode 100644
index ff41738826..0000000000
--- a/submodules/AuthorizationUI/Sources/AuthorizationUI.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// AuthorizationUI.h
-// AuthorizationUI
-//
-// Created by Peter on 8/17/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for AuthorizationUI.
-FOUNDATION_EXPORT double AuthorizationUIVersionNumber;
-
-//! Project version string for AuthorizationUI.
-FOUNDATION_EXPORT const unsigned char AuthorizationUIVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/AvatarNode/BUILD b/submodules/AvatarNode/BUILD
new file mode 100644
index 0000000000..df2c2c6837
--- /dev/null
+++ b/submodules/AvatarNode/BUILD
@@ -0,0 +1,22 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "AvatarNode",
+ module_name = "AvatarNode",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/TelegramCore:TelegramCore",
+ "//submodules/SyncCore:SyncCore",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/AnimationUI:AnimationUI",
+ "//submodules/AppBundle:AppBundle",
+ "//submodules/AccountContext:AccountContext",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/AvatarNode/Info.plist b/submodules/AvatarNode/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/AvatarNode/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/AvatarNode/Sources/AvatarNode.h b/submodules/AvatarNode/Sources/AvatarNode.h
deleted file mode 100644
index 999cedcf3d..0000000000
--- a/submodules/AvatarNode/Sources/AvatarNode.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// AvatarNode.h
-// AvatarNode
-//
-// Created by Peter on 8/4/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for AvatarNode.
-FOUNDATION_EXPORT double AvatarNodeVersionNumber;
-
-//! Project version string for AvatarNode.
-FOUNDATION_EXPORT const unsigned char AvatarNodeVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/BotPaymentsUI/BUILD b/submodules/BotPaymentsUI/BUILD
new file mode 100644
index 0000000000..f7213427bf
--- /dev/null
+++ b/submodules/BotPaymentsUI/BUILD
@@ -0,0 +1,29 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "BotPaymentsUI",
+ module_name = "BotPaymentsUI",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ "//submodules/Postbox:Postbox",
+ "//submodules/TelegramCore:TelegramCore",
+ "//submodules/SyncCore:SyncCore",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/LocalAuth:LocalAuth",
+ "//submodules/AccountContext:AccountContext",
+ "//submodules/ItemListUI:ItemListUI",
+ "//submodules/PasswordSetupUI:PasswordSetupUI",
+ "//submodules/PhotoResources:PhotoResources",
+ "//submodules/TelegramNotices:TelegramNotices",
+ "//submodules/Stripe:Stripe",
+ "//submodules/CountrySelectionUI:CountrySelectionUI",
+ "//submodules/AppBundle:AppBundle",
+ "//submodules/PresentationDataUtils:PresentationDataUtils",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/BotPaymentsUI/Info.plist b/submodules/BotPaymentsUI/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/BotPaymentsUI/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/BotPaymentsUI/Sources/BotPaymentsUI.h b/submodules/BotPaymentsUI/Sources/BotPaymentsUI.h
deleted file mode 100644
index 52ac46ad1b..0000000000
--- a/submodules/BotPaymentsUI/Sources/BotPaymentsUI.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// BotPaymentsUI.h
-// BotPaymentsUI
-//
-// Created by Peter on 8/12/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for BotPaymentsUI.
-FOUNDATION_EXPORT double BotPaymentsUIVersionNumber;
-
-//! Project version string for BotPaymentsUI.
-FOUNDATION_EXPORT const unsigned char BotPaymentsUIVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/BuildConfig/Config-AppStoreLLC.xcconfig b/submodules/BuildConfig/Config-AppStoreLLC.xcconfig
deleted file mode 100644
index d6449fc612..0000000000
--- a/submodules/BuildConfig/Config-AppStoreLLC.xcconfig
+++ /dev/null
@@ -1 +0,0 @@
-#include "../../Telegram-iOS/Config-AppStoreLLC.xcconfig"
diff --git a/submodules/BuildConfig/Config-Fork.xcconfig b/submodules/BuildConfig/Config-Fork.xcconfig
deleted file mode 100644
index efe0d66c5c..0000000000
--- a/submodules/BuildConfig/Config-Fork.xcconfig
+++ /dev/null
@@ -1 +0,0 @@
-#include "../../Telegram-iOS/Config-Fork.xcconfig"
diff --git a/submodules/BuildConfig/Config-Hockeyapp-Internal.xcconfig b/submodules/BuildConfig/Config-Hockeyapp-Internal.xcconfig
deleted file mode 100644
index 8b9e14fa83..0000000000
--- a/submodules/BuildConfig/Config-Hockeyapp-Internal.xcconfig
+++ /dev/null
@@ -1 +0,0 @@
-#include "../../../Telegram-iOS-Shared/Config/Hockeyapp-Internal/Config.xcconfig"
diff --git a/submodules/BuildConfig/Info.plist b/submodules/BuildConfig/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/BuildConfig/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/CallListUI/BUILD b/submodules/CallListUI/BUILD
new file mode 100644
index 0000000000..7828266e84
--- /dev/null
+++ b/submodules/CallListUI/BUILD
@@ -0,0 +1,30 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "CallListUI",
+ module_name = "CallListUI",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/Postbox:Postbox",
+ "//submodules/TelegramCore:TelegramCore",
+ "//submodules/SyncCore:SyncCore",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/TelegramUIPreferences:TelegramUIPreferences",
+ "//submodules/AccountContext:AccountContext",
+ "//submodules/ItemListUI:ItemListUI",
+ "//submodules/AvatarNode:AvatarNode",
+ "//submodules/TelegramStringFormatting:TelegramStringFormatting",
+ "//submodules/AlertUI:AlertUI",
+ "//submodules/PresentationDataUtils:PresentationDataUtils",
+ "//submodules/TelegramNotices:TelegramNotices",
+ "//submodules/MergeLists:MergeLists",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/CallListUI/Info.plist b/submodules/CallListUI/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/CallListUI/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/CallListUI/Sources/CallListUI.h b/submodules/CallListUI/Sources/CallListUI.h
deleted file mode 100644
index 0104a06195..0000000000
--- a/submodules/CallListUI/Sources/CallListUI.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// CallListUI.h
-// CallListUI
-//
-// Created by Peter on 8/13/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for CallListUI.
-FOUNDATION_EXPORT double CallListUIVersionNumber;
-
-//! Project version string for CallListUI.
-FOUNDATION_EXPORT const unsigned char CallListUIVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/Charts/BUILD b/submodules/Charts/BUILD
new file mode 100644
index 0000000000..802cbe7fa6
--- /dev/null
+++ b/submodules/Charts/BUILD
@@ -0,0 +1,31 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "Charts",
+ module_name = "Charts",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/Postbox:Postbox",
+ "//submodules/TelegramCore:TelegramCore",
+ "//submodules/SyncCore:SyncCore",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/TelegramUIPreferences:TelegramUIPreferences",
+ "//submodules/AccountContext:AccountContext",
+ "//submodules/ItemListUI:ItemListUI",
+ "//submodules/AvatarNode:AvatarNode",
+ "//submodules/TelegramStringFormatting:TelegramStringFormatting",
+ "//submodules/AlertUI:AlertUI",
+ "//submodules/PresentationDataUtils:PresentationDataUtils",
+ "//submodules/TelegramNotices:TelegramNotices",
+ "//submodules/MergeLists:MergeLists",
+ "//submodules/AppBundle:AppBundle",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/Charts/Info.plist b/submodules/Charts/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/Charts/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/Charts/Sources/Charts.h b/submodules/Charts/Sources/Charts.h
deleted file mode 100644
index 89573b3f16..0000000000
--- a/submodules/Charts/Sources/Charts.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// StatisticsUI.h
-// StatisticsUI
-//
-// Created by Peter on 8/13/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for StatisticsUI.
-FOUNDATION_EXPORT double StatisticsUIVersionNumber;
-
-//! Project version string for StatisticsUI.
-FOUNDATION_EXPORT const unsigned char StatisticsUIVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/ChatListSearchItemHeader/BUILD b/submodules/ChatListSearchItemHeader/BUILD
new file mode 100644
index 0000000000..edfacc2082
--- /dev/null
+++ b/submodules/ChatListSearchItemHeader/BUILD
@@ -0,0 +1,17 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "ChatListSearchItemHeader",
+ module_name = "ChatListSearchItemHeader",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/Display:Display",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/ListSectionHeaderNode:ListSectionHeaderNode",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/ChatListSearchItemHeader/Info.plist b/submodules/ChatListSearchItemHeader/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/ChatListSearchItemHeader/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/ChatListSearchItemHeader/Sources/ChatListSearchItemHeader.h b/submodules/ChatListSearchItemHeader/Sources/ChatListSearchItemHeader.h
deleted file mode 100644
index 4fbda00392..0000000000
--- a/submodules/ChatListSearchItemHeader/Sources/ChatListSearchItemHeader.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// ChatListSearchItemHeader.h
-// ChatListSearchItemHeader
-//
-// Created by Peter on 8/12/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for ChatListSearchItemHeader.
-FOUNDATION_EXPORT double ChatListSearchItemHeaderVersionNumber;
-
-//! Project version string for ChatListSearchItemHeader.
-FOUNDATION_EXPORT const unsigned char ChatListSearchItemHeaderVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/ChatListSearchItemNode/BUILD b/submodules/ChatListSearchItemNode/BUILD
new file mode 100644
index 0000000000..c57793411e
--- /dev/null
+++ b/submodules/ChatListSearchItemNode/BUILD
@@ -0,0 +1,20 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "ChatListSearchItemNode",
+ module_name = "ChatListSearchItemNode",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/Postbox:Postbox",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/SearchBarNode:SearchBarNode",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/ChatListSearchItemNode/Info.plist b/submodules/ChatListSearchItemNode/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/ChatListSearchItemNode/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/ChatListSearchItemNode/Sources/ChatListSearchItemNode.h b/submodules/ChatListSearchItemNode/Sources/ChatListSearchItemNode.h
deleted file mode 100644
index 74066c502e..0000000000
--- a/submodules/ChatListSearchItemNode/Sources/ChatListSearchItemNode.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// ChatListSearchItemNode.h
-// ChatListSearchItemNode
-//
-// Created by Peter on 8/13/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for ChatListSearchItemNode.
-FOUNDATION_EXPORT double ChatListSearchItemNodeVersionNumber;
-
-//! Project version string for ChatListSearchItemNode.
-FOUNDATION_EXPORT const unsigned char ChatListSearchItemNodeVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/ChatListSearchRecentPeersNode/BUILD b/submodules/ChatListSearchRecentPeersNode/BUILD
new file mode 100644
index 0000000000..659eec2f7a
--- /dev/null
+++ b/submodules/ChatListSearchRecentPeersNode/BUILD
@@ -0,0 +1,26 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "ChatListSearchRecentPeersNode",
+ module_name = "ChatListSearchRecentPeersNode",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/Postbox:Postbox",
+ "//submodules/TelegramCore:TelegramCore",
+ "//submodules/SyncCore:SyncCore",
+ "//submodules/ListSectionHeaderNode:ListSectionHeaderNode",
+ "//submodules/HorizontalPeerItem:HorizontalPeerItem",
+ "//submodules/MergeLists:MergeLists",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/ContextUI:ContextUI",
+ "//submodules/AccountContext:AccountContext",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/ChatListSearchRecentPeersNode/Info.plist b/submodules/ChatListSearchRecentPeersNode/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/ChatListSearchRecentPeersNode/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/ChatListSearchRecentPeersNode/Sources/ChatListSearchRecentPeersNode.h b/submodules/ChatListSearchRecentPeersNode/Sources/ChatListSearchRecentPeersNode.h
deleted file mode 100644
index 82bc0e1c74..0000000000
--- a/submodules/ChatListSearchRecentPeersNode/Sources/ChatListSearchRecentPeersNode.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// ChatListSearchRecentPeersNode.h
-// ChatListSearchRecentPeersNode
-//
-// Created by Peter on 8/5/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for ChatListSearchRecentPeersNode.
-FOUNDATION_EXPORT double ChatListSearchRecentPeersNodeVersionNumber;
-
-//! Project version string for ChatListSearchRecentPeersNode.
-FOUNDATION_EXPORT const unsigned char ChatListSearchRecentPeersNodeVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/ChatListUI/BUILD b/submodules/ChatListUI/BUILD
new file mode 100644
index 0000000000..2c48996391
--- /dev/null
+++ b/submodules/ChatListUI/BUILD
@@ -0,0 +1,51 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "ChatListUI",
+ module_name = "ChatListUI",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/Postbox:Postbox",
+ "//submodules/TelegramCore:TelegramCore",
+ "//submodules/SyncCore:SyncCore",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/TelegramUIPreferences:TelegramUIPreferences",
+ "//submodules/AccountContext:AccountContext",
+ "//submodules/TelegramBaseController:TelegramBaseController",
+ "//submodules/OverlayStatusController:OverlayStatusController",
+ "//submodules/AlertUI:AlertUI",
+ "//submodules/PresentationDataUtils:PresentationDataUtils",
+ "//submodules/UndoUI:UndoUI",
+ "//submodules/TelegramNotices:TelegramNotices",
+ "//submodules/SearchUI:SearchUI",
+ "//submodules/MergeLists:MergeLists",
+ "//submodules/ActivityIndicator:ActivityIndicator",
+ "//submodules/SearchBarNode:SearchBarNode",
+ "//submodules/ChatListSearchRecentPeersNode:ChatListSearchRecentPeersNode",
+ "//submodules/ChatListSearchItemNode:ChatListSearchItemNode",
+ "//submodules/ChatListSearchItemHeader:ChatListSearchItemHeader",
+ "//submodules/TemporaryCachedPeerDataManager:TemporaryCachedPeerDataManager",
+ "//submodules/PeerPresenceStatusManager:PeerPresenceStatusManager",
+ "//submodules/PeerOnlineMarkerNode:PeerOnlineMarkerNode",
+ "//submodules/LocalizedPeerData:LocalizedPeerData",
+ "//submodules/ChatTitleActivityNode:ChatTitleActivityNode",
+ "//submodules/DeleteChatPeerActionSheetItem:DeleteChatPeerActionSheetItem",
+ "//submodules/LanguageSuggestionUI:LanguageSuggestionUI",
+ "//submodules/ContactsPeerItem:ContactsPeerItem",
+ "//submodules/ContactListUI:ContactListUI",
+ "//submodules/PhotoResources:PhotoResources",
+ "//submodules/AppBundle:AppBundle",
+ "//submodules/ContextUI:ContextUI",
+ "//submodules/PhoneNumberFormat:PhoneNumberFormat",
+ "//submodules/TelegramIntents:TelegramIntents",
+ "//submodules/ItemListPeerActionItem:ItemListPeerActionItem",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/ChatListUI/Info.plist b/submodules/ChatListUI/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/ChatListUI/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/ChatListUI/Sources/ChatListUI.h b/submodules/ChatListUI/Sources/ChatListUI.h
deleted file mode 100644
index 4a3e46fa3c..0000000000
--- a/submodules/ChatListUI/Sources/ChatListUI.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// ChatListUI.h
-// ChatListUI
-//
-// Created by Peter on 8/13/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for ChatListUI.
-FOUNDATION_EXPORT double ChatListUIVersionNumber;
-
-//! Project version string for ChatListUI.
-FOUNDATION_EXPORT const unsigned char ChatListUIVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/ChatTitleActivityNode/BUILD b/submodules/ChatTitleActivityNode/BUILD
new file mode 100644
index 0000000000..c6d3c8966e
--- /dev/null
+++ b/submodules/ChatTitleActivityNode/BUILD
@@ -0,0 +1,17 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "ChatTitleActivityNode",
+ module_name = "ChatTitleActivityNode",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/LegacyComponents:LegacyComponents",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/ChatTitleActivityNode/Info.plist b/submodules/ChatTitleActivityNode/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/ChatTitleActivityNode/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/ChatTitleActivityNode/Sources/ChatTitleActivityNode.h b/submodules/ChatTitleActivityNode/Sources/ChatTitleActivityNode.h
deleted file mode 100644
index 0d41a1270b..0000000000
--- a/submodules/ChatTitleActivityNode/Sources/ChatTitleActivityNode.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// ChatTitleActivityNode.h
-// ChatTitleActivityNode
-//
-// Created by Peter on 8/13/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for ChatTitleActivityNode.
-FOUNDATION_EXPORT double ChatTitleActivityNodeVersionNumber;
-
-//! Project version string for ChatTitleActivityNode.
-FOUNDATION_EXPORT const unsigned char ChatTitleActivityNodeVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/CheckNode/BUCK b/submodules/CheckNode/BUCK
index 138e1ec664..78852663a9 100644
--- a/submodules/CheckNode/BUCK
+++ b/submodules/CheckNode/BUCK
@@ -4,14 +4,7 @@ static_library(
name = "CheckNode",
srcs = glob([
"Sources/**/*.swift",
- "Sources/*.m",
]),
- headers = glob([
- "Sources/*.h",
- ], exclude = ["Sources/TelegramPresentationData.h"]),
- exported_headers = glob([
- "Sources/*.h",
- ], exclude = ["Sources/TelegramPresentationData.h"]),
deps = [
"//submodules/AsyncDisplayKit:AsyncDisplayKit#shared",
"//submodules/Display:Display#shared",
diff --git a/submodules/CheckNode/BUILD b/submodules/CheckNode/BUILD
new file mode 100644
index 0000000000..fb56fea55e
--- /dev/null
+++ b/submodules/CheckNode/BUILD
@@ -0,0 +1,17 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "CheckNode",
+ module_name = "CheckNode",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/LegacyComponents:LegacyComponents",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/CheckNode/Info.plist b/submodules/CheckNode/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/CheckNode/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/CheckNode/Sources/CheckNode.h b/submodules/CheckNode/Sources/CheckNode.h
deleted file mode 100644
index 20e15c1826..0000000000
--- a/submodules/CheckNode/Sources/CheckNode.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// CheckNode.h
-// CheckNode
-//
-// Created by Peter on 8/1/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for CheckNode.
-FOUNDATION_EXPORT double CheckNodeVersionNumber;
-
-//! Project version string for CheckNode.
-FOUNDATION_EXPORT const unsigned char CheckNodeVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/ComposePollUI/BUILD b/submodules/ComposePollUI/BUILD
new file mode 100644
index 0000000000..df9b19b552
--- /dev/null
+++ b/submodules/ComposePollUI/BUILD
@@ -0,0 +1,24 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "ComposePollUI",
+ module_name = "ComposePollUI",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/Postbox:Postbox",
+ "//submodules/TelegramCore:TelegramCore",
+ "//submodules/SyncCore:SyncCore",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/ItemListUI:ItemListUI",
+ "//submodules/AccountContext:AccountContext",
+ "//submodules/AlertUI:AlertUI",
+ "//submodules/PresentationDataUtils:PresentationDataUtils",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/ComposePollUI/Info.plist b/submodules/ComposePollUI/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/ComposePollUI/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/ComposePollUI/Sources/ComposePollUI.h b/submodules/ComposePollUI/Sources/ComposePollUI.h
deleted file mode 100644
index 0bdf9b7117..0000000000
--- a/submodules/ComposePollUI/Sources/ComposePollUI.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// ComposePollUI.h
-// ComposePollUI
-//
-// Created by Peter on 8/10/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for ComposePollUI.
-FOUNDATION_EXPORT double ComposePollUIVersionNumber;
-
-//! Project version string for ComposePollUI.
-FOUNDATION_EXPORT const unsigned char ComposePollUIVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/ContactListUI/BUILD b/submodules/ContactListUI/BUILD
new file mode 100644
index 0000000000..9222087c53
--- /dev/null
+++ b/submodules/ContactListUI/BUILD
@@ -0,0 +1,38 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "ContactListUI",
+ module_name = "ContactListUI",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/Postbox:Postbox",
+ "//submodules/TelegramCore:TelegramCore",
+ "//submodules/SyncCore:SyncCore",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/AccountContext:AccountContext",
+ "//submodules/TelegramUIPreferences:TelegramUIPreferences",
+ "//submodules/MergeLists:MergeLists",
+ "//submodules/SearchUI:SearchUI",
+ "//submodules/ChatListSearchItemHeader:ChatListSearchItemHeader",
+ "//submodules/ItemListPeerItem:ItemListPeerItem",
+ "//submodules/ContactsPeerItem:ContactsPeerItem",
+ "//submodules/ChatListSearchItemNode:ChatListSearchItemNode",
+ "//submodules/TelegramPermissionsUI:TelegramPermissionsUI",
+ "//submodules/TelegramNotices:TelegramNotices",
+ "//submodules/AlertUI:AlertUI",
+ "//submodules/PresentationDataUtils:PresentationDataUtils",
+ "//submodules/ShareController:ShareController",
+ "//submodules/AppBundle:AppBundle",
+ "//submodules/OverlayStatusController:OverlayStatusController",
+ "//submodules/PhoneNumberFormat:PhoneNumberFormat",
+ "//submodules/SolidRoundedButtonNode:SolidRoundedButtonNode",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/ContactListUI/Info.plist b/submodules/ContactListUI/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/ContactListUI/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/ContactListUI/Sources/ContactListUI.h b/submodules/ContactListUI/Sources/ContactListUI.h
deleted file mode 100644
index 4d1cb36e9b..0000000000
--- a/submodules/ContactListUI/Sources/ContactListUI.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// ContactListUI.h
-// ContactListUI
-//
-// Created by Peter on 8/12/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for ContactListUI.
-FOUNDATION_EXPORT double ContactListUIVersionNumber;
-
-//! Project version string for ContactListUI.
-FOUNDATION_EXPORT const unsigned char ContactListUIVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/ContactsPeerItem/BUILD b/submodules/ContactsPeerItem/BUILD
new file mode 100644
index 0000000000..1af726ec27
--- /dev/null
+++ b/submodules/ContactsPeerItem/BUILD
@@ -0,0 +1,32 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "ContactsPeerItem",
+ module_name = "ContactsPeerItem",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/Postbox:Postbox",
+ "//submodules/TelegramCore:TelegramCore",
+ "//submodules/SyncCore:SyncCore",
+ "//submodules/AccountContext:AccountContext",
+ "//submodules/AvatarNode:AvatarNode",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/CheckNode:CheckNode",
+ "//submodules/TelegramStringFormatting:TelegramStringFormatting",
+ "//submodules/ItemListPeerItem:ItemListPeerItem",
+ "//submodules/PeerPresenceStatusManager:PeerPresenceStatusManager",
+ "//submodules/ItemListUI:ItemListUI",
+ "//submodules/TelegramUIPreferences:TelegramUIPreferences",
+ "//submodules/ListSectionHeaderNode:ListSectionHeaderNode",
+ "//submodules/ContextUI:ContextUI",
+ "//submodules/PresentationDataUtils:PresentationDataUtils",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/ContactsPeerItem/Info.plist b/submodules/ContactsPeerItem/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/ContactsPeerItem/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/ContactsPeerItem/Sources/ContactsPeerItem.h b/submodules/ContactsPeerItem/Sources/ContactsPeerItem.h
deleted file mode 100644
index 9addb32e87..0000000000
--- a/submodules/ContactsPeerItem/Sources/ContactsPeerItem.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// ContactsPeerItem.h
-// ContactsPeerItem
-//
-// Created by Peter on 8/13/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for ContactsPeerItem.
-FOUNDATION_EXPORT double ContactsPeerItemVersionNumber;
-
-//! Project version string for ContactsPeerItem.
-FOUNDATION_EXPORT const unsigned char ContactsPeerItemVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/ContextUI/BUILD b/submodules/ContextUI/BUILD
new file mode 100644
index 0000000000..f8157be861
--- /dev/null
+++ b/submodules/ContextUI/BUILD
@@ -0,0 +1,21 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "ContextUI",
+ module_name = "ContextUI",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/TextSelectionNode:TextSelectionNode",
+ "//submodules/ReactionSelectionNode:ReactionSelectionNode",
+ "//submodules/AppBundle:AppBundle",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/ContextUI/Info.plist b/submodules/ContextUI/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/ContextUI/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/ContextUI/Sources/ContextUI.h b/submodules/ContextUI/Sources/ContextUI.h
deleted file mode 100644
index 8ba61f93ed..0000000000
--- a/submodules/ContextUI/Sources/ContextUI.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// ContextUI.h
-// ContextUI
-//
-// Created by Peter on 8/5/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for ContextUI.
-FOUNDATION_EXPORT double ContextUIVersionNumber;
-
-//! Project version string for ContextUI.
-FOUNDATION_EXPORT const unsigned char ContextUIVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/CounterContollerTitleView/BUILD b/submodules/CounterContollerTitleView/BUILD
new file mode 100644
index 0000000000..0462915bd5
--- /dev/null
+++ b/submodules/CounterContollerTitleView/BUILD
@@ -0,0 +1,17 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "CounterContollerTitleView",
+ module_name = "CounterContollerTitleView",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/CounterContollerTitleView/Info.plist b/submodules/CounterContollerTitleView/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/CounterContollerTitleView/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/CounterContollerTitleView/Sources/CounterContollerTitleView.h b/submodules/CounterContollerTitleView/Sources/CounterContollerTitleView.h
deleted file mode 100644
index c0ddce18a5..0000000000
--- a/submodules/CounterContollerTitleView/Sources/CounterContollerTitleView.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// CounterContollerTitleView.h
-// CounterContollerTitleView
-//
-// Created by Peter on 8/17/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for CounterContollerTitleView.
-FOUNDATION_EXPORT double CounterContollerTitleViewVersionNumber;
-
-//! Project version string for CounterContollerTitleView.
-FOUNDATION_EXPORT const unsigned char CounterContollerTitleViewVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/CountrySelectionUI/BUILD b/submodules/CountrySelectionUI/BUILD
new file mode 100644
index 0000000000..7fcc859b8b
--- /dev/null
+++ b/submodules/CountrySelectionUI/BUILD
@@ -0,0 +1,21 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "CountrySelectionUI",
+ module_name = "CountrySelectionUI",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/TelegramStringFormatting:TelegramStringFormatting",
+ "//submodules/SearchBarNode:SearchBarNode",
+ "//submodules/AppBundle:AppBundle",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/CountrySelectionUI/Info.plist b/submodules/CountrySelectionUI/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/CountrySelectionUI/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/CountrySelectionUI/Sources/CountrySelectionUI.h b/submodules/CountrySelectionUI/Sources/CountrySelectionUI.h
deleted file mode 100644
index 3505c8a4d6..0000000000
--- a/submodules/CountrySelectionUI/Sources/CountrySelectionUI.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// CountrySelectionUI.h
-// CountrySelectionUI
-//
-// Created by Peter on 8/11/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for CountrySelectionUI.
-FOUNDATION_EXPORT double CountrySelectionUIVersionNumber;
-
-//! Project version string for CountrySelectionUI.
-FOUNDATION_EXPORT const unsigned char CountrySelectionUIVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/DateSelectionUI/BUILD b/submodules/DateSelectionUI/BUILD
new file mode 100644
index 0000000000..a34f436ac4
--- /dev/null
+++ b/submodules/DateSelectionUI/BUILD
@@ -0,0 +1,20 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "DateSelectionUI",
+ module_name = "DateSelectionUI",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/AccountContext:AccountContext",
+ "//submodules/TelegramStringFormatting:TelegramStringFormatting",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/DateSelectionUI/Info.plist b/submodules/DateSelectionUI/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/DateSelectionUI/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/DateSelectionUI/Sources/DateSelectionUI.h b/submodules/DateSelectionUI/Sources/DateSelectionUI.h
deleted file mode 100644
index f52f7827f6..0000000000
--- a/submodules/DateSelectionUI/Sources/DateSelectionUI.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// DateSelectionUI.h
-// DateSelectionUI
-//
-// Created by Peter on 8/12/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for DateSelectionUI.
-FOUNDATION_EXPORT double DateSelectionUIVersionNumber;
-
-//! Project version string for DateSelectionUI.
-FOUNDATION_EXPORT const unsigned char DateSelectionUIVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/DeleteChatPeerActionSheetItem/BUILD b/submodules/DeleteChatPeerActionSheetItem/BUILD
new file mode 100644
index 0000000000..c8da24e78c
--- /dev/null
+++ b/submodules/DeleteChatPeerActionSheetItem/BUILD
@@ -0,0 +1,22 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "DeleteChatPeerActionSheetItem",
+ module_name = "DeleteChatPeerActionSheetItem",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/Postbox:Postbox",
+ "//submodules/TelegramCore:TelegramCore",
+ "//submodules/SyncCore:SyncCore",
+ "//submodules/AccountContext:AccountContext",
+ "//submodules/AvatarNode:AvatarNode",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/DeleteChatPeerActionSheetItem/Info.plist b/submodules/DeleteChatPeerActionSheetItem/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/DeleteChatPeerActionSheetItem/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/DeleteChatPeerActionSheetItem/Sources/DeleteChatPeerActionSheetItem.h b/submodules/DeleteChatPeerActionSheetItem/Sources/DeleteChatPeerActionSheetItem.h
deleted file mode 100644
index eff87f3b1f..0000000000
--- a/submodules/DeleteChatPeerActionSheetItem/Sources/DeleteChatPeerActionSheetItem.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// DeleteChatPeerActionSheetItem.h
-// DeleteChatPeerActionSheetItem
-//
-// Created by Peter on 8/13/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for DeleteChatPeerActionSheetItem.
-FOUNDATION_EXPORT double DeleteChatPeerActionSheetItemVersionNumber;
-
-//! Project version string for DeleteChatPeerActionSheetItem.
-FOUNDATION_EXPORT const unsigned char DeleteChatPeerActionSheetItemVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/DeviceAccess/BUILD b/submodules/DeviceAccess/BUILD
new file mode 100644
index 0000000000..1bfb8443f5
--- /dev/null
+++ b/submodules/DeviceAccess/BUILD
@@ -0,0 +1,21 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "DeviceAccess",
+ module_name = "DeviceAccess",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/TelegramCore:TelegramCore",
+ "//submodules/SyncCore:SyncCore",
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ "//submodules/Display:Display",
+ "//submodules/AccountContext:AccountContext",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/LegacyComponents:LegacyComponents",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/DeviceAccess/Info.plist b/submodules/DeviceAccess/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/DeviceAccess/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/DeviceAccess/Sources/DeviceAccess.h b/submodules/DeviceAccess/Sources/DeviceAccess.h
deleted file mode 100644
index bfb7ce3a32..0000000000
--- a/submodules/DeviceAccess/Sources/DeviceAccess.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// DeviceAccess.h
-// DeviceAccess
-//
-// Created by Peter on 6/13/19.
-// Copyright © 2019 Telegram LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for DeviceAccess.
-FOUNDATION_EXPORT double DeviceAccessVersionNumber;
-
-//! Project version string for DeviceAccess.
-FOUNDATION_EXPORT const unsigned char DeviceAccessVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/DeviceLocationManager/BUILD b/submodules/DeviceLocationManager/BUILD
new file mode 100644
index 0000000000..583f811cfb
--- /dev/null
+++ b/submodules/DeviceLocationManager/BUILD
@@ -0,0 +1,15 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "DeviceLocationManager",
+ module_name = "DeviceLocationManager",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/DeviceProximity/BUCK b/submodules/DeviceProximity/BUCK
index 8d7d99755b..94392f0568 100644
--- a/submodules/DeviceProximity/BUCK
+++ b/submodules/DeviceProximity/BUCK
@@ -7,10 +7,10 @@ static_library(
]),
headers = glob([
"Sources/*.h",
- ], exclude = ["Sources/DeviceProximity.h"]),
+ ]),
exported_headers = glob([
- "Sources/*.h",
- ], exclude = ["Sources/DeviceProximity.h"]),
+ "PublicHeaders/**/*.h",
+ ]),
frameworks = [
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
"$SDKROOT/System/Library/Frameworks/UIKit.framework",
diff --git a/submodules/DeviceProximity/BUILD b/submodules/DeviceProximity/BUILD
new file mode 100644
index 0000000000..243c604641
--- /dev/null
+++ b/submodules/DeviceProximity/BUILD
@@ -0,0 +1,22 @@
+
+objc_library(
+ name = "DeviceProximity",
+ enable_modules = True,
+ module_name = "DeviceProximity",
+ srcs = glob([
+ "Sources/*.m",
+ ]),
+ hdrs = glob([
+ "PublicHeaders/**/*.h",
+ ]),
+ includes = [
+ "PublicHeaders",
+ ],
+ sdk_frameworks = [
+ "Foundation",
+ "UIKit",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/DeviceProximity/Info.plist b/submodules/DeviceProximity/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/DeviceProximity/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/DeviceProximity/PublicHeaders/DeviceProximity/DeviceProximity.h b/submodules/DeviceProximity/PublicHeaders/DeviceProximity/DeviceProximity.h
new file mode 100644
index 0000000000..be14dd0c27
--- /dev/null
+++ b/submodules/DeviceProximity/PublicHeaders/DeviceProximity/DeviceProximity.h
@@ -0,0 +1,5 @@
+#import
+
+#import
+
+
diff --git a/submodules/DeviceProximity/Sources/DeviceProximityManager.h b/submodules/DeviceProximity/PublicHeaders/DeviceProximity/DeviceProximityManager.h
similarity index 100%
rename from submodules/DeviceProximity/Sources/DeviceProximityManager.h
rename to submodules/DeviceProximity/PublicHeaders/DeviceProximity/DeviceProximityManager.h
diff --git a/submodules/DeviceProximity/Sources/DeviceProximity.h b/submodules/DeviceProximity/Sources/DeviceProximity.h
deleted file mode 100644
index 449c242823..0000000000
--- a/submodules/DeviceProximity/Sources/DeviceProximity.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#import
-
-//! Project version number for DeviceProximity.
-FOUNDATION_EXPORT double DeviceProximityVersionNumber;
-
-//! Project version string for DeviceProximity.
-FOUNDATION_EXPORT const unsigned char DeviceProximityVersionString[];
-
-#import
-
-
diff --git a/submodules/DeviceProximity/Sources/DeviceProximityManager.m b/submodules/DeviceProximity/Sources/DeviceProximityManager.m
index 3061832dcf..94ef975a8d 100644
--- a/submodules/DeviceProximity/Sources/DeviceProximityManager.m
+++ b/submodules/DeviceProximity/Sources/DeviceProximityManager.m
@@ -1,4 +1,4 @@
-#import "DeviceProximityManager.h"
+#import
#import
diff --git a/submodules/DirectionalPanGesture/BUILD b/submodules/DirectionalPanGesture/BUILD
new file mode 100644
index 0000000000..9e62d95bb1
--- /dev/null
+++ b/submodules/DirectionalPanGesture/BUILD
@@ -0,0 +1,12 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "DirectionalPanGesture",
+ module_name = "DirectionalPanGesture",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/DirectionalPanGesture/Info.plist b/submodules/DirectionalPanGesture/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/DirectionalPanGesture/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/DirectionalPanGesture/Sources/DirectionalPanGesture.h b/submodules/DirectionalPanGesture/Sources/DirectionalPanGesture.h
deleted file mode 100644
index 25ac53274e..0000000000
--- a/submodules/DirectionalPanGesture/Sources/DirectionalPanGesture.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// DirectionalPanGesture.h
-// DirectionalPanGesture
-//
-// Created by Peter on 8/10/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for DirectionalPanGesture.
-FOUNDATION_EXPORT double DirectionalPanGestureVersionNumber;
-
-//! Project version string for DirectionalPanGesture.
-FOUNDATION_EXPORT const unsigned char DirectionalPanGestureVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/Emoji/BUILD b/submodules/Emoji/BUILD
new file mode 100644
index 0000000000..9b5e934bcf
--- /dev/null
+++ b/submodules/Emoji/BUILD
@@ -0,0 +1,12 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "Emoji",
+ module_name = "Emoji",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/Emoji/Info.plist b/submodules/Emoji/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/Emoji/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/Emoji/Sources/Emoji.h b/submodules/Emoji/Sources/Emoji.h
deleted file mode 100644
index 5e70ebcc00..0000000000
--- a/submodules/Emoji/Sources/Emoji.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// Emoji.h
-// Emoji
-//
-// Created by Peter on 8/15/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for Emoji.
-FOUNDATION_EXPORT double EmojiVersionNumber;
-
-//! Project version string for Emoji.
-FOUNDATION_EXPORT const unsigned char EmojiVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/EncryptionKeyVisualization/Info.plist b/submodules/EncryptionKeyVisualization/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/EncryptionKeyVisualization/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/FastBlur/BUCK b/submodules/FastBlur/BUCK
new file mode 100644
index 0000000000..5e2cc7b602
--- /dev/null
+++ b/submodules/FastBlur/BUCK
@@ -0,0 +1,19 @@
+load("//Config:buck_rule_macros.bzl", "static_library")
+
+static_library(
+ name = "FastBlur",
+ srcs = glob([
+ "Sources/*.m",
+ ]),
+ headers = glob([
+ "Sources/*.h",
+ ]),
+ exported_headers = glob([
+ "PublicHeaders/**/*.h",
+ ]),
+ deps = [
+ ],
+ frameworks = [
+ "$SDKROOT/System/Library/Frameworks/Foundation.framework",
+ ],
+)
diff --git a/submodules/FastBlur/BUILD b/submodules/FastBlur/BUILD
new file mode 100644
index 0000000000..839f88d8c1
--- /dev/null
+++ b/submodules/FastBlur/BUILD
@@ -0,0 +1,23 @@
+
+objc_library(
+ name = "FastBlur",
+ enable_modules = True,
+ module_name = "FastBlur",
+ srcs = glob([
+ "Sources/*.m",
+ ]),
+ hdrs = glob([
+ "PublicHeaders/**/*.h",
+ ]),
+ includes = [
+ "PublicHeaders",
+ ],
+ sdk_frameworks = [
+ "Foundation",
+ "UIKit",
+ "Accelerate",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/ImageBlur/Sources/ApplyScreenshotEffect.h b/submodules/FastBlur/PublicHeaders/FastBlur/ApplyScreenshotEffect.h
similarity index 100%
rename from submodules/ImageBlur/Sources/ApplyScreenshotEffect.h
rename to submodules/FastBlur/PublicHeaders/FastBlur/ApplyScreenshotEffect.h
diff --git a/submodules/ImageBlur/Sources/FastBlur.h b/submodules/FastBlur/PublicHeaders/FastBlur/FastBlur.h
similarity index 100%
rename from submodules/ImageBlur/Sources/FastBlur.h
rename to submodules/FastBlur/PublicHeaders/FastBlur/FastBlur.h
diff --git a/submodules/ImageBlur/Sources/ImageBlur.h b/submodules/FastBlur/PublicHeaders/FastBlur/ImageBlur.h
similarity index 100%
rename from submodules/ImageBlur/Sources/ImageBlur.h
rename to submodules/FastBlur/PublicHeaders/FastBlur/ImageBlur.h
diff --git a/submodules/ImageBlur/Sources/ApplyScreenshotEffect.m b/submodules/FastBlur/Sources/ApplyScreenshotEffect.m
similarity index 99%
rename from submodules/ImageBlur/Sources/ApplyScreenshotEffect.m
rename to submodules/FastBlur/Sources/ApplyScreenshotEffect.m
index 8cfd8109b5..6ab0275e44 100644
--- a/submodules/ImageBlur/Sources/ApplyScreenshotEffect.m
+++ b/submodules/FastBlur/Sources/ApplyScreenshotEffect.m
@@ -1,4 +1,4 @@
-#import "ApplyScreenshotEffect.h"
+#import
#import
#import
diff --git a/submodules/ImageBlur/Sources/FastBlur.m b/submodules/FastBlur/Sources/FastBlur.m
similarity index 99%
rename from submodules/ImageBlur/Sources/FastBlur.m
rename to submodules/FastBlur/Sources/FastBlur.m
index 106e50b545..2c7849384f 100644
--- a/submodules/ImageBlur/Sources/FastBlur.m
+++ b/submodules/FastBlur/Sources/FastBlur.m
@@ -1,4 +1,4 @@
-#import "FastBlur.h"
+#import
#import
diff --git a/submodules/GZip/Info.plist b/submodules/GZip/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/GZip/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/GalleryUI/BUILD b/submodules/GalleryUI/BUILD
new file mode 100644
index 0000000000..ad5f85f26d
--- /dev/null
+++ b/submodules/GalleryUI/BUILD
@@ -0,0 +1,34 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "GalleryUI",
+ module_name = "GalleryUI",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/Postbox:Postbox",
+ "//submodules/TelegramCore:TelegramCore",
+ "//submodules/SyncCore:SyncCore",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/TextFormat:TextFormat",
+ "//submodules/AccountContext:AccountContext",
+ "//submodules/TelegramUniversalVideoContent:TelegramUniversalVideoContent",
+ "//submodules/WebsiteType:WebsiteType",
+ "//submodules/ScreenCaptureDetection:ScreenCaptureDetection",
+ "//submodules/OpenInExternalAppUI:OpenInExternalAppUI",
+ "//submodules/ShareController:ShareController",
+ "//submodules/SwipeToDismissGesture:SwipeToDismissGesture",
+ "//submodules/CheckNode:CheckNode",
+ "//submodules/AppBundle:AppBundle",
+ "//submodules/StickerPackPreviewUI:StickerPackPreviewUI",
+ "//submodules/OverlayStatusController:OverlayStatusController",
+ "//submodules/PresentationDataUtils:PresentationDataUtils",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/GalleryUI/Info.plist b/submodules/GalleryUI/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/GalleryUI/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/GalleryUI/Sources/GalleryUI.h b/submodules/GalleryUI/Sources/GalleryUI.h
deleted file mode 100644
index 96745aa2f0..0000000000
--- a/submodules/GalleryUI/Sources/GalleryUI.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// GalleryUI.h
-// GalleryUI
-//
-// Created by Peter on 8/11/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for GalleryUI.
-FOUNDATION_EXPORT double GalleryUIVersionNumber;
-
-//! Project version string for GalleryUI.
-FOUNDATION_EXPORT const unsigned char GalleryUIVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/GameUI/BUILD b/submodules/GameUI/BUILD
new file mode 100644
index 0000000000..95d7034d1b
--- /dev/null
+++ b/submodules/GameUI/BUILD
@@ -0,0 +1,23 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "GameUI",
+ module_name = "GameUI",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/Postbox:Postbox",
+ "//submodules/TelegramCore:TelegramCore",
+ "//submodules/SyncCore:SyncCore",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/AccountContext:AccountContext",
+ "//submodules/ShareController:ShareController",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/GameUI/Info.plist b/submodules/GameUI/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/GameUI/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/GameUI/Sources/GameUI.h b/submodules/GameUI/Sources/GameUI.h
deleted file mode 100644
index 18da9568d0..0000000000
--- a/submodules/GameUI/Sources/GameUI.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// GameUI.h
-// GameUI
-//
-// Created by Peter on 8/11/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for GameUI.
-FOUNDATION_EXPORT double GameUIVersionNumber;
-
-//! Project version string for GameUI.
-FOUNDATION_EXPORT const unsigned char GameUIVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/Geocoding/BUILD b/submodules/Geocoding/BUILD
new file mode 100644
index 0000000000..d03fe14734
--- /dev/null
+++ b/submodules/Geocoding/BUILD
@@ -0,0 +1,15 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "Geocoding",
+ module_name = "Geocoding",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/Geocoding/Info.plist b/submodules/Geocoding/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/Geocoding/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/Geocoding/Sources/Geocoding.h b/submodules/Geocoding/Sources/Geocoding.h
deleted file mode 100644
index d49cdcfd42..0000000000
--- a/submodules/Geocoding/Sources/Geocoding.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// Geocoding.h
-// Geocoding
-//
-// Created by Peter on 8/15/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for Geocoding.
-FOUNDATION_EXPORT double GeocodingVersionNumber;
-
-//! Project version string for Geocoding.
-FOUNDATION_EXPORT const unsigned char GeocodingVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/GridMessageSelectionNode/BUILD b/submodules/GridMessageSelectionNode/BUILD
new file mode 100644
index 0000000000..1d24313555
--- /dev/null
+++ b/submodules/GridMessageSelectionNode/BUILD
@@ -0,0 +1,18 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "GridMessageSelectionNode",
+ module_name = "GridMessageSelectionNode",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/CheckNode:CheckNode",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/GridMessageSelectionNode/Info.plist b/submodules/GridMessageSelectionNode/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/GridMessageSelectionNode/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/GridMessageSelectionNode/Sources/GridMessageSelectionNode.h b/submodules/GridMessageSelectionNode/Sources/GridMessageSelectionNode.h
deleted file mode 100644
index 7bc2834b05..0000000000
--- a/submodules/GridMessageSelectionNode/Sources/GridMessageSelectionNode.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// GridMessageSelectionNode.h
-// GridMessageSelectionNode
-//
-// Created by Peter on 8/17/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for GridMessageSelectionNode.
-FOUNDATION_EXPORT double GridMessageSelectionNodeVersionNumber;
-
-//! Project version string for GridMessageSelectionNode.
-FOUNDATION_EXPORT const unsigned char GridMessageSelectionNodeVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/HashtagSearchUI/BUILD b/submodules/HashtagSearchUI/BUILD
new file mode 100644
index 0000000000..0384121b97
--- /dev/null
+++ b/submodules/HashtagSearchUI/BUILD
@@ -0,0 +1,25 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "HashtagSearchUI",
+ module_name = "HashtagSearchUI",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
+ "//submodules/AsyncDisplayKit:AsyncDisplayKit",
+ "//submodules/Display:Display",
+ "//submodules/Postbox:Postbox",
+ "//submodules/TelegramCore:TelegramCore",
+ "//submodules/SyncCore:SyncCore",
+ "//submodules/TelegramPresentationData:TelegramPresentationData",
+ "//submodules/AccountContext:AccountContext",
+ "//submodules/TelegramBaseController:TelegramBaseController",
+ "//submodules/ChatListUI:ChatListUI",
+ "//submodules/SegmentedControlNode:SegmentedControlNode",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/HashtagSearchUI/Info.plist b/submodules/HashtagSearchUI/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/HashtagSearchUI/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/HashtagSearchUI/Sources/HashtagSearchUI.h b/submodules/HashtagSearchUI/Sources/HashtagSearchUI.h
deleted file mode 100644
index c5be233f9a..0000000000
--- a/submodules/HashtagSearchUI/Sources/HashtagSearchUI.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// HashtagSearchUI.h
-// HashtagSearchUI
-//
-// Created by Peter on 8/14/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for HashtagSearchUI.
-FOUNDATION_EXPORT double HashtagSearchUIVersionNumber;
-
-//! Project version string for HashtagSearchUI.
-FOUNDATION_EXPORT const unsigned char HashtagSearchUIVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/HexColor/BUILD b/submodules/HexColor/BUILD
new file mode 100644
index 0000000000..faf074d046
--- /dev/null
+++ b/submodules/HexColor/BUILD
@@ -0,0 +1,15 @@
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+swift_library(
+ name = "HexColor",
+ module_name = "HexColor",
+ srcs = glob([
+ "Sources/**/*.swift",
+ ]),
+ deps = [
+ "//submodules/TextFormat:TextFormat",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/submodules/HexColor/Info.plist b/submodules/HexColor/Info.plist
deleted file mode 100644
index e1fe4cfb7b..0000000000
--- a/submodules/HexColor/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/submodules/HexColor/Sources/HexColor.h b/submodules/HexColor/Sources/HexColor.h
deleted file mode 100644
index add4edae03..0000000000
--- a/submodules/HexColor/Sources/HexColor.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// HexColor.h
-// HexColor
-//
-// Created by Peter on 8/17/19.
-// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
-//
-
-#import
-
-//! Project version number for HexColor.
-FOUNDATION_EXPORT double HexColorVersionNumber;
-
-//! Project version string for HexColor.
-FOUNDATION_EXPORT const unsigned char HexColorVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/submodules/HockeySDK-iOS/.gitattributes b/submodules/HockeySDK-iOS/.gitattributes
deleted file mode 100644
index 854d90babf..0000000000
--- a/submodules/HockeySDK-iOS/.gitattributes
+++ /dev/null
@@ -1 +0,0 @@
-*.pbxproj merge=union
\ No newline at end of file
diff --git a/submodules/HockeySDK-iOS/.gitignore b/submodules/HockeySDK-iOS/.gitignore
deleted file mode 100644
index db0ab09450..0000000000
--- a/submodules/HockeySDK-iOS/.gitignore
+++ /dev/null
@@ -1,25 +0,0 @@
-fastlane/README.md
-fastlane/report.xml
-fastlane/test_output/*
-*.pbxuser
-!default.pbxuser
-*.mode1v3
-!default.mode1v3
-*.mode2v3
-!default.mode2v3
-*.perspectivev3
-!default.perspectivev3
-xcuserdata
-*.xccheckout
-*.xcscmblueprint
-*.moved-aside
-DerivedData
-*.hmap
-*.ipa
-*.xcuserstate
-.DS_Store
-*.dSYM
-*.dSYM.zip
-*.ipa
-*/xcuserdata/*
-HockeySDK-iOS.xcodeproj/*
diff --git a/submodules/HockeySDK-iOS/BUCK b/submodules/HockeySDK-iOS/BUCK
deleted file mode 100644
index 582118aa4b..0000000000
--- a/submodules/HockeySDK-iOS/BUCK
+++ /dev/null
@@ -1,60 +0,0 @@
-load("//Config:buck_rule_macros.bzl", "static_library")
-
-prebuilt_apple_framework(
- name = "CrashReporter",
- framework = "Vendor/CrashReporter.framework",
- preferred_linkage = "static",
-)
-
-static_library(
- name = "HockeySDK",
- srcs = glob([
- "Classes/*.m",
- "Classes/*.mm",
- ]),
- headers = glob([
- "Classes/*.h",
- ]),
- exported_headers = [
- "Classes/HockeySDKFeatureConfig.h",
- "Classes/HockeySDKEnums.h",
- "Classes/HockeySDKNullability.h",
- "Classes/BITAlertAction.h",
-
- "Classes/BITHockeyManager.h",
-
- "Classes/BITHockeyAttachment.h",
-
- "Classes/BITHockeyBaseManager.h",
- "Classes/BITCrashManager.h",
- "Classes/BITCrashAttachment.h",
- "Classes/BITCrashManagerDelegate.h",
- "Classes/BITCrashDetails.h",
- "Classes/BITCrashMetaData.h",
-
- "Classes/BITAuthenticator.h",
-
- "Classes/BITUpdateManager.h",
- "Classes/BITUpdateManagerDelegate.h",
- "Classes/BITUpdateViewController.h",
- "Classes/BITHockeyBaseViewController.h",
- "Classes/BITHockeyManagerDelegate.h",
- ],
- compiler_flags = [
- '-DBITHOCKEY_VERSION=@\"5.1.2\"',
- '-DBITHOCKEY_C_VERSION="5.1.2"',
- '-DBITHOCKEY_C_BUILD="108"',
- "-DHOCKEYSDK_FEATURE_CRASH_REPORTER=1",
- "-DHOCKEYSDK_FEATURE_UPDATES=1",
- "-DHOCKEYSDK_FEATURE_FEEDBACK=0",
- "-DHOCKEYSDK_FEATURE_AUTHENTICATOR=1",
- "-DHOCKEYSDK_FEATURE_METRICS=0",
- ],
- deps = [
- ":CrashReporter",
- ],
- frameworks = [
- "$SDKROOT/System/Library/Frameworks/Foundation.framework",
- "$SDKROOT/System/Library/Frameworks/UIKit.framework",
- ],
-)
diff --git a/submodules/HockeySDK-iOS/Classes/BITActivityIndicatorButton.h b/submodules/HockeySDK-iOS/Classes/BITActivityIndicatorButton.h
deleted file mode 100644
index 2c633222c9..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITActivityIndicatorButton.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import
-
-@interface BITActivityIndicatorButton : UIButton
-
-- (void)setShowsActivityIndicator:(BOOL)showsIndicator;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITActivityIndicatorButton.m b/submodules/HockeySDK-iOS/Classes/BITActivityIndicatorButton.m
deleted file mode 100644
index 6a731bb434..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITActivityIndicatorButton.m
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_FEEDBACK
-
-#import "BITActivityIndicatorButton.h"
-
-@interface BITActivityIndicatorButton()
-
-@property (nonatomic, strong) UIActivityIndicatorView *indicator;
-@property (nonatomic) BOOL indicatorVisible;
-
-@end
-
-@implementation BITActivityIndicatorButton
-
-- (void)setShowsActivityIndicator:(BOOL)showsIndicator {
- if (self.indicatorVisible == showsIndicator){
- return;
- }
-
- if (!self.indicator){
- self.indicator = [[UIActivityIndicatorView alloc] initWithFrame:self.bounds];
- [self addSubview:self.indicator];
- [self.indicator setColor:[UIColor blackColor]];
- }
-
- self.indicatorVisible = showsIndicator;
-
- if (showsIndicator){
- [self.indicator startAnimating];
- self.indicator.alpha = 1;
- self.layer.borderWidth = 1;
- self.layer.borderColor = [UIColor lightGrayColor].CGColor;
- self.layer.cornerRadius = 5;
- self.imageView.image = nil;
- } else {
- [self.indicator stopAnimating];
- self.layer.cornerRadius = 0;
- self.indicator.alpha = 0;
- self.layer.borderWidth = 0;
-
- }
-
-}
-
-- (void)layoutSubviews {
- [super layoutSubviews];
-
- [self.indicator setFrame:self.bounds];
-
-}
-
-
-@end
-
-#endif /* HOCKEYSDK_FEATURE_FEEDBACK */
diff --git a/submodules/HockeySDK-iOS/Classes/BITAlertAction.h b/submodules/HockeySDK-iOS/Classes/BITAlertAction.h
deleted file mode 100644
index caf1277f5c..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITAlertAction.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#import
-
-@interface BITAlertAction : UIAlertAction
-
-+ (UIAlertAction * _Nonnull)actionWithTitle:(nullable NSString *)title style:(UIAlertActionStyle)style handler:(void (^_Nullable)(UIAlertAction *_Nonnull))handler;
-
-- (void)invokeAction;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITAlertAction.m b/submodules/HockeySDK-iOS/Classes/BITAlertAction.m
deleted file mode 100644
index d689a5a960..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITAlertAction.m
+++ /dev/null
@@ -1,23 +0,0 @@
-#import "BITAlertAction.h"
-
-@interface BITAlertAction ()
-
-@property (nonatomic, copy) void (^storedHandler)(UIAlertAction * _Nonnull);
-
-@end
-
-@implementation BITAlertAction
-
-+ (UIAlertAction *)actionWithTitle:(nullable NSString *)title style:(UIAlertActionStyle)style handler:(void (^)(UIAlertAction *_Nonnull))handler {
- BITAlertAction *action = [super actionWithTitle:title style:style handler:handler];
- action.storedHandler = handler;
- return action;
-}
-
-- (void)invokeAction {
- if (self.storedHandler) {
- self.storedHandler(self);
- }
-}
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITAppStoreHeader.h b/submodules/HockeySDK-iOS/Classes/BITAppStoreHeader.h
deleted file mode 100644
index c0b5e8f955..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITAppStoreHeader.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Author: Andreas Linde
- * Peter Steinberger
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * Copyright (c) 2011-2012 Peter Steinberger.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#import
-
-@interface BITAppStoreHeader : UIView
-
-@property (nonatomic, copy) NSString *headerText;
-@property (nonatomic, copy) NSString *subHeaderText;
-@property (nonatomic, strong) UIImage *iconImage;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITAppStoreHeader.m b/submodules/HockeySDK-iOS/Classes/BITAppStoreHeader.m
deleted file mode 100644
index 54e72abf76..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITAppStoreHeader.m
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Author: Andreas Linde
- * Peter Steinberger
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * Copyright (c) 2011-2012 Peter Steinberger.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_UPDATES
-
-#import "BITAppStoreHeader.h"
-#import "BITHockeyHelper.h"
-#import "HockeySDKPrivate.h"
-
-#define kDarkGrayColor BIT_RGBCOLOR(186, 186, 186)
-#define kWhiteBackgroundColorDefault BIT_RGBCOLOR(245, 245, 245)
-#define kWhiteBackgroundColorOS7 BIT_RGBCOLOR(255, 255, 255)
-#define kImageHeight 72
-#define kImageBorderRadiusiOS7 16.5
-#define kImageLeftMargin 14
-#define kImageTopMargin 12
-#define kTextRow kImageTopMargin*2 + kImageHeight
-
-@interface BITAppStoreHeader ()
-
-@property (nonatomic, strong) UILabel *headerLabelView;
-@property (nonatomic, strong) UILabel *middleLabelView;
-
-@end
-
-@implementation BITAppStoreHeader
-
-
-#pragma mark - NSObject
-
-- (instancetype)initWithFrame:(CGRect)frame {
- if ((self = [super initWithFrame:frame])) {
- self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
- self.backgroundColor = kWhiteBackgroundColorDefault;
- }
- return self;
-}
-
-
-#pragma mark - UIView
-
-- (void)drawRect:(CGRect)rect {
- CGRect bounds = self.bounds;
-
- // draw the line
- CGContextRef ctx = UIGraphicsGetCurrentContext();
- CGContextSetLineWidth(ctx, 1.0);
- CGContextSetStrokeColorWithColor(ctx, kDarkGrayColor.CGColor);
- CGContextMoveToPoint(ctx, 0, CGRectGetMaxY(bounds));
- CGContextAddLineToPoint( ctx, CGRectGetMaxX(bounds), CGRectGetMaxY(bounds));
- CGContextStrokePath(ctx);
-
- // icon
- [self.iconImage drawAtPoint:CGPointMake(kImageLeftMargin, kImageTopMargin)];
-
- [super drawRect:rect];
-}
-
-
-- (void)layoutSubviews {
- self.backgroundColor = kWhiteBackgroundColorOS7;
-
- [super layoutSubviews];
-
- CGFloat globalWidth = self.frame.size.width;
-
- // draw header name
- UIColor *mainTextColor = BIT_RGBCOLOR(61, 61, 61);
- UIColor *secondaryTextColor = BIT_RGBCOLOR(100, 100, 100);
- UIFont *mainFont = [UIFont boldSystemFontOfSize:15];
- UIFont *secondaryFont = [UIFont systemFontOfSize:10];
-
- if (!self.headerLabelView) self.headerLabelView = [[UILabel alloc] init];
- [self.headerLabelView setFont:mainFont];
- [self.headerLabelView setFrame:CGRectMake(kTextRow, kImageTopMargin, globalWidth-kTextRow, 20)];
- [self.headerLabelView setTextColor:mainTextColor];
- [self.headerLabelView setBackgroundColor:[UIColor clearColor]];
- [self.headerLabelView setText:self.headerText];
- [self addSubview:self.headerLabelView];
-
- // middle
- if (!self.middleLabelView) self.middleLabelView = [[UILabel alloc] init];
- [self.middleLabelView setFont:secondaryFont];
- [self.middleLabelView setFrame:CGRectMake(kTextRow, kImageTopMargin + 17, globalWidth-kTextRow, 20)];
- [self.middleLabelView setTextColor:secondaryTextColor];
- [self.middleLabelView setBackgroundColor:[UIColor clearColor]];
- [self.middleLabelView setText:self.subHeaderText];
- [self addSubview:self.middleLabelView];
-}
-
-
-#pragma mark - Properties
-
-- (void)setHeaderText:(NSString *)anHeaderText {
- if (_headerText != anHeaderText) {
- _headerText = [anHeaderText copy];
- [self setNeedsDisplay];
- }
-}
-
-- (void)setSubHeaderText:(NSString *)aSubHeaderText {
- if (_subHeaderText != aSubHeaderText) {
- _subHeaderText = [aSubHeaderText copy];
- [self setNeedsDisplay];
- }
-}
-
-- (void)setIconImage:(UIImage *)anIconImage {
- if (_iconImage != anIconImage) {
-
- // scale, make borders and reflection
- _iconImage = bit_imageToFitSize(anIconImage, CGSizeMake(kImageHeight, kImageHeight), YES);
- _iconImage = bit_roundedCornerImage(_iconImage, kImageBorderRadiusiOS7, 0.0);
-
- [self setNeedsDisplay];
- }
-}
-
-@end
-
-#endif /* HOCKEYSDK_FEATURE_UPDATES */
diff --git a/submodules/HockeySDK-iOS/Classes/BITAppVersionMetaInfo.h b/submodules/HockeySDK-iOS/Classes/BITAppVersionMetaInfo.h
deleted file mode 100644
index 2143e02a72..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITAppVersionMetaInfo.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Author: Peter Steinberger
- * Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * Copyright (c) 2011 Andreas Linde, Peter Steinberger.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import
-
-@interface BITAppVersionMetaInfo : NSObject {
-}
-@property (nonatomic, copy) NSString *name;
-@property (nonatomic, copy) NSString *version;
-@property (nonatomic, copy) NSString *shortVersion;
-@property (nonatomic, copy) NSString *minOSVersion;
-@property (nonatomic, copy) NSString *notes;
-@property (nonatomic, copy) NSDate *date;
-@property (nonatomic, copy) NSNumber *size;
-@property (nonatomic, copy) NSNumber *mandatory;
-@property (nonatomic, copy) NSNumber *versionID;
-@property (nonatomic, copy) NSDictionary *uuids;
-
-- (NSString *)nameAndVersionString;
-- (NSString *)versionString;
-- (NSString *)dateString;
-- (NSString *)sizeInMB;
-- (NSString *)notesOrEmptyString;
-- (void)setDateWithTimestamp:(NSTimeInterval)timestamp;
-- (BOOL)isValid;
-- (BOOL)hasUUID:(NSString *)uuid;
-- (BOOL)isEqualToAppVersionMetaInfo:(BITAppVersionMetaInfo *)anAppVersionMetaInfo;
-
-+ (BITAppVersionMetaInfo *)appVersionMetaInfoFromDict:(NSDictionary *)dict;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITAppVersionMetaInfo.m b/submodules/HockeySDK-iOS/Classes/BITAppVersionMetaInfo.m
deleted file mode 100644
index 9320ed5092..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITAppVersionMetaInfo.m
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Author: Peter Steinberger
- * Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * Copyright (c) 2011 Andreas Linde, Peter Steinberger.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import "BITAppVersionMetaInfo.h"
-#import "HockeySDKPrivate.h"
-
-
-@implementation BITAppVersionMetaInfo
-
-
-#pragma mark - Static
-
-+ (BITAppVersionMetaInfo *)appVersionMetaInfoFromDict:(NSDictionary *)dict {
- BITAppVersionMetaInfo *appVersionMetaInfo = [[[self class] alloc] init];
-
- if ([dict isKindOfClass:[NSDictionary class]]) {
- appVersionMetaInfo.name = [dict objectForKey:@"title"];
- appVersionMetaInfo.version = [dict objectForKey:@"version"];
- appVersionMetaInfo.shortVersion = [dict objectForKey:@"shortversion"];
- appVersionMetaInfo.minOSVersion = [dict objectForKey:@"minimum_os_version"];
- [appVersionMetaInfo setDateWithTimestamp:[[dict objectForKey:@"timestamp"] doubleValue]];
- appVersionMetaInfo.size = [dict objectForKey:@"appsize"];
- appVersionMetaInfo.notes = [dict objectForKey:@"notes"];
- appVersionMetaInfo.mandatory = [dict objectForKey:@"mandatory"];
- appVersionMetaInfo.versionID = [dict objectForKey:@"id"];
- appVersionMetaInfo.uuids = [dict objectForKey:@"uuids"];
- }
-
- return appVersionMetaInfo;
-}
-
-
-#pragma mark - NSObject
-
-- (BOOL)isEqual:(id)other {
- if (other == self)
- return YES;
- if (!other || ![other isKindOfClass:[self class]])
- return NO;
- return [self isEqualToAppVersionMetaInfo:other];
-}
-
-- (BOOL)isEqualComparingString:(NSString *)stringA withString:(NSString *)stringB {
- if ([stringA isKindOfClass:[NSString class]] && [stringB isKindOfClass:[NSString class]]) {
- return [stringA isEqualToString:stringB];
- }
-
- return NO;
-}
-
-- (BOOL)isEqualComparingNumber:(NSNumber *)numberA withNumber:(NSNumber *)numberB {
- if ([numberA isKindOfClass:[NSNumber class]] && [numberB isKindOfClass:[NSNumber class]]) {
- return [numberA isEqualToNumber:numberB];
- }
-
- return NO;
-}
-
-- (BOOL)isEqualComparingDate:(NSDate *)dateA withDate:(NSDate *)dateB {
- if ([dateA isKindOfClass:[NSDate class]] && [dateB isKindOfClass:[NSDate class]]) {
- return [dateA isEqualToDate:dateB];
- }
-
- return NO;
-}
-
-- (BOOL)isEqualComparingDictionary:(NSDictionary *)dictA withDate:(NSDictionary *)dictB {
- if ([dictA isKindOfClass:[NSDictionary class]] && [dictB isKindOfClass:[NSDictionary class]]) {
- return [dictA isEqualToDictionary:dictB];
- }
-
- return NO;
-}
-
-- (BOOL)isEqualToAppVersionMetaInfo:(BITAppVersionMetaInfo *)anAppVersionMetaInfo {
- if (self == anAppVersionMetaInfo)
- return YES;
- if (![self isEqualComparingString:self.name withString:anAppVersionMetaInfo.name])
- return NO;
- if (![self isEqualComparingString:self.version withString:anAppVersionMetaInfo.version])
- return NO;
- if (![self isEqualComparingString:self.shortVersion withString:anAppVersionMetaInfo.shortVersion])
- return NO;
- if (![self isEqualComparingString:self.minOSVersion withString:anAppVersionMetaInfo.minOSVersion])
- return NO;
- if (![self isEqualComparingString:self.notes withString:anAppVersionMetaInfo.notes])
- return NO;
- if (![self isEqualComparingDate:self.date withDate:anAppVersionMetaInfo.date])
- return NO;
- if (![self isEqualComparingNumber:self.size withNumber:anAppVersionMetaInfo.size])
- return NO;
- if (![self isEqualComparingNumber:self.mandatory withNumber:anAppVersionMetaInfo.mandatory])
- return NO;
- if (![self isEqualComparingDictionary:self.uuids withDate:anAppVersionMetaInfo.uuids])
- return NO;
- return YES;
-}
-
-
-#pragma mark - NSCoder
-
-- (void)encodeWithCoder:(NSCoder *)encoder {
- [encoder encodeObject:self.name forKey:@"name"];
- [encoder encodeObject:self.version forKey:@"version"];
- [encoder encodeObject:self.shortVersion forKey:@"shortVersion"];
- [encoder encodeObject:self.minOSVersion forKey:@"minOSVersion"];
- [encoder encodeObject:self.notes forKey:@"notes"];
- [encoder encodeObject:self.date forKey:@"date"];
- [encoder encodeObject:self.size forKey:@"size"];
- [encoder encodeObject:self.mandatory forKey:@"mandatory"];
- [encoder encodeObject:self.versionID forKey:@"versionID"];
- [encoder encodeObject:self.uuids forKey:@"uuids"];
-}
-
-- (instancetype)initWithCoder:(NSCoder *)decoder {
- if ((self = [super init])) {
- self.name = [decoder decodeObjectForKey:@"name"];
- self.version = [decoder decodeObjectForKey:@"version"];
- self.shortVersion = [decoder decodeObjectForKey:@"shortVersion"];
- self.minOSVersion = [decoder decodeObjectForKey:@"minOSVersion"];
- self.notes = [decoder decodeObjectForKey:@"notes"];
- self.date = [decoder decodeObjectForKey:@"date"];
- self.size = [decoder decodeObjectForKey:@"size"];
- self.mandatory = [decoder decodeObjectForKey:@"mandatory"];
- self.versionID = [decoder decodeObjectForKey:@"versionID"];
- self.uuids = [decoder decodeObjectForKey:@"uuids"];
- }
- return self;
-}
-
-
-#pragma mark - Properties
-
-- (NSString *)nameAndVersionString {
- NSString *appNameAndVersion = [NSString stringWithFormat:@"%@ %@", self.name, [self versionString]];
- return appNameAndVersion;
-}
-
-- (NSString *)versionString {
- NSString *shortString = ([self.shortVersion respondsToSelector:@selector(length)] && [self.shortVersion length]) ? [NSString stringWithFormat:@"%@", self.shortVersion] : @"";
- NSString *versionString = [shortString length] ? [NSString stringWithFormat:@" (%@)", self.version] : self.version;
- return [NSString stringWithFormat:@"%@ %@%@", BITHockeyLocalizedString(@"Version"), shortString, versionString];
-}
-
-- (NSString *)dateString {
- NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
- [formatter setDateStyle:NSDateFormatterMediumStyle];
-
- return [formatter stringFromDate:self.date];
-}
-
-- (NSString *)sizeInMB {
- if ([self.size isKindOfClass: [NSNumber class]] && [self.size doubleValue] > 0) {
- double appSizeInMB = [self.size doubleValue]/(1024*1024);
- NSString *appSizeString = [NSString stringWithFormat:@"%.1f MB", appSizeInMB];
- return appSizeString;
- }
-
- return @"0 MB";
-}
-
-- (void)setDateWithTimestamp:(NSTimeInterval)timestamp {
- if (timestamp != 0) {
- NSDate *appDate = [NSDate dateWithTimeIntervalSince1970:timestamp];
- self.date = appDate;
- } else {
- self.date = nil;
- }
-}
-
-- (NSString *)notesOrEmptyString {
- if (self.notes) {
- return self.notes;
- }else {
- return [NSString string];
- }
-}
-
-
-// A valid app needs at least following properties: name, version, date
-- (BOOL)isValid {
- BOOL valid = [self.name length] && [self.version length] && self.date;
- return valid;
-}
-
-- (BOOL)hasUUID:(NSString *)uuid {
- if (!uuid) return NO;
- if (!self.uuids) return NO;
-
- __block BOOL hasUUID = NO;
-
- [self.uuids enumerateKeysAndObjectsUsingBlock:^(id __unused key, id obj, BOOL *stop){
- if (obj && [uuid compare:obj] == NSOrderedSame) {
- hasUUID = YES;
- *stop = YES;
- }
- }];
-
- return hasUUID;
-}
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITApplication.h b/submodules/HockeySDK-iOS/Classes/BITApplication.h
deleted file mode 100755
index 6a03147e2d..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITApplication.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#import "BITTelemetryObject.h"
-
-@interface BITApplication : BITTelemetryObject
-
-@property (nonatomic, copy) NSString *version;
-@property (nonatomic, copy) NSString *build;
-@property (nonatomic, copy) NSString *typeId;
-
-- (instancetype)initWithCoder:(NSCoder *)coder;
-- (void)encodeWithCoder:(NSCoder *)coder;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITApplication.m b/submodules/HockeySDK-iOS/Classes/BITApplication.m
deleted file mode 100755
index e3104f3616..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITApplication.m
+++ /dev/null
@@ -1,44 +0,0 @@
-#import "BITApplication.h"
-
-/// Data contract class for type Application.
-@implementation BITApplication
-
-///
-/// Adds all members of this class to a dictionary
-///
-- (NSDictionary *)serializeToDictionary {
- NSMutableDictionary *dict = [super serializeToDictionary].mutableCopy;
- if (self.version != nil) {
- [dict setObject:self.version forKey:@"ai.application.ver"];
- }
- if (self.build != nil) {
- [dict setObject:self.build forKey:@"ai.application.build"];
- }
- if (self.typeId != nil) {
- [dict setObject:self.typeId forKey:@"ai.application.typeId"];
- }
- return dict;
-}
-
-#pragma mark - NSCoding
-
-- (instancetype)initWithCoder:(NSCoder *)coder {
- self = [super initWithCoder:coder];
- if (self) {
- _version = [coder decodeObjectForKey:@"self.version"];
- _build = [coder decodeObjectForKey:@"self.build"];
- _typeId = [coder decodeObjectForKey:@"self.typeId"];
- }
-
- return self;
-}
-
-- (void)encodeWithCoder:(NSCoder *)coder {
- [super encodeWithCoder:coder];
- [coder encodeObject:self.version forKey:@"self.version"];
- [coder encodeObject:self.build forKey:@"self.build"];
- [coder encodeObject:self.typeId forKey:@"self.typeId"];
-}
-
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITArrowImageAnnotation.h b/submodules/HockeySDK-iOS/Classes/BITArrowImageAnnotation.h
deleted file mode 100644
index feeca7613b..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITArrowImageAnnotation.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Author: Moritz Haarmann
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import "BITImageAnnotation.h"
-
-@interface BITArrowImageAnnotation : BITImageAnnotation
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITArrowImageAnnotation.m b/submodules/HockeySDK-iOS/Classes/BITArrowImageAnnotation.m
deleted file mode 100644
index d74a76cf10..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITArrowImageAnnotation.m
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Author: Moritz Haarmann
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_FEEDBACK
-
-#import "BITArrowImageAnnotation.h"
-#import
-
-#define kArrowPointCount 7
-
-
-@interface BITArrowImageAnnotation()
-
-@property (nonatomic, strong) CAShapeLayer *shapeLayer;
-@property (nonatomic, strong) CAShapeLayer *strokeLayer;
-
-@end
-
-@implementation BITArrowImageAnnotation
-
-- (instancetype)initWithFrame:(CGRect)frame {
- self = [super initWithFrame:frame];
- if (self) {
- self.shapeLayer = [CAShapeLayer layer];
- self.shapeLayer.strokeColor = [UIColor whiteColor].CGColor;
- self.shapeLayer.lineWidth = 5;
- self.shapeLayer.fillColor = [UIColor redColor].CGColor;
-
- self.strokeLayer = [CAShapeLayer layer];
- self.strokeLayer.strokeColor = [UIColor redColor].CGColor;
- self.strokeLayer.lineWidth = 10;
- self.strokeLayer.fillColor = [UIColor clearColor].CGColor;
- [self.layer addSublayer:self.strokeLayer];
-
- [self.layer addSublayer:self.shapeLayer];
-
-
- }
- return self;
-}
-
-- (void)buildShape {
- CGFloat baseWidth = MAX(self.frame.size.width, self.frame.size.height);
- CGFloat topHeight = MAX(baseWidth / 3,10);
-
-
- CGFloat lineWidth = MAX(baseWidth / 10,3);
- CGFloat startX, startY, endX, endY;
-
- CGRect boundRect = CGRectInset(self.bounds, 0, 0);
- CGFloat arrowLength= sqrt(pow(CGRectGetWidth(boundRect), (CGFloat)2) + pow(CGRectGetHeight(boundRect), (CGFloat)2));
- if (0 < arrowLength && arrowLength < 30){
-
- CGFloat factor = 30 / arrowLength;
-
- boundRect = CGRectApplyAffineTransform(boundRect, CGAffineTransformMakeScale(factor,factor));
- }
-
- if ( self.movedDelta.width < 0){
- startX = CGRectGetMinX(boundRect);
- endX = CGRectGetMaxX(boundRect);
- } else {
- startX = CGRectGetMaxX(boundRect);
- endX = CGRectGetMinX(boundRect);
-
- }
-
- if ( self.movedDelta.height < 0){
- startY = CGRectGetMinY(boundRect);
- endY = CGRectGetMaxY(boundRect);
- } else {
- startY = CGRectGetMaxY(boundRect);
- endY = CGRectGetMinY(boundRect);
-
- }
-
-
- if (fabs(CGRectGetWidth(boundRect)) < 30 || fabs(CGRectGetHeight(boundRect)) < 30){
- CGFloat smallerOne = MIN(fabs(CGRectGetHeight(boundRect)), fabs(CGRectGetWidth(boundRect)));
-
- CGFloat factor = smallerOne / 30;
-
- CGRectApplyAffineTransform(boundRect, CGAffineTransformMakeScale(factor,factor));
- }
-
- UIBezierPath *path = [self bezierPathWithArrowFromPoint:CGPointMake(endX, endY) toPoint:CGPointMake(startX, startY) tailWidth:lineWidth headWidth:topHeight headLength:topHeight];
-
- self.shapeLayer.path = path.CGPath;
- self.strokeLayer.path = path.CGPath;
- [CATransaction begin];
- [CATransaction setAnimationDuration:0];
- self.strokeLayer.lineWidth = lineWidth / (CGFloat)1.5;
- self.shapeLayer.lineWidth = lineWidth / 3;
-
- [CATransaction commit];
-
-}
-
-
-- (UIBezierPath *)bezierPathWithArrowFromPoint:(CGPoint)startPoint
- toPoint:(CGPoint)endPoint
- tailWidth:(CGFloat)tailWidth
- headWidth:(CGFloat)headWidth
- headLength:(CGFloat)headLength {
- CGFloat length = hypot(endPoint.x - startPoint.x, endPoint.y - startPoint.y);
-
- CGPoint points[kArrowPointCount];
- [self getAxisAlignedArrowPoints:points
- forLength:length
- tailWidth:tailWidth
- headWidth:headWidth
- headLength:headLength];
-
- CGAffineTransform transform = [self transformForStartPoint:startPoint
- endPoint:endPoint
- length:length];
-
- CGMutablePathRef cgPath = CGPathCreateMutable();
- CGPathAddLines(cgPath, &transform, points, sizeof points / sizeof *points);
- CGPathCloseSubpath(cgPath);
-
- UIBezierPath *uiPath = [UIBezierPath bezierPathWithCGPath:cgPath];
- CGPathRelease(cgPath);
- return uiPath;
-}
-
-- (void)getAxisAlignedArrowPoints:(CGPoint[kArrowPointCount])points
- forLength:(CGFloat)length
- tailWidth:(CGFloat)tailWidth
- headWidth:(CGFloat)headWidth
- headLength:(CGFloat)headLength {
- CGFloat tailLength = length - headLength;
- points[0] = CGPointMake(0, tailWidth / 2);
- points[1] = CGPointMake(tailLength, tailWidth / 2);
- points[2] = CGPointMake(tailLength, headWidth / 2);
- points[3] = CGPointMake(length, 0);
- points[4] = CGPointMake(tailLength, -headWidth / 2);
- points[5] = CGPointMake(tailLength, -tailWidth / 2);
- points[6] = CGPointMake(0, -tailWidth / 2);
-}
-
-+ (CGAffineTransform)dqd_transformForStartPoint:(CGPoint)startPoint
- endPoint:(CGPoint)endPoint
- length:(CGFloat)length {
- CGFloat cosine = (endPoint.x - startPoint.x) / length;
- CGFloat sine = (endPoint.y - startPoint.y) / length;
- return (CGAffineTransform){ cosine, sine, -sine, cosine, startPoint.x, startPoint.y };
-}
-
-- (CGAffineTransform)transformForStartPoint:(CGPoint)startPoint
- endPoint:(CGPoint)endPoint
- length:(CGFloat)length {
- if (CGPointEqualToPoint(startPoint, CGPointZero) && (length == 0)) {
- return CGAffineTransformIdentity;
- }
-
- CGFloat cosine = (endPoint.x - startPoint.x) / length;
- CGFloat sine = (endPoint.y - startPoint.y) / length;
- return (CGAffineTransform){ cosine, sine, -sine, cosine, startPoint.x, startPoint.y };
-}
-
-#pragma mark - UIView
-
-- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *) __unused event {
-
- CGPathRef strokePath = CGPathCreateCopyByStrokingPath(self.shapeLayer.path, NULL, fmax(90.0f, self.shapeLayer.lineWidth), kCGLineCapRound,kCGLineJoinMiter,0);
-
- BOOL containsPoint = CGPathContainsPoint(strokePath, NULL, point, NO);
-
- CGPathRelease(strokePath);
-
- if (containsPoint){
- return self;
- } else {
- return nil;
- }
-
-}
-
-- (void)layoutSubviews{
- [super layoutSubviews];
-
- [self buildShape];
-}
-
-@end
-
-#endif /* HOCKEYSDK_FEATURE_FEEDBACK */
diff --git a/submodules/HockeySDK-iOS/Classes/BITAttributedLabel.h b/submodules/HockeySDK-iOS/Classes/BITAttributedLabel.h
deleted file mode 100644
index 720aaf37ef..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITAttributedLabel.h
+++ /dev/null
@@ -1,681 +0,0 @@
-// TTTAttributedLabel.h
-//
-// Copyright (c) 2011 Mattt Thompson (http://mattt.me)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#import
-#import
-
-//! Project version number for BITAttributedLabel.
-FOUNDATION_EXPORT double BITAttributedLabelVersionNumber;
-
-//! Project version string for BITAttributedLabel.
-FOUNDATION_EXPORT const unsigned char BITAttributedLabelVersionString[];
-
-@class BITAttributedLabelLink;
-
-/**
- Vertical alignment for text in a label whose bounds are larger than its text bounds
- */
-typedef NS_ENUM(NSInteger, BITAttributedLabelVerticalAlignment) {
- BITAttributedLabelVerticalAlignmentCenter = 0,
- BITAttributedLabelVerticalAlignmentTop = 1,
- BITAttributedLabelVerticalAlignmentBottom = 2,
-};
-
-/**
- Determines whether the text to which this attribute applies has a strikeout drawn through itself.
- */
-extern NSString * const kBITStrikeOutAttributeName;
-
-/**
- The background fill color. Value must be a `CGColorRef`. Default value is `nil` (no fill).
- */
-extern NSString * const kBITBackgroundFillColorAttributeName;
-
-/**
- The padding for the background fill. Value must be a `UIEdgeInsets`. Default value is `UIEdgeInsetsZero` (no padding).
- */
-extern NSString * const kBITBackgroundFillPaddingAttributeName;
-
-/**
- The background stroke color. Value must be a `CGColorRef`. Default value is `nil` (no stroke).
- */
-extern NSString * const kBITBackgroundStrokeColorAttributeName;
-
-/**
- The background stroke line width. Value must be an `NSNumber`. Default value is `1.0f`.
- */
-extern NSString * const kBITBackgroundLineWidthAttributeName;
-
-/**
- The background corner radius. Value must be an `NSNumber`. Default value is `5.0f`.
- */
-extern NSString * const kBITBackgroundCornerRadiusAttributeName;
-
-@protocol BITAttributedLabelDelegate;
-
-// Override UILabel @property to accept both NSString and NSAttributedString
-@protocol BITAttributedLabel
-@property (nonatomic, copy) IBInspectable id text;
-@end
-
-IB_DESIGNABLE
-
-/**
- `BITAttributedLabel` is a drop-in replacement for `UILabel` that supports `NSAttributedString`, as well as automatically-detected and manually-added links to URLs, addresses, phone numbers, and dates.
-
- ## Differences Between `BITAttributedLabel` and `UILabel`
-
- For the most part, `BITAttributedLabel` behaves just like `UILabel`. The following are notable exceptions, in which `BITAttributedLabel` may act differently:
-
- - `text` - This property now takes an `id` type argument, which can either be a kind of `NSString` or `NSAttributedString` (mutable or immutable in both cases)
- - `attributedText` - Do not set this property directly. Instead, pass an `NSAttributedString` to `text`.
- - `lineBreakMode` - This property displays only the first line when the value is `UILineBreakModeHeadTruncation`, `UILineBreakModeTailTruncation`, or `UILineBreakModeMiddleTruncation`
- - `adjustsFontsizeToFitWidth` - Supported in iOS 5 and greater, this property is effective for any value of `numberOfLines` greater than zero. In iOS 4, setting `numberOfLines` to a value greater than 1 with `adjustsFontSizeToFitWidth` set to `YES` may cause `sizeToFit` to execute indefinitely.
- - `baselineAdjustment` - This property has no affect.
- - `textAlignment` - This property does not support justified alignment.
- - `NSTextAttachment` - This string attribute is not supported.
-
- Any properties affecting text or paragraph styling, such as `firstLineIndent` will only apply when text is set with an `NSString`. If the text is set with an `NSAttributedString`, these properties will not apply.
-
- ### NSCoding
-
- `BITAttributedLabel`, like `UILabel`, conforms to `NSCoding`. However, if the build target is set to less than iOS 6.0, `linkAttributes` and `activeLinkAttributes` will not be encoded or decoded. This is due to an runtime exception thrown when attempting to copy non-object CoreText values in dictionaries.
-
- @warning Any properties changed on the label after setting the text will not be reflected until a subsequent call to `setText:` or `setText:afterInheritingLabelAttributesAndConfiguringWithBlock:`. This is to say, order of operations matters in this case. For example, if the label text color is originally black when the text is set, changing the text color to red will have no effect on the display of the label until the text is set once again.
-
- @bug Setting `attributedText` directly is not recommended, as it may cause a crash when attempting to access any links previously set. Instead, call `setText:`, passing an `NSAttributedString`.
- */
-@interface BITAttributedLabel : UILabel
-
-/**
- * The designated initializers are @c initWithFrame: and @c initWithCoder:.
- * init will not properly initialize many required properties and other configuration.
- */
-- (instancetype) init NS_UNAVAILABLE;
-
-///-----------------------------
-/// @name Accessing the Delegate
-///-----------------------------
-
-/**
- The receiver's delegate.
-
- @discussion A `BITAttributedLabel` delegate responds to messages sent by tapping on links in the label. You can use the delegate to respond to links referencing a URL, address, phone number, date, or date with a specified time zone and duration.
- */
-@property (nonatomic, unsafe_unretained) IBOutlet id delegate;
-
-///--------------------------------------------
-/// @name Detecting, Accessing, & Styling Links
-///--------------------------------------------
-
-/**
- A bitmask of `NSTextCheckingType` which are used to automatically detect links in the label text.
-
- @warning You must specify `enabledTextCheckingTypes` before setting the `text`, with either `setText:` or `setText:afterInheritingLabelAttributesAndConfiguringWithBlock:`.
- */
-@property (nonatomic, assign) NSTextCheckingTypes enabledTextCheckingTypes;
-
-/**
- An array of `NSTextCheckingResult` objects for links detected or manually added to the label text.
- */
-@property (readonly, nonatomic, strong) NSArray *links;
-
-/**
- A dictionary containing the default `NSAttributedString` attributes to be applied to links detected or manually added to the label text. The default link style is blue and underlined.
-
- @warning You must specify `linkAttributes` before setting autodecting or manually-adding links for these attributes to be applied.
- */
-@property (nonatomic, strong) NSDictionary *linkAttributes;
-
-/**
- A dictionary containing the default `NSAttributedString` attributes to be applied to links when they are in the active state. If `nil` or an empty `NSDictionary`, active links will not be styled. The default active link style is red and underlined.
- */
-@property (nonatomic, strong) NSDictionary *activeLinkAttributes;
-
-/**
- A dictionary containing the default `NSAttributedString` attributes to be applied to links when they are in the inactive state, which is triggered by a change in `tintColor` in iOS 7 and later. If `nil` or an empty `NSDictionary`, inactive links will not be styled. The default inactive link style is gray and unadorned.
- */
-@property (nonatomic, strong) NSDictionary *inactiveLinkAttributes;
-
-/**
- The edge inset for the background of a link. The default value is `{0, -1, 0, -1}`.
- */
-@property (nonatomic, assign) UIEdgeInsets linkBackgroundEdgeInset;
-
-/**
- Indicates if links will be detected within an extended area around the touch
- to emulate the link detection behaviour of UIWebView.
- Default value is NO. Enabling this may adversely impact performance.
- */
-@property (nonatomic, assign) BOOL extendsLinkTouchArea;
-
-///---------------------------------------
-/// @name Acccessing Text Style Attributes
-///---------------------------------------
-
-/**
- The shadow blur radius for the label. A value of 0 indicates no blur, while larger values produce correspondingly larger blurring. This value must not be negative. The default value is 0.
- */
-@property (nonatomic, assign) IBInspectable CGFloat shadowRadius;
-
-/**
- The shadow blur radius for the label when the label's `highlighted` property is `YES`. A value of 0 indicates no blur, while larger values produce correspondingly larger blurring. This value must not be negative. The default value is 0.
- */
-@property (nonatomic, assign) IBInspectable CGFloat highlightedShadowRadius;
-/**
- The shadow offset for the label when the label's `highlighted` property is `YES`. A size of {0, 0} indicates no offset, with positive values extending down and to the right. The default size is {0, 0}.
- */
-@property (nonatomic, assign) IBInspectable CGSize highlightedShadowOffset;
-/**
- The shadow color for the label when the label's `highlighted` property is `YES`. The default value is `nil` (no shadow color).
- */
-@property (nonatomic, strong) IBInspectable UIColor *highlightedShadowColor;
-
-/**
- The amount to kern the next character. Default is standard kerning. If this attribute is set to 0.0, no kerning is done at all.
- */
-@property (nonatomic, assign) IBInspectable CGFloat kern;
-
-///--------------------------------------------
-/// @name Acccessing Paragraph Style Attributes
-///--------------------------------------------
-
-/**
- The distance, in points, from the leading margin of a frame to the beginning of the
- paragraph's first line. This value is always nonnegative, and is 0.0 by default.
- This applies to the full text, rather than any specific paragraph metrics.
- */
-@property (nonatomic, assign) IBInspectable CGFloat firstLineIndent;
-
-/**
- The space in points added between lines within the paragraph. This value is always nonnegative and is 0.0 by default.
- */
-@property (nonatomic, assign) IBInspectable CGFloat lineSpacing;
-
-/**
- The minimum line height within the paragraph. If the value is 0.0, the minimum line height is set to the line height of the `font`. 0.0 by default.
- */
-@property (nonatomic, assign) IBInspectable CGFloat minimumLineHeight;
-
-/**
- The maximum line height within the paragraph. If the value is 0.0, the maximum line height is set to the line height of the `font`. 0.0 by default.
- */
-@property (nonatomic, assign) IBInspectable CGFloat maximumLineHeight;
-
-/**
- The line height multiple. This value is 1.0 by default.
- */
-@property (nonatomic, assign) IBInspectable CGFloat lineHeightMultiple;
-
-/**
- The distance, in points, from the margin to the text container. This value is `UIEdgeInsetsZero` by default.
- sizeThatFits: will have its returned size increased by these margins.
- drawTextInRect: will inset all drawn text by these margins.
- */
-@property (nonatomic, assign) IBInspectable UIEdgeInsets textInsets;
-
-/**
- The vertical text alignment for the label, for when the frame size is greater than the text rect size. The vertical alignment is `BITAttributedLabelVerticalAlignmentCenter` by default.
- */
-@property (nonatomic, assign) BITAttributedLabelVerticalAlignment verticalAlignment;
-
-///--------------------------------------------
-/// @name Accessing Truncation Token Appearance
-///--------------------------------------------
-
-/**
- The attributed string to apply to the truncation token at the end of a truncated line.
- */
-@property (nonatomic, strong) IBInspectable NSAttributedString *attributedTruncationToken;
-
-///--------------------------
-/// @name Long press gestures
-///--------------------------
-
-/**
- * The long-press gesture recognizer used internally by the label.
- */
-@property (nonatomic, strong, readonly) UILongPressGestureRecognizer *longPressGestureRecognizer;
-
-///--------------------------------------------
-/// @name Calculating Size of Attributed String
-///--------------------------------------------
-
-/**
- Calculate and return the size that best fits an attributed string, given the specified constraints on size and number of lines.
-
- @param attributedString The attributed string.
- @param size The maximum dimensions used to calculate size.
- @param numberOfLines The maximum number of lines in the text to draw, if the constraining size cannot accomodate the full attributed string.
-
- @return The size that fits the attributed string within the specified constraints.
- */
-+ (CGSize)sizeThatFitsAttributedString:(NSAttributedString *)attributedString
- withConstraints:(CGSize)size
- limitedToNumberOfLines:(NSUInteger)numberOfLines;
-
-///----------------------------------
-/// @name Setting the Text Attributes
-///----------------------------------
-
-/**
- Sets the text displayed by the label.
-
- @param text An `NSString` or `NSAttributedString` object to be displayed by the label. If the specified text is an `NSString`, the label will display the text like a `UILabel`, inheriting the text styles of the label. If the specified text is an `NSAttributedString`, the label text styles will be overridden by the styles specified in the attributed string.
-
- @discussion This method overrides `UILabel -setText:` to accept both `NSString` and `NSAttributedString` objects. This string is `nil` by default.
- */
-- (void)setText:(id)text;
-
-/**
- Sets the text displayed by the label, after configuring an attributed string containing the text attributes inherited from the label in a block.
-
- @param text An `NSString` or `NSAttributedString` object to be displayed by the label.
- @param block A block object that returns an `NSMutableAttributedString` object and takes a single argument, which is an `NSMutableAttributedString` object with the text from the first parameter, and the text attributes inherited from the label text styles. For example, if you specified the `font` of the label to be `[UIFont boldSystemFontOfSize:14]` and `textColor` to be `[UIColor redColor]`, the `NSAttributedString` argument of the block would be contain the `NSAttributedString` attribute equivalents of those properties. In this block, you can set further attributes on particular ranges.
-
- @discussion This string is `nil` by default.
- */
-- (void)setText:(id)text
-afterInheritingLabelAttributesAndConfiguringWithBlock:(NSMutableAttributedString *(^)(NSMutableAttributedString *mutableAttributedString))block;
-
-///------------------------------------
-/// @name Accessing the Text Attributes
-///------------------------------------
-
-/**
- A copy of the label's current attributedText. This returns `nil` if an attributed string has never been set on the label.
-
- @warning Do not set this property directly. Instead, set @c text to an @c NSAttributedString.
- */
-@property (readwrite, nonatomic, copy) NSAttributedString *attributedText;
-
-///-------------------
-/// @name Adding Links
-///-------------------
-
-/**
- Adds a link. You can customize an individual link's appearance and accessibility value by creating your own @c BITAttributedLabelLink and passing it to this method. The other methods for adding links will use the label's default attributes.
-
- @warning Modifying the link's attribute dictionaries must be done before calling this method.
-
- @param link A @c BITAttributedLabelLink object.
- */
-- (void)addLink:(BITAttributedLabelLink *)link;
-
-/**
- Adds a link to an @c NSTextCheckingResult.
-
- @param result An @c NSTextCheckingResult representing the link's location and type.
-
- @return The newly added link object.
- */
-- (BITAttributedLabelLink *)addLinkWithTextCheckingResult:(NSTextCheckingResult *)result;
-
-/**
- Adds a link to an @c NSTextCheckingResult.
-
- @param result An @c NSTextCheckingResult representing the link's location and type.
- @param attributes The attributes to be added to the text in the range of the specified link. If set, the label's @c activeAttributes and @c inactiveAttributes will be applied to the link. If `nil`, no attributes are added to the link.
-
- @return The newly added link object.
- */
-- (BITAttributedLabelLink *)addLinkWithTextCheckingResult:(NSTextCheckingResult *)result
- attributes:(NSDictionary *)attributes;
-
-/**
- Adds a link to a URL for a specified range in the label text.
-
- @param url The url to be linked to
- @param range The range in the label text of the link. The range must not exceed the bounds of the receiver.
-
- @return The newly added link object.
- */
-- (BITAttributedLabelLink *)addLinkToURL:(NSURL *)url
- withRange:(NSRange)range;
-
-/**
- Adds a link to an address for a specified range in the label text.
-
- @param addressComponents A dictionary of address components for the address to be linked to
- @param range The range in the label text of the link. The range must not exceed the bounds of the receiver.
-
- @discussion The address component dictionary keys are described in `NSTextCheckingResult`'s "Keys for Address Components."
-
- @return The newly added link object.
- */
-- (BITAttributedLabelLink *)addLinkToAddress:(NSDictionary *)addressComponents
- withRange:(NSRange)range;
-
-/**
- Adds a link to a phone number for a specified range in the label text.
-
- @param phoneNumber The phone number to be linked to.
- @param range The range in the label text of the link. The range must not exceed the bounds of the receiver.
-
- @return The newly added link object.
- */
-- (BITAttributedLabelLink *)addLinkToPhoneNumber:(NSString *)phoneNumber
- withRange:(NSRange)range;
-
-/**
- Adds a link to a date for a specified range in the label text.
-
- @param date The date to be linked to.
- @param range The range in the label text of the link. The range must not exceed the bounds of the receiver.
-
- @return The newly added link object.
- */
-- (BITAttributedLabelLink *)addLinkToDate:(NSDate *)date
- withRange:(NSRange)range;
-
-/**
- Adds a link to a date with a particular time zone and duration for a specified range in the label text.
-
- @param date The date to be linked to.
- @param timeZone The time zone of the specified date.
- @param duration The duration, in seconds from the specified date.
- @param range The range in the label text of the link. The range must not exceed the bounds of the receiver.
-
- @return The newly added link object.
- */
-- (BITAttributedLabelLink *)addLinkToDate:(NSDate *)date
- timeZone:(NSTimeZone *)timeZone
- duration:(NSTimeInterval)duration
- withRange:(NSRange)range;
-
-/**
- Adds a link to transit information for a specified range in the label text.
-
- @param components A dictionary containing the transit components. The currently supported keys are `NSTextCheckingAirlineKey` and `NSTextCheckingFlightKey`.
- @param range The range in the label text of the link. The range must not exceed the bounds of the receiver.
-
- @return The newly added link object.
- */
-- (BITAttributedLabelLink *)addLinkToTransitInformation:(NSDictionary *)components
- withRange:(NSRange)range;
-
-/**
- Returns whether an @c NSTextCheckingResult is found at the give point.
-
- @discussion This can be used together with @c UITapGestureRecognizer to tap interactions with overlapping views.
-
- @param point The point inside the label.
- */
-- (BOOL)containslinkAtPoint:(CGPoint)point;
-
-/**
- Returns the @c BITAttributedLabelLink at the give point if it exists.
-
- @discussion This can be used together with @c UIViewControllerPreviewingDelegate to peek into links.
-
- @param point The point inside the label.
- */
-- (BITAttributedLabelLink *)linkAtPoint:(CGPoint)point;
-
-@end
-
-/**
- The `BITAttributedLabelDelegate` protocol defines the messages sent to an attributed label delegate when links are tapped. All of the methods of this protocol are optional.
- */
-@protocol BITAttributedLabelDelegate
-
-///-----------------------------------
-/// @name Responding to Link Selection
-///-----------------------------------
-@optional
-
-/**
- Tells the delegate that the user did select a link to a URL.
-
- @param label The label whose link was selected.
- @param url The URL for the selected link.
- */
-- (void)attributedLabel:(BITAttributedLabel *)label
- didSelectLinkWithURL:(NSURL *)url;
-
-/**
- Tells the delegate that the user did select a link to an address.
-
- @param label The label whose link was selected.
- @param addressComponents The components of the address for the selected link.
- */
-- (void)attributedLabel:(BITAttributedLabel *)label
-didSelectLinkWithAddress:(NSDictionary *)addressComponents;
-
-/**
- Tells the delegate that the user did select a link to a phone number.
-
- @param label The label whose link was selected.
- @param phoneNumber The phone number for the selected link.
- */
-- (void)attributedLabel:(BITAttributedLabel *)label
-didSelectLinkWithPhoneNumber:(NSString *)phoneNumber;
-
-/**
- Tells the delegate that the user did select a link to a date.
-
- @param label The label whose link was selected.
- @param date The datefor the selected link.
- */
-- (void)attributedLabel:(BITAttributedLabel *)label
- didSelectLinkWithDate:(NSDate *)date;
-
-/**
- Tells the delegate that the user did select a link to a date with a time zone and duration.
-
- @param label The label whose link was selected.
- @param date The date for the selected link.
- @param timeZone The time zone of the date for the selected link.
- @param duration The duration, in seconds from the date for the selected link.
- */
-- (void)attributedLabel:(BITAttributedLabel *)label
- didSelectLinkWithDate:(NSDate *)date
- timeZone:(NSTimeZone *)timeZone
- duration:(NSTimeInterval)duration;
-
-/**
- Tells the delegate that the user did select a link to transit information
-
- @param label The label whose link was selected.
- @param components A dictionary containing the transit components. The currently supported keys are `NSTextCheckingAirlineKey` and `NSTextCheckingFlightKey`.
- */
-- (void)attributedLabel:(BITAttributedLabel *)label
-didSelectLinkWithTransitInformation:(NSDictionary *)components;
-
-/**
- Tells the delegate that the user did select a link to a text checking result.
-
- @discussion This method is called if no other delegate method was called, which can occur by either now implementing the method in `BITAttributedLabelDelegate` corresponding to a particular link, or the link was added by passing an instance of a custom `NSTextCheckingResult` subclass into `-addLinkWithTextCheckingResult:`.
-
- @param label The label whose link was selected.
- @param result The custom text checking result.
- */
-- (void)attributedLabel:(BITAttributedLabel *)label
-didSelectLinkWithTextCheckingResult:(NSTextCheckingResult *)result;
-
-///---------------------------------
-/// @name Responding to Long Presses
-///---------------------------------
-
-/**
- * Long-press delegate methods include the CGPoint tapped within the label's coordinate space.
- * This may be useful on iPad to present a popover from a specific origin point.
- */
-
-/**
- Tells the delegate that the user long-pressed a link to a URL.
-
- @param label The label whose link was long pressed.
- @param url The URL for the link.
- @param point the point pressed, in the label's coordinate space
- */
-- (void)attributedLabel:(BITAttributedLabel *)label
-didLongPressLinkWithURL:(NSURL *)url
- atPoint:(CGPoint)point;
-
-/**
- Tells the delegate that the user long-pressed a link to an address.
-
- @param label The label whose link was long pressed.
- @param addressComponents The components of the address for the link.
- @param point the point pressed, in the label's coordinate space
- */
-- (void)attributedLabel:(BITAttributedLabel *)label
-didLongPressLinkWithAddress:(NSDictionary *)addressComponents
- atPoint:(CGPoint)point;
-
-/**
- Tells the delegate that the user long-pressed a link to a phone number.
-
- @param label The label whose link was long pressed.
- @param phoneNumber The phone number for the link.
- @param point the point pressed, in the label's coordinate space
- */
-- (void)attributedLabel:(BITAttributedLabel *)label
-didLongPressLinkWithPhoneNumber:(NSString *)phoneNumber
- atPoint:(CGPoint)point;
-
-
-/**
- Tells the delegate that the user long-pressed a link to a date.
-
- @param label The label whose link was long pressed.
- @param date The date for the selected link.
- @param point the point pressed, in the label's coordinate space
- */
-- (void)attributedLabel:(BITAttributedLabel *)label
-didLongPressLinkWithDate:(NSDate *)date
- atPoint:(CGPoint)point;
-
-
-/**
- Tells the delegate that the user long-pressed a link to a date with a time zone and duration.
-
- @param label The label whose link was long pressed.
- @param date The date for the link.
- @param timeZone The time zone of the date for the link.
- @param duration The duration, in seconds from the date for the link.
- @param point the point pressed, in the label's coordinate space
- */
-- (void)attributedLabel:(BITAttributedLabel *)label
-didLongPressLinkWithDate:(NSDate *)date
- timeZone:(NSTimeZone *)timeZone
- duration:(NSTimeInterval)duration
- atPoint:(CGPoint)point;
-
-
-/**
- Tells the delegate that the user long-pressed a link to transit information.
-
- @param label The label whose link was long pressed.
- @param components A dictionary containing the transit components. The currently supported keys are `NSTextCheckingAirlineKey` and `NSTextCheckingFlightKey`.
- @param point the point pressed, in the label's coordinate space
- */
-- (void)attributedLabel:(BITAttributedLabel *)label
-didLongPressLinkWithTransitInformation:(NSDictionary *)components
- atPoint:(CGPoint)point;
-
-/**
- Tells the delegate that the user long-pressed a link to a text checking result.
-
- @discussion Similar to `-attributedLabel:didSelectLinkWithTextCheckingResult:`, this method is called if a link is long pressed and the delegate does not implement the method corresponding to this type of link.
-
- @param label The label whose link was long pressed.
- @param result The custom text checking result.
- @param point the point pressed, in the label's coordinate space
- */
-- (void)attributedLabel:(BITAttributedLabel *)label
-didLongPressLinkWithTextCheckingResult:(NSTextCheckingResult *)result
- atPoint:(CGPoint)point;
-
-@end
-
-@interface BITAttributedLabelLink : NSObject
-
-typedef void (^BITAttributedLabelLinkBlock) (BITAttributedLabel *, BITAttributedLabelLink *);
-
-/**
- An `NSTextCheckingResult` representing the link's location and type.
- */
-@property (readonly, nonatomic, strong) NSTextCheckingResult *result;
-
-/**
- A dictionary containing the @c NSAttributedString attributes to be applied to the link.
- */
-@property (readonly, nonatomic, copy) NSDictionary *attributes;
-
-/**
- A dictionary containing the @c NSAttributedString attributes to be applied to the link when it is in the active state.
- */
-@property (readonly, nonatomic, copy) NSDictionary *activeAttributes;
-
-/**
- A dictionary containing the @c NSAttributedString attributes to be applied to the link when it is in the inactive state, which is triggered by a change in `tintColor` in iOS 7 and later.
- */
-@property (readonly, nonatomic, copy) NSDictionary *inactiveAttributes;
-
-/**
- Additional information about a link for VoiceOver users. Has default values if the link's @c result is @c NSTextCheckingTypeLink, @c NSTextCheckingTypePhoneNumber, or @c NSTextCheckingTypeDate.
- */
-@property (nonatomic, copy) NSString *accessibilityValue;
-
-/**
- A block called when this link is tapped.
- If non-nil, tapping on this link will call this block instead of the
- @c BITAttributedLabelDelegate tap methods, which will not be called for this link.
- */
-@property (nonatomic, copy) BITAttributedLabelLinkBlock linkTapBlock;
-
-/**
- A block called when this link is long-pressed.
- If non-nil, long pressing on this link will call this block instead of the
- @c BITAttributedLabelDelegate long press methods, which will not be called for this link.
- */
-@property (nonatomic, copy) BITAttributedLabelLinkBlock linkLongPressBlock;
-
-/**
- Initializes a link using the attribute dictionaries specified.
-
- @param attributes The @c attributes property for the link.
- @param activeAttributes The @c activeAttributes property for the link.
- @param inactiveAttributes The @c inactiveAttributes property for the link.
- @param result An @c NSTextCheckingResult representing the link's location and type.
-
- @return The initialized link object.
- */
-- (instancetype)initWithAttributes:(NSDictionary *)attributes
- activeAttributes:(NSDictionary *)activeAttributes
- inactiveAttributes:(NSDictionary *)inactiveAttributes
- textCheckingResult:(NSTextCheckingResult *)result;
-
-/**
- Initializes a link using the attribute dictionaries set on a specified label.
-
- @param label The attributed label from which to inherit attribute dictionaries.
- @param result An @c NSTextCheckingResult representing the link's location and type.
-
- @return The initialized link object.
- */
-- (instancetype)initWithAttributesFromLabel:(BITAttributedLabel*)label
- textCheckingResult:(NSTextCheckingResult *)result;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITAttributedLabel.m b/submodules/HockeySDK-iOS/Classes/BITAttributedLabel.m
deleted file mode 100644
index 0e48cea48b..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITAttributedLabel.m
+++ /dev/null
@@ -1,1850 +0,0 @@
-// TTTAttributedLabel.m
-//
-// Copyright (c) 2011 Mattt Thompson (http://mattt.me)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_FEEDBACK
-
-#import "BITAttributedLabel.h"
-
-#import
-#import
-#import
-
-#define kBITLineBreakWordWrapTextWidthScalingFactor (M_PI / M_E)
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-#pragma clang diagnostic ignored "-Wunused-variable"
-#pragma clang diagnostic ignored "-Wunused-parameter"
-#pragma clang diagnostic ignored "-Wcast-qual"
-#pragma clang diagnostic ignored "-Wdouble-promotion"
-#pragma clang diagnostic ignored "-Wdirect-ivar-access"
-#pragma clang diagnostic ignored "-Wnullable-to-nonnull-conversion"
-#pragma clang diagnostic ignored "-Wvla"
-
-static CGFloat const BITFLOAT_MAX = 100000;
-
-NSString * const kBITStrikeOutAttributeName = @"BITStrikeOutAttribute";
-NSString * const kBITBackgroundFillColorAttributeName = @"BITBackgroundFillColor";
-NSString * const kBITBackgroundFillPaddingAttributeName = @"BITBackgroundFillPadding";
-NSString * const kBITBackgroundStrokeColorAttributeName = @"BITBackgroundStrokeColor";
-NSString * const kBITBackgroundLineWidthAttributeName = @"BITBackgroundLineWidth";
-NSString * const kBITBackgroundCornerRadiusAttributeName = @"BITBackgroundCornerRadius";
-
-static const NSTextAlignment BITTextAlignmentLeft = NSTextAlignmentLeft;
-static const NSTextAlignment BITTextAlignmentCenter = NSTextAlignmentCenter;
-static const NSTextAlignment BITTextAlignmentRight = NSTextAlignmentRight;
-static const NSTextAlignment BITTextAlignmentJustified = NSTextAlignmentJustified;
-static const NSTextAlignment BITTextAlignmentNatural = NSTextAlignmentNatural;
-
-static const NSLineBreakMode BITLineBreakByWordWrapping = NSLineBreakByWordWrapping;
-static const NSLineBreakMode BITLineBreakByCharWrapping = NSLineBreakByCharWrapping;
-static const NSLineBreakMode BITLineBreakByClipping = NSLineBreakByClipping;
-static const NSLineBreakMode BITLineBreakByTruncatingHead = NSLineBreakByTruncatingHead;
-static const NSLineBreakMode BITLineBreakByTruncatingMiddle = NSLineBreakByTruncatingMiddle;
-static const NSLineBreakMode BITLineBreakByTruncatingTail = NSLineBreakByTruncatingTail;
-
-typedef NSTextAlignment BITTextAlignment;
-typedef NSLineBreakMode BITLineBreakMode;
-
-
-static inline CGFLOAT_TYPE CGFloat_ceil(CGFLOAT_TYPE cgfloat) {
-#if CGFLOAT_IS_DOUBLE
- return ceil(cgfloat);
-#else
- return ceilf(cgfloat);
-#endif
-}
-
-static inline CGFLOAT_TYPE CGFloat_floor(CGFLOAT_TYPE cgfloat) {
-#if CGFLOAT_IS_DOUBLE
- return floor(cgfloat);
-#else
- return floorf(cgfloat);
-#endif
-}
-
-static inline CGFLOAT_TYPE CGFloat_round(CGFLOAT_TYPE cgfloat) {
-#if CGFLOAT_IS_DOUBLE
- return round(cgfloat);
-#else
- return roundf(cgfloat);
-#endif
-}
-
-static inline CGFLOAT_TYPE CGFloat_sqrt(CGFLOAT_TYPE cgfloat) {
-#if CGFLOAT_IS_DOUBLE
- return sqrt(cgfloat);
-#else
- return sqrtf(cgfloat);
-#endif
-}
-
-static inline CGFloat BITFlushFactorForTextAlignment(NSTextAlignment textAlignment) {
- switch (textAlignment) {
- case BITTextAlignmentCenter:
- return 0.5f;
- case BITTextAlignmentRight:
- return 1.0f;
- case BITTextAlignmentLeft:
- default:
- return 0.0f;
- }
-}
-
-static inline NSDictionary * NSAttributedStringAttributesFromLabel(BITAttributedLabel *label) {
- NSMutableDictionary *mutableAttributes = [NSMutableDictionary dictionary];
-
- [mutableAttributes setObject:label.font forKey:(NSString *)kCTFontAttributeName];
- [mutableAttributes setObject:label.textColor forKey:(NSString *)kCTForegroundColorAttributeName];
- [mutableAttributes setObject:@(label.kern) forKey:(NSString *)kCTKernAttributeName];
-
- NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
- paragraphStyle.alignment = label.textAlignment;
- paragraphStyle.lineSpacing = label.lineSpacing;
- paragraphStyle.minimumLineHeight = label.minimumLineHeight > 0 ? label.minimumLineHeight : label.font.lineHeight * label.lineHeightMultiple;
- paragraphStyle.maximumLineHeight = label.maximumLineHeight > 0 ? label.maximumLineHeight : label.font.lineHeight * label.lineHeightMultiple;
- paragraphStyle.lineHeightMultiple = label.lineHeightMultiple;
- paragraphStyle.firstLineHeadIndent = label.firstLineIndent;
-
- if (label.numberOfLines == 1) {
- paragraphStyle.lineBreakMode = label.lineBreakMode;
- } else {
- paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
- }
-
- [mutableAttributes setObject:paragraphStyle forKey:(NSString *)kCTParagraphStyleAttributeName];
-
- return [NSDictionary dictionaryWithDictionary:mutableAttributes];
-}
-
-static inline CGColorRef CGColorRefFromColor(id color);
-static inline NSDictionary * convertNSAttributedStringAttributesToCTAttributes(NSDictionary *attributes);
-
-static inline NSAttributedString * NSAttributedStringByScalingFontSize(NSAttributedString *attributedString, CGFloat scale) {
- NSMutableAttributedString *mutableAttributedString = [attributedString mutableCopy];
- [mutableAttributedString enumerateAttribute:(NSString *)kCTFontAttributeName inRange:NSMakeRange(0, [mutableAttributedString length]) options:0 usingBlock:^(id value, NSRange range, BOOL * __unused stop) {
- UIFont *font = (UIFont *)value;
- if (font) {
- NSString *fontName;
- CGFloat pointSize;
-
- if ([font isKindOfClass:[UIFont class]]) {
- fontName = font.fontName;
- pointSize = font.pointSize;
- } else {
- fontName = (NSString *)CFBridgingRelease(CTFontCopyName((__bridge CTFontRef)font, kCTFontPostScriptNameKey));
- pointSize = CTFontGetSize((__bridge CTFontRef)font);
- }
-
- [mutableAttributedString removeAttribute:(NSString *)kCTFontAttributeName range:range];
- CTFontRef fontRef = CTFontCreateWithName((__bridge CFStringRef)fontName, CGFloat_floor(pointSize * scale), NULL);
- [mutableAttributedString addAttribute:(NSString *)kCTFontAttributeName value:(__bridge id)fontRef range:range];
- CFRelease(fontRef);
- }
- }];
-
- return mutableAttributedString;
-}
-
-static inline NSAttributedString * NSAttributedStringBySettingColorFromContext(NSAttributedString *attributedString, UIColor *color) {
- if (!color) {
- return attributedString;
- }
-
- NSMutableAttributedString *mutableAttributedString = [attributedString mutableCopy];
- [mutableAttributedString enumerateAttribute:(NSString *)kCTForegroundColorFromContextAttributeName inRange:NSMakeRange(0, [mutableAttributedString length]) options:0 usingBlock:^(id value, NSRange range, __unused BOOL *stop) {
- BOOL usesColorFromContext = (BOOL)value;
- if (usesColorFromContext) {
- [mutableAttributedString setAttributes:[NSDictionary dictionaryWithObject:color forKey:(NSString *)kCTForegroundColorAttributeName] range:range];
- [mutableAttributedString removeAttribute:(NSString *)kCTForegroundColorFromContextAttributeName range:range];
- }
- }];
-
- return mutableAttributedString;
-}
-
-static inline CGSize CTFramesetterSuggestFrameSizeForAttributedStringWithConstraints(CTFramesetterRef framesetter, NSAttributedString *attributedString, CGSize size, NSUInteger numberOfLines) {
- CFRange rangeToSize = CFRangeMake(0, (CFIndex)[attributedString length]);
- CGSize constraints = CGSizeMake(size.width, BITFLOAT_MAX);
-
- if (numberOfLines == 1) {
- // If there is one line, the size that fits is the full width of the line
- constraints = CGSizeMake(BITFLOAT_MAX, BITFLOAT_MAX);
- } else if (numberOfLines > 0) {
- // If the line count of the label more than 1, limit the range to size to the number of lines that have been set
- CGMutablePathRef path = CGPathCreateMutable();
- CGPathAddRect(path, NULL, CGRectMake(0.0f, 0.0f, constraints.width, BITFLOAT_MAX));
- CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);
- CFArrayRef lines = CTFrameGetLines(frame);
-
- if (CFArrayGetCount(lines) > 0) {
- NSInteger lastVisibleLineIndex = MIN((CFIndex)numberOfLines, CFArrayGetCount(lines)) - 1;
- CTLineRef lastVisibleLine = CFArrayGetValueAtIndex(lines, lastVisibleLineIndex);
-
- CFRange rangeToLayout = CTLineGetStringRange(lastVisibleLine);
- rangeToSize = CFRangeMake(0, rangeToLayout.location + rangeToLayout.length);
- }
-
- CFRelease(frame);
- CGPathRelease(path);
- }
-
- CGSize suggestedSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, rangeToSize, NULL, constraints, NULL);
-
- return CGSizeMake(CGFloat_ceil(suggestedSize.width), CGFloat_ceil(suggestedSize.height));
-}
-
-@interface BITAccessibilityElement : UIAccessibilityElement
-@property (nonatomic, weak) UIView *superview;
-@property (nonatomic, assign) CGRect boundingRect;
-@end
-
-@implementation BITAccessibilityElement
-
-- (CGRect)accessibilityFrame {
- return UIAccessibilityConvertFrameToScreenCoordinates(self.boundingRect, self.superview);
-}
-
-@end
-
-@interface BITAttributedLabel ()
-@property (readwrite, nonatomic, copy) NSAttributedString *inactiveAttributedText;
-@property (readwrite, nonatomic, copy) NSAttributedString *renderedAttributedText;
-@property (readwrite, atomic, strong) NSDataDetector *dataDetector;
-@property (readwrite, nonatomic, strong) NSArray *linkModels;
-@property (readwrite, nonatomic, strong) BITAttributedLabelLink *activeLink;
-@property (readwrite, nonatomic, strong) NSArray *accessibilityElements;
-
-- (void) longPressGestureDidFire:(UILongPressGestureRecognizer *)sender;
-@end
-
-@implementation BITAttributedLabel {
-@private
- BOOL _needsFramesetter;
- CTFramesetterRef _framesetter;
- CTFramesetterRef _highlightFramesetter;
-}
-
-@dynamic text;
-@synthesize attributedText = _attributedText;
-
-#ifndef kCFCoreFoundationVersionNumber_iOS_7_0
-#define kCFCoreFoundationVersionNumber_iOS_7_0 847.2
-#endif
-
-+ (void)load {
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_7_0) {
- Class class = [self class];
- Class superclass = class_getSuperclass(class);
-
- NSArray *strings = @[
- NSStringFromSelector(@selector(isAccessibilityElement)),
- NSStringFromSelector(@selector(accessibilityElementCount)),
- NSStringFromSelector(@selector(accessibilityElementAtIndex:)),
- NSStringFromSelector(@selector(indexOfAccessibilityElement:)),
- ];
-
- for (NSString *string in strings) {
- SEL selector = NSSelectorFromString(string);
- IMP superImplementation = class_getMethodImplementation(superclass, selector);
- Method method = class_getInstanceMethod(class, selector);
- const char *types = method_getTypeEncoding(method);
- class_replaceMethod(class, selector, superImplementation, types);
- }
- }
- });
-}
-
-- (instancetype)initWithFrame:(CGRect)frame {
- self = [super initWithFrame:frame];
- if (!self) {
- return nil;
- }
-
- [self commonInit];
-
- return self;
-}
-
-- (void)commonInit {
- self.userInteractionEnabled = YES;
-#if !TARGET_OS_TV
- self.multipleTouchEnabled = NO;
-#endif
-
- self.textInsets = UIEdgeInsetsZero;
- self.lineHeightMultiple = 1.0f;
-
- self.linkModels = [NSArray array];
-
- self.linkBackgroundEdgeInset = UIEdgeInsetsMake(0.0f, -1.0f, 0.0f, -1.0f);
-
- NSMutableDictionary *mutableLinkAttributes = [NSMutableDictionary dictionary];
- [mutableLinkAttributes setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCTUnderlineStyleAttributeName];
-
- NSMutableDictionary *mutableActiveLinkAttributes = [NSMutableDictionary dictionary];
- [mutableActiveLinkAttributes setObject:[NSNumber numberWithBool:NO] forKey:(NSString *)kCTUnderlineStyleAttributeName];
-
- NSMutableDictionary *mutableInactiveLinkAttributes = [NSMutableDictionary dictionary];
- [mutableInactiveLinkAttributes setObject:[NSNumber numberWithBool:NO] forKey:(NSString *)kCTUnderlineStyleAttributeName];
-
- if ([NSMutableParagraphStyle class]) {
- [mutableLinkAttributes setObject:[UIColor blueColor] forKey:(NSString *)kCTForegroundColorAttributeName];
- [mutableActiveLinkAttributes setObject:[UIColor redColor] forKey:(NSString *)kCTForegroundColorAttributeName];
- [mutableInactiveLinkAttributes setObject:[UIColor grayColor] forKey:(NSString *)kCTForegroundColorAttributeName];
- } else {
- [mutableLinkAttributes setObject:(__bridge id)[[UIColor blueColor] CGColor] forKey:(NSString *)kCTForegroundColorAttributeName];
- [mutableActiveLinkAttributes setObject:(__bridge id)[[UIColor redColor] CGColor] forKey:(NSString *)kCTForegroundColorAttributeName];
- [mutableInactiveLinkAttributes setObject:(__bridge id)[[UIColor grayColor] CGColor] forKey:(NSString *)kCTForegroundColorAttributeName];
- }
-
- self.linkAttributes = [NSDictionary dictionaryWithDictionary:mutableLinkAttributes];
- self.activeLinkAttributes = [NSDictionary dictionaryWithDictionary:mutableActiveLinkAttributes];
- self.inactiveLinkAttributes = [NSDictionary dictionaryWithDictionary:mutableInactiveLinkAttributes];
- _extendsLinkTouchArea = NO;
- _longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self
- action:@selector(longPressGestureDidFire:)];
- self.longPressGestureRecognizer.delegate = self;
- [self addGestureRecognizer:self.longPressGestureRecognizer];
-}
-
-- (void)dealloc {
- if (_framesetter) {
- CFRelease(_framesetter);
- }
-
- if (_highlightFramesetter) {
- CFRelease(_highlightFramesetter);
- }
-
- if (_longPressGestureRecognizer) {
- [self removeGestureRecognizer:_longPressGestureRecognizer];
- }
-}
-
-#pragma mark -
-
-+ (CGSize)sizeThatFitsAttributedString:(NSAttributedString *)attributedString
- withConstraints:(CGSize)size
- limitedToNumberOfLines:(NSUInteger)numberOfLines
-{
- if (!attributedString || attributedString.length == 0) {
- return CGSizeZero;
- }
-
- CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attributedString);
-
- CGSize calculatedSize = CTFramesetterSuggestFrameSizeForAttributedStringWithConstraints(framesetter, attributedString, size, numberOfLines);
-
- CFRelease(framesetter);
-
- return calculatedSize;
-}
-
-#pragma mark -
-
-- (void)setAttributedText:(NSAttributedString *)text {
- if ([text isEqualToAttributedString:_attributedText]) {
- return;
- }
-
- _attributedText = [text copy];
-
- [self setNeedsFramesetter];
- [self setNeedsDisplay];
-
- if ([self respondsToSelector:@selector(invalidateIntrinsicContentSize)]) {
- [self invalidateIntrinsicContentSize];
- }
-
- [super setText:[self.attributedText string]];
-}
-
-- (NSAttributedString *)renderedAttributedText {
- if (!_renderedAttributedText) {
- NSMutableAttributedString *fullString = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
-
- if (self.attributedTruncationToken) {
- [fullString appendAttributedString:self.attributedTruncationToken];
- }
-
- NSAttributedString *string = [[NSAttributedString alloc] initWithAttributedString:fullString];
- self.renderedAttributedText = NSAttributedStringBySettingColorFromContext(string, self.textColor);
- }
-
- return _renderedAttributedText;
-}
-
-- (NSArray *) links {
- return [_linkModels valueForKey:@"result"];
-}
-
-- (void)setLinkModels:(NSArray *)linkModels {
- _linkModels = linkModels;
-
- self.accessibilityElements = nil;
-}
-
-- (void)setNeedsFramesetter {
- // Reset the rendered attributed text so it has a chance to regenerate
- self.renderedAttributedText = nil;
-
- _needsFramesetter = YES;
-}
-
-- (CTFramesetterRef)framesetter {
- if (_needsFramesetter) {
- @synchronized(self) {
- CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)self.renderedAttributedText);
- [self setFramesetter:framesetter];
- [self setHighlightFramesetter:nil];
- _needsFramesetter = NO;
-
- if (framesetter) {
- CFRelease(framesetter);
- }
- }
- }
-
- return _framesetter;
-}
-
-- (void)setFramesetter:(CTFramesetterRef)framesetter {
- if (framesetter) {
- CFRetain(framesetter);
- }
-
- if (_framesetter) {
- CFRelease(_framesetter);
- }
-
- _framesetter = framesetter;
-}
-
-- (CTFramesetterRef)highlightFramesetter {
- return _highlightFramesetter;
-}
-
-- (void)setHighlightFramesetter:(CTFramesetterRef)highlightFramesetter {
- if (highlightFramesetter) {
- CFRetain(highlightFramesetter);
- }
-
- if (_highlightFramesetter) {
- CFRelease(_highlightFramesetter);
- }
-
- _highlightFramesetter = highlightFramesetter;
-}
-
-#pragma mark -
-
-- (void)setEnabledTextCheckingTypes:(NSTextCheckingTypes)enabledTextCheckingTypes {
- if (self.enabledTextCheckingTypes == enabledTextCheckingTypes) {
- return;
- }
-
- _enabledTextCheckingTypes = enabledTextCheckingTypes;
-
- // one detector instance per type (combination), fast reuse e.g. in cells
- static NSMutableDictionary *dataDetectorsByType = nil;
-
- if (!dataDetectorsByType) {
- dataDetectorsByType = [NSMutableDictionary dictionary];
- }
-
- if (enabledTextCheckingTypes) {
- if (![dataDetectorsByType objectForKey:@(enabledTextCheckingTypes)]) {
- NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:enabledTextCheckingTypes
- error:nil];
- if (detector) {
- [dataDetectorsByType setObject:detector forKey:@(enabledTextCheckingTypes)];
- }
- }
- self.dataDetector = [dataDetectorsByType objectForKey:@(enabledTextCheckingTypes)];
- } else {
- self.dataDetector = nil;
- }
-}
-
-- (void)addLink:(BITAttributedLabelLink *)link {
- [self addLinks:@[link]];
-}
-
-- (void)addLinks:(NSArray *)links {
- NSMutableArray *mutableLinkModels = [NSMutableArray arrayWithArray:self.linkModels];
-
- NSMutableAttributedString *mutableAttributedString = [self.attributedText mutableCopy];
-
- for (BITAttributedLabelLink *link in links) {
- if (link.attributes) {
- [mutableAttributedString addAttributes:link.attributes range:link.result.range];
- }
- }
-
- self.attributedText = mutableAttributedString;
- [self setNeedsDisplay];
-
- [mutableLinkModels addObjectsFromArray:links];
-
- self.linkModels = [NSArray arrayWithArray:mutableLinkModels];
-}
-
-- (BITAttributedLabelLink *)addLinkWithTextCheckingResult:(NSTextCheckingResult *)result
- attributes:(NSDictionary *)attributes
-{
- return [self addLinksWithTextCheckingResults:@[result] attributes:attributes].firstObject;
-}
-
-- (NSArray *)addLinksWithTextCheckingResults:(NSArray *)results
- attributes:(NSDictionary *)attributes
-{
- NSMutableArray *links = [NSMutableArray array];
-
- for (NSTextCheckingResult *result in results) {
- NSDictionary *activeAttributes = attributes ? self.activeLinkAttributes : nil;
- NSDictionary *inactiveAttributes = attributes ? self.inactiveLinkAttributes : nil;
-
- BITAttributedLabelLink *link = [[BITAttributedLabelLink alloc] initWithAttributes:attributes
- activeAttributes:activeAttributes
- inactiveAttributes:inactiveAttributes
- textCheckingResult:result];
-
- [links addObject:link];
- }
-
- [self addLinks:links];
-
- return links;
-}
-
-- (BITAttributedLabelLink *)addLinkWithTextCheckingResult:(NSTextCheckingResult *)result {
- return [self addLinkWithTextCheckingResult:result attributes:self.linkAttributes];
-}
-
-- (BITAttributedLabelLink *)addLinkToURL:(NSURL *)url
- withRange:(NSRange)range
-{
- return [self addLinkWithTextCheckingResult:[NSTextCheckingResult linkCheckingResultWithRange:range URL:url]];
-}
-
-- (BITAttributedLabelLink *)addLinkToAddress:(NSDictionary *)addressComponents
- withRange:(NSRange)range
-{
- return [self addLinkWithTextCheckingResult:[NSTextCheckingResult addressCheckingResultWithRange:range components:addressComponents]];
-}
-
-- (BITAttributedLabelLink *)addLinkToPhoneNumber:(NSString *)phoneNumber
- withRange:(NSRange)range
-{
- return [self addLinkWithTextCheckingResult:[NSTextCheckingResult phoneNumberCheckingResultWithRange:range phoneNumber:phoneNumber]];
-}
-
-- (BITAttributedLabelLink *)addLinkToDate:(NSDate *)date
- withRange:(NSRange)range
-{
- return [self addLinkWithTextCheckingResult:[NSTextCheckingResult dateCheckingResultWithRange:range date:date]];
-}
-
-- (BITAttributedLabelLink *)addLinkToDate:(NSDate *)date
- timeZone:(NSTimeZone *)timeZone
- duration:(NSTimeInterval)duration
- withRange:(NSRange)range
-{
- return [self addLinkWithTextCheckingResult:[NSTextCheckingResult dateCheckingResultWithRange:range date:date timeZone:timeZone duration:duration]];
-}
-
-- (BITAttributedLabelLink *)addLinkToTransitInformation:(NSDictionary *)components
- withRange:(NSRange)range
-{
- return [self addLinkWithTextCheckingResult:[NSTextCheckingResult transitInformationCheckingResultWithRange:range components:components]];
-}
-
-#pragma mark -
-
-- (BOOL)containslinkAtPoint:(CGPoint)point {
- return [self linkAtPoint:point] != nil;
-}
-
-- (BITAttributedLabelLink *)linkAtPoint:(CGPoint)point {
-
- // Stop quickly if none of the points to be tested are in the bounds.
- if (!CGRectContainsPoint(CGRectInset(self.bounds, -15.f, -15.f), point) || self.links.count == 0) {
- return nil;
- }
-
- BITAttributedLabelLink *result = [self linkAtCharacterIndex:[self characterIndexAtPoint:point]];
-
- if (!result && self.extendsLinkTouchArea) {
- result = [self linkAtRadius:2.5f aroundPoint:point]
- ?: [self linkAtRadius:5.f aroundPoint:point]
- ?: [self linkAtRadius:7.5f aroundPoint:point]
- ?: [self linkAtRadius:12.5f aroundPoint:point]
- ?: [self linkAtRadius:15.f aroundPoint:point];
- }
-
- return result;
-}
-
-- (BITAttributedLabelLink *)linkAtRadius:(const CGFloat)radius aroundPoint:(CGPoint)point {
- const CGFloat diagonal = CGFloat_sqrt(2 * radius * radius);
- const CGPoint deltas[] = {
- CGPointMake(0, -radius), CGPointMake(0, radius), // Above and below
- CGPointMake(-radius, 0), CGPointMake(radius, 0), // Beside
- CGPointMake(-diagonal, -diagonal), CGPointMake(-diagonal, diagonal),
- CGPointMake(diagonal, diagonal), CGPointMake(diagonal, -diagonal) // Diagonal
- };
- const size_t count = sizeof(deltas) / sizeof(CGPoint);
-
- BITAttributedLabelLink *link = nil;
-
- for (NSUInteger i = 0; i < count && link.result == nil; i ++) {
- CGPoint currentPoint = CGPointMake(point.x + deltas[i].x, point.y + deltas[i].y);
- link = [self linkAtCharacterIndex:[self characterIndexAtPoint:currentPoint]];
- }
-
- return link;
-}
-
-- (BITAttributedLabelLink *)linkAtCharacterIndex:(CFIndex)idx {
- // Do not enumerate if the index is outside of the bounds of the text.
- if (!NSLocationInRange((NSUInteger)idx, NSMakeRange(0, self.attributedText.length))) {
- return nil;
- }
-
- NSEnumerator *enumerator = [self.linkModels reverseObjectEnumerator];
- BITAttributedLabelLink *link = nil;
- while ((link = [enumerator nextObject])) {
- if (NSLocationInRange((NSUInteger)idx, link.result.range)) {
- return link;
- }
- }
-
- return nil;
-}
-
-- (CFIndex)characterIndexAtPoint:(CGPoint)p {
- if (!CGRectContainsPoint(self.bounds, p)) {
- return NSNotFound;
- }
-
- CGRect textRect = [self textRectForBounds:self.bounds limitedToNumberOfLines:self.numberOfLines];
- if (!CGRectContainsPoint(textRect, p)) {
- return NSNotFound;
- }
-
- // Offset tap coordinates by textRect origin to make them relative to the origin of frame
- p = CGPointMake(p.x - textRect.origin.x, p.y - textRect.origin.y);
- // Convert tap coordinates (start at top left) to CT coordinates (start at bottom left)
- p = CGPointMake(p.x, textRect.size.height - p.y);
-
- CGMutablePathRef path = CGPathCreateMutable();
- CGPathAddRect(path, NULL, textRect);
- CTFrameRef frame = CTFramesetterCreateFrame([self framesetter], CFRangeMake(0, (CFIndex)[self.attributedText length]), path, NULL);
- if (frame == NULL) {
- CGPathRelease(path);
- return NSNotFound;
- }
-
- CFArrayRef lines = CTFrameGetLines(frame);
- NSInteger numberOfLines = self.numberOfLines > 0 ? MIN(self.numberOfLines, CFArrayGetCount(lines)) : CFArrayGetCount(lines);
- if (numberOfLines == 0) {
- CFRelease(frame);
- CGPathRelease(path);
- return NSNotFound;
- }
-
- CFIndex idx = NSNotFound;
-
- CGPoint lineOrigins[numberOfLines];
- CTFrameGetLineOrigins(frame, CFRangeMake(0, numberOfLines), lineOrigins);
-
- for (CFIndex lineIndex = 0; lineIndex < numberOfLines; lineIndex++) {
- CGPoint lineOrigin = lineOrigins[lineIndex];
- CTLineRef line = CFArrayGetValueAtIndex(lines, lineIndex);
-
- // Get bounding information of line
- CGFloat ascent = 0.0f, descent = 0.0f, leading = 0.0f;
- CGFloat width = (CGFloat)CTLineGetTypographicBounds(line, &ascent, &descent, &leading);
- CGFloat yMin = (CGFloat)floor(lineOrigin.y - descent);
- CGFloat yMax = (CGFloat)ceil(lineOrigin.y + ascent);
-
- // Apply penOffset using flushFactor for horizontal alignment to set lineOrigin since this is the horizontal offset from drawFramesetter
- CGFloat flushFactor = BITFlushFactorForTextAlignment(self.textAlignment);
- CGFloat penOffset = (CGFloat)CTLineGetPenOffsetForFlush(line, flushFactor, textRect.size.width);
- lineOrigin.x = penOffset;
-
- // Check if we've already passed the line
- if (p.y > yMax) {
- break;
- }
- // Check if the point is within this line vertically
- if (p.y >= yMin) {
- // Check if the point is within this line horizontally
- if (p.x >= lineOrigin.x && p.x <= lineOrigin.x + width) {
- // Convert CT coordinates to line-relative coordinates
- CGPoint relativePoint = CGPointMake(p.x - lineOrigin.x, p.y - lineOrigin.y);
- idx = CTLineGetStringIndexForPosition(line, relativePoint);
- break;
- }
- }
- }
-
- CFRelease(frame);
- CGPathRelease(path);
-
- return idx;
-}
-
-- (CGRect)boundingRectForCharacterRange:(NSRange)range {
- NSMutableAttributedString *mutableAttributedString = [self.attributedText mutableCopy];
-
- NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:mutableAttributedString];
-
- NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
- [textStorage addLayoutManager:layoutManager];
-
- NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:self.bounds.size];
- [layoutManager addTextContainer:textContainer];
-
- NSRange glyphRange;
- [layoutManager characterRangeForGlyphRange:range actualGlyphRange:&glyphRange];
-
- return [layoutManager boundingRectForGlyphRange:glyphRange inTextContainer:textContainer];
-}
-
-- (void)drawFramesetter:(CTFramesetterRef)framesetter
- attributedString:(NSAttributedString *)attributedString
- textRange:(CFRange)textRange
- inRect:(CGRect)rect
- context:(CGContextRef)c
-{
- CGMutablePathRef path = CGPathCreateMutable();
- CGPathAddRect(path, NULL, rect);
- CTFrameRef frame = CTFramesetterCreateFrame(framesetter, textRange, path, NULL);
-
- [self drawBackground:frame inRect:rect context:c];
-
- CFArrayRef lines = CTFrameGetLines(frame);
- NSInteger numberOfLines = self.numberOfLines > 0 ? MIN(self.numberOfLines, CFArrayGetCount(lines)) : CFArrayGetCount(lines);
- BOOL truncateLastLine = (self.lineBreakMode == BITLineBreakByTruncatingHead || self.lineBreakMode == BITLineBreakByTruncatingMiddle || self.lineBreakMode == BITLineBreakByTruncatingTail);
-
- CGPoint lineOrigins[numberOfLines];
- CTFrameGetLineOrigins(frame, CFRangeMake(0, numberOfLines), lineOrigins);
-
- for (CFIndex lineIndex = 0; lineIndex < numberOfLines; lineIndex++) {
- CGPoint lineOrigin = lineOrigins[lineIndex];
- CGContextSetTextPosition(c, lineOrigin.x, lineOrigin.y);
- CTLineRef line = CFArrayGetValueAtIndex(lines, lineIndex);
-
- CGFloat descent = 0.0f;
- CTLineGetTypographicBounds((CTLineRef)line, NULL, &descent, NULL);
-
- // Adjust pen offset for flush depending on text alignment
- CGFloat flushFactor = BITFlushFactorForTextAlignment(self.textAlignment);
-
- if (lineIndex == numberOfLines - 1 && truncateLastLine) {
- // Check if the range of text in the last line reaches the end of the full attributed string
- CFRange lastLineRange = CTLineGetStringRange(line);
-
- if (!(lastLineRange.length == 0 && lastLineRange.location == 0) && lastLineRange.location + lastLineRange.length < textRange.location + textRange.length) {
- // Get correct truncationType and attribute position
- CTLineTruncationType truncationType;
- CFIndex truncationAttributePosition = lastLineRange.location;
- BITLineBreakMode lineBreakMode = self.lineBreakMode;
-
- // Multiple lines, only use UILineBreakModeTailTruncation
- if (numberOfLines != 1) {
- lineBreakMode = BITLineBreakByTruncatingTail;
- }
-
- switch (lineBreakMode) {
- case BITLineBreakByTruncatingHead:
- truncationType = kCTLineTruncationStart;
- break;
- case BITLineBreakByTruncatingMiddle:
- truncationType = kCTLineTruncationMiddle;
- truncationAttributePosition += (lastLineRange.length / 2);
- break;
- case BITLineBreakByTruncatingTail:
- default:
- truncationType = kCTLineTruncationEnd;
- truncationAttributePosition += (lastLineRange.length - 1);
- break;
- }
-
- NSAttributedString *attributedTruncationString = self.attributedTruncationToken;
- if (!attributedTruncationString) {
- NSString *truncationTokenString = @"\u2026"; // Unicode Character 'HORIZONTAL ELLIPSIS' (U+2026)
-
- NSDictionary *truncationTokenStringAttributes = truncationTokenStringAttributes = [attributedString attributesAtIndex:(NSUInteger)truncationAttributePosition effectiveRange:NULL];
-
- attributedTruncationString = [[NSAttributedString alloc] initWithString:truncationTokenString attributes:truncationTokenStringAttributes];
- }
- CTLineRef truncationToken = CTLineCreateWithAttributedString((__bridge CFAttributedStringRef)attributedTruncationString);
-
- // Append truncationToken to the string
- // because if string isn't too long, CT won't add the truncationToken on its own.
- // There is no chance of a double truncationToken because CT only adds the
- // token if it removes characters (and the one we add will go first)
- NSMutableAttributedString *truncationString = [[NSMutableAttributedString alloc] initWithAttributedString:
- [attributedString attributedSubstringFromRange:
- NSMakeRange((NSUInteger)lastLineRange.location,
- (NSUInteger)lastLineRange.length)]];
- if (lastLineRange.length > 0) {
- // Remove any newline at the end (we don't want newline space between the text and the truncation token). There can only be one, because the second would be on the next line.
- unichar lastCharacter = [[truncationString string] characterAtIndex:(NSUInteger)(lastLineRange.length - 1)];
- if ([[NSCharacterSet newlineCharacterSet] characterIsMember:lastCharacter]) {
- [truncationString deleteCharactersInRange:NSMakeRange((NSUInteger)(lastLineRange.length - 1), 1)];
- }
- }
- [truncationString appendAttributedString:attributedTruncationString];
- CTLineRef truncationLine = CTLineCreateWithAttributedString((__bridge CFAttributedStringRef)truncationString);
-
- // Truncate the line in case it is too long.
- CTLineRef truncatedLine = CTLineCreateTruncatedLine(truncationLine, rect.size.width, truncationType, truncationToken);
- if (!truncatedLine) {
- // If the line is not as wide as the truncationToken, truncatedLine is NULL
- truncatedLine = CFRetain(truncationToken);
- }
-
- CGFloat penOffset = (CGFloat)CTLineGetPenOffsetForFlush(truncatedLine, flushFactor, rect.size.width);
- CGContextSetTextPosition(c, penOffset, lineOrigin.y - descent - self.font.descender);
-
- CTLineDraw(truncatedLine, c);
-
- NSRange linkRange;
- if ([attributedTruncationString attribute:NSLinkAttributeName atIndex:0 effectiveRange:&linkRange]) {
- NSRange tokenRange = [truncationString.string rangeOfString:attributedTruncationString.string];
- NSRange tokenLinkRange = NSMakeRange((NSUInteger)(lastLineRange.location+lastLineRange.length)-tokenRange.length, (NSUInteger)tokenRange.length);
-
- [self addLinkToURL:[attributedTruncationString attribute:NSLinkAttributeName atIndex:0 effectiveRange:&linkRange] withRange:tokenLinkRange];
- }
-
- CFRelease(truncatedLine);
- CFRelease(truncationLine);
- CFRelease(truncationToken);
- } else {
- CGFloat penOffset = (CGFloat)CTLineGetPenOffsetForFlush(line, flushFactor, rect.size.width);
- CGContextSetTextPosition(c, penOffset, lineOrigin.y - descent - self.font.descender);
- CTLineDraw(line, c);
- }
- } else {
- CGFloat penOffset = (CGFloat)CTLineGetPenOffsetForFlush(line, flushFactor, rect.size.width);
- CGContextSetTextPosition(c, penOffset, lineOrigin.y - descent - self.font.descender);
- CTLineDraw(line, c);
- }
- }
-
- [self drawStrike:frame inRect:rect context:c];
-
- CFRelease(frame);
- CGPathRelease(path);
-}
-
-- (void)drawBackground:(CTFrameRef)frame
- inRect:(CGRect)rect
- context:(CGContextRef)c
-{
- NSArray *lines = (__bridge NSArray *)CTFrameGetLines(frame);
- CGPoint origins[[lines count]];
- CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), origins);
-
- CFIndex lineIndex = 0;
- for (id line in lines) {
- CGFloat ascent = 0.0f, descent = 0.0f, leading = 0.0f;
- CGFloat width = (CGFloat)CTLineGetTypographicBounds((__bridge CTLineRef)line, &ascent, &descent, &leading) ;
-
- for (id glyphRun in (__bridge NSArray *)CTLineGetGlyphRuns((__bridge CTLineRef)line)) {
- NSDictionary *attributes = (__bridge NSDictionary *)CTRunGetAttributes((__bridge CTRunRef) glyphRun);
- CGColorRef strokeColor = CGColorRefFromColor([attributes objectForKey:kBITBackgroundStrokeColorAttributeName]);
- CGColorRef fillColor = CGColorRefFromColor([attributes objectForKey:kBITBackgroundFillColorAttributeName]);
- UIEdgeInsets fillPadding = [[attributes objectForKey:kBITBackgroundFillPaddingAttributeName] UIEdgeInsetsValue];
- CGFloat cornerRadius = [[attributes objectForKey:kBITBackgroundCornerRadiusAttributeName] floatValue];
- CGFloat lineWidth = [[attributes objectForKey:kBITBackgroundLineWidthAttributeName] floatValue];
-
- if (strokeColor || fillColor) {
- CGRect runBounds = CGRectZero;
- CGFloat runAscent = 0.0f;
- CGFloat runDescent = 0.0f;
-
- runBounds.size.width = (CGFloat)CTRunGetTypographicBounds((__bridge CTRunRef)glyphRun, CFRangeMake(0, 0), &runAscent, &runDescent, NULL) + fillPadding.left + fillPadding.right;
- runBounds.size.height = runAscent + runDescent + fillPadding.top + fillPadding.bottom;
-
- CGFloat xOffset = 0.0f;
- CFRange glyphRange = CTRunGetStringRange((__bridge CTRunRef)glyphRun);
- switch (CTRunGetStatus((__bridge CTRunRef)glyphRun)) {
- case kCTRunStatusRightToLeft:
- xOffset = CTLineGetOffsetForStringIndex((__bridge CTLineRef)line, glyphRange.location + glyphRange.length, NULL);
- break;
- default:
- xOffset = CTLineGetOffsetForStringIndex((__bridge CTLineRef)line, glyphRange.location, NULL);
- break;
- }
-
- runBounds.origin.x = origins[lineIndex].x + rect.origin.x + xOffset - fillPadding.left - rect.origin.x;
- runBounds.origin.y = origins[lineIndex].y + rect.origin.y - fillPadding.bottom - rect.origin.y;
- runBounds.origin.y -= runDescent;
-
- // Don't draw higlightedLinkBackground too far to the right
- if (CGRectGetWidth(runBounds) > width) {
- runBounds.size.width = width;
- }
-
- CGPathRef path = [[UIBezierPath bezierPathWithRoundedRect:CGRectInset(UIEdgeInsetsInsetRect(runBounds, self.linkBackgroundEdgeInset), lineWidth, lineWidth) cornerRadius:cornerRadius] CGPath];
-
- CGContextSetLineJoin(c, kCGLineJoinRound);
-
- if (fillColor) {
- CGContextSetFillColorWithColor(c, fillColor);
- CGContextAddPath(c, path);
- CGContextFillPath(c);
- }
-
- if (strokeColor) {
- CGContextSetStrokeColorWithColor(c, strokeColor);
- CGContextAddPath(c, path);
- CGContextStrokePath(c);
- }
- }
- }
-
- lineIndex++;
- }
-}
-
-- (void)drawStrike:(CTFrameRef)frame
- inRect:(__unused CGRect)rect
- context:(CGContextRef)c
-{
- NSArray *lines = (__bridge NSArray *)CTFrameGetLines(frame);
- CGPoint origins[[lines count]];
- CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), origins);
-
- CFIndex lineIndex = 0;
- for (id line in lines) {
- CGFloat ascent = 0.0f, descent = 0.0f, leading = 0.0f;
- CGFloat width = (CGFloat)CTLineGetTypographicBounds((__bridge CTLineRef)line, &ascent, &descent, &leading) ;
-
- for (id glyphRun in (__bridge NSArray *)CTLineGetGlyphRuns((__bridge CTLineRef)line)) {
- NSDictionary *attributes = (__bridge NSDictionary *)CTRunGetAttributes((__bridge CTRunRef) glyphRun);
- BOOL strikeOut = [[attributes objectForKey:kBITStrikeOutAttributeName] boolValue];
- NSInteger superscriptStyle = [[attributes objectForKey:(id)kCTSuperscriptAttributeName] integerValue];
-
- if (strikeOut) {
- CGRect runBounds = CGRectZero;
- CGFloat runAscent = 0.0f;
- CGFloat runDescent = 0.0f;
-
- runBounds.size.width = (CGFloat)CTRunGetTypographicBounds((__bridge CTRunRef)glyphRun, CFRangeMake(0, 0), &runAscent, &runDescent, NULL);
- runBounds.size.height = runAscent + runDescent;
-
- CGFloat xOffset = 0.0f;
- CFRange glyphRange = CTRunGetStringRange((__bridge CTRunRef)glyphRun);
- switch (CTRunGetStatus((__bridge CTRunRef)glyphRun)) {
- case kCTRunStatusRightToLeft:
- xOffset = CTLineGetOffsetForStringIndex((__bridge CTLineRef)line, glyphRange.location + glyphRange.length, NULL);
- break;
- default:
- xOffset = CTLineGetOffsetForStringIndex((__bridge CTLineRef)line, glyphRange.location, NULL);
- break;
- }
- runBounds.origin.x = origins[lineIndex].x + xOffset;
- runBounds.origin.y = origins[lineIndex].y;
- runBounds.origin.y -= runDescent;
-
- // Don't draw strikeout too far to the right
- if (CGRectGetWidth(runBounds) > width) {
- runBounds.size.width = width;
- }
-
- switch (superscriptStyle) {
- case 1:
- runBounds.origin.y -= runAscent * 0.47f;
- break;
- case -1:
- runBounds.origin.y += runAscent * 0.25f;
- break;
- default:
- break;
- }
-
- // Use text color, or default to black
- id color = [attributes objectForKey:(id)kCTForegroundColorAttributeName];
- if (color) {
- CGContextSetStrokeColorWithColor(c, CGColorRefFromColor(color));
- } else {
- CGContextSetGrayStrokeColor(c, 0.0f, 1.0);
- }
-
- CTFontRef font = CTFontCreateWithName((__bridge CFStringRef)self.font.fontName, self.font.pointSize, NULL);
- CGContextSetLineWidth(c, CTFontGetUnderlineThickness(font));
- CFRelease(font);
-
- CGFloat y = CGFloat_round(runBounds.origin.y + runBounds.size.height / 2.0f);
- CGContextMoveToPoint(c, runBounds.origin.x, y);
- CGContextAddLineToPoint(c, runBounds.origin.x + runBounds.size.width, y);
-
- CGContextStrokePath(c);
- }
- }
-
- lineIndex++;
- }
-}
-
-#pragma mark - BITAttributedLabel
-
-- (void)setText:(id)text {
- NSParameterAssert(!text || [text isKindOfClass:[NSAttributedString class]] || [text isKindOfClass:[NSString class]]);
-
- if ([text isKindOfClass:[NSString class]]) {
- [self setText:text afterInheritingLabelAttributesAndConfiguringWithBlock:nil];
- return;
- }
-
- self.attributedText = text;
- self.activeLink = nil;
-
- self.linkModels = [NSArray array];
- if (text && self.attributedText && self.enabledTextCheckingTypes) {
- __weak __typeof(self)weakSelf = self;
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- __strong __typeof(weakSelf)strongSelf = weakSelf;
-
- NSDataDetector *dataDetector = strongSelf.dataDetector;
- if (dataDetector && [dataDetector respondsToSelector:@selector(matchesInString:options:range:)]) {
- NSArray *results = [dataDetector matchesInString:[(NSAttributedString *)text string] options:0 range:NSMakeRange(0, [(NSAttributedString *)text length])];
- if ([results count] > 0) {
- dispatch_async(dispatch_get_main_queue(), ^{
- if ([[strongSelf.attributedText string] isEqualToString:[(NSAttributedString *)text string]]) {
- [strongSelf addLinksWithTextCheckingResults:results attributes:strongSelf.linkAttributes];
- }
- });
- }
- }
- });
- }
-
- [self.attributedText enumerateAttribute:NSLinkAttributeName inRange:NSMakeRange(0, self.attributedText.length) options:0 usingBlock:^(id value, NSRange range, __unused BOOL *stop) {
- if (value) {
- NSURL *URL = [value isKindOfClass:[NSString class]] ? [NSURL URLWithString:value] : value;
- [self addLinkToURL:URL withRange:range];
- }
- }];
-}
-
-- (void)setText:(id)text
-afterInheritingLabelAttributesAndConfiguringWithBlock:(NSMutableAttributedString * (^)(NSMutableAttributedString *mutableAttributedString))block
-{
- NSMutableAttributedString *mutableAttributedString = nil;
- if ([text isKindOfClass:[NSString class]]) {
- mutableAttributedString = [[NSMutableAttributedString alloc] initWithString:text attributes:NSAttributedStringAttributesFromLabel(self)];
- } else {
- mutableAttributedString = [[NSMutableAttributedString alloc] initWithAttributedString:text];
- [mutableAttributedString addAttributes:NSAttributedStringAttributesFromLabel(self) range:NSMakeRange(0, [mutableAttributedString length])];
- }
-
- if (block) {
- mutableAttributedString = block(mutableAttributedString);
- }
-
- [self setText:mutableAttributedString];
-}
-
-- (void)setActiveLink:(BITAttributedLabelLink *)activeLink {
- _activeLink = activeLink;
-
- NSDictionary *activeAttributes = activeLink.activeAttributes ?: self.activeLinkAttributes;
-
- if (_activeLink && activeAttributes.count > 0) {
- if (!self.inactiveAttributedText) {
- self.inactiveAttributedText = [self.attributedText copy];
- }
-
- NSMutableAttributedString *mutableAttributedString = [self.inactiveAttributedText mutableCopy];
- if (self.activeLink.result.range.length > 0 && NSLocationInRange(NSMaxRange(self.activeLink.result.range) - 1, NSMakeRange(0, [self.inactiveAttributedText length]))) {
- [mutableAttributedString addAttributes:activeAttributes range:self.activeLink.result.range];
- }
-
- self.attributedText = mutableAttributedString;
- [self setNeedsDisplay];
-
- [CATransaction flush];
- } else if (self.inactiveAttributedText) {
- self.attributedText = self.inactiveAttributedText;
- self.inactiveAttributedText = nil;
-
- [self setNeedsDisplay];
- }
-}
-
-- (void)setLinkAttributes:(NSDictionary *)linkAttributes {
- _linkAttributes = convertNSAttributedStringAttributesToCTAttributes(linkAttributes);
-}
-
-- (void)setActiveLinkAttributes:(NSDictionary *)activeLinkAttributes {
- _activeLinkAttributes = convertNSAttributedStringAttributesToCTAttributes(activeLinkAttributes);
-}
-
-- (void)setInactiveLinkAttributes:(NSDictionary *)inactiveLinkAttributes {
- _inactiveLinkAttributes = convertNSAttributedStringAttributesToCTAttributes(inactiveLinkAttributes);
-}
-
-#pragma mark - UILabel
-
-- (void)setHighlighted:(BOOL)highlighted {
- [super setHighlighted:highlighted];
- [self setNeedsDisplay];
-}
-
-// Fixes crash when loading from a UIStoryboard
-- (UIColor *)textColor {
- UIColor *color = [super textColor];
- if (!color) {
- color = [UIColor blackColor];
- }
-
- return color;
-}
-
-- (void)setTextColor:(UIColor *)textColor {
- UIColor *oldTextColor = self.textColor;
- [super setTextColor:textColor];
-
- // Redraw to allow any ColorFromContext attributes a chance to update
- if (textColor != oldTextColor) {
- [self setNeedsFramesetter];
- [self setNeedsDisplay];
- }
-}
-
-- (CGRect)textRectForBounds:(CGRect)bounds
- limitedToNumberOfLines:(NSInteger)numberOfLines
-{
- bounds = UIEdgeInsetsInsetRect(bounds, self.textInsets);
- if (!self.attributedText) {
- return [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines];
- }
-
- CGRect textRect = bounds;
-
- // Calculate height with a minimum of double the font pointSize, to ensure that CTFramesetterSuggestFrameSizeWithConstraints doesn't return CGSizeZero, as it would if textRect height is insufficient.
- textRect.size.height = MAX(self.font.lineHeight * MAX(2, numberOfLines), bounds.size.height);
-
- // Adjust the text to be in the center vertically, if the text size is smaller than bounds
- CGSize textSize = CTFramesetterSuggestFrameSizeWithConstraints([self framesetter], CFRangeMake(0, (CFIndex)[self.attributedText length]), NULL, textRect.size, NULL);
- textSize = CGSizeMake(CGFloat_ceil(textSize.width), CGFloat_ceil(textSize.height)); // Fix for iOS 4, CTFramesetterSuggestFrameSizeWithConstraints sometimes returns fractional sizes
-
- if (textSize.height < bounds.size.height) {
- CGFloat yOffset = 0.0f;
- switch (self.verticalAlignment) {
- case BITAttributedLabelVerticalAlignmentCenter:
- yOffset = CGFloat_floor((bounds.size.height - textSize.height) / 2.0f);
- break;
- case BITAttributedLabelVerticalAlignmentBottom:
- yOffset = bounds.size.height - textSize.height;
- break;
- case BITAttributedLabelVerticalAlignmentTop:
- default:
- break;
- }
-
- textRect.origin.y += yOffset;
- }
-
- return textRect;
-}
-
-- (void)drawTextInRect:(CGRect)rect {
- CGRect insetRect = UIEdgeInsetsInsetRect(rect, self.textInsets);
- if (!self.attributedText) {
- [super drawTextInRect:insetRect];
- return;
- }
-
- NSAttributedString *originalAttributedText = nil;
-
- // Adjust the font size to fit width, if necessarry
- if (self.adjustsFontSizeToFitWidth && self.numberOfLines > 0) {
- // Framesetter could still be working with a resized version of the text;
- // need to reset so we start from the original font size.
- // See #393.
- [self setNeedsFramesetter];
- [self setNeedsDisplay];
-
- if ([self respondsToSelector:@selector(invalidateIntrinsicContentSize)]) {
- [self invalidateIntrinsicContentSize];
- }
-
- // Use infinite width to find the max width, which will be compared to availableWidth if needed.
- CGSize maxSize = (self.numberOfLines > 1) ? CGSizeMake(BITFLOAT_MAX, BITFLOAT_MAX) : CGSizeZero;
-
- CGFloat textWidth = [self sizeThatFits:maxSize].width;
- CGFloat availableWidth = self.frame.size.width * self.numberOfLines;
- if (self.numberOfLines > 1 && self.lineBreakMode == BITLineBreakByWordWrapping) {
- textWidth *= kBITLineBreakWordWrapTextWidthScalingFactor;
- }
-
- if (textWidth > availableWidth && textWidth > 0.0f) {
- originalAttributedText = [self.attributedText copy];
-
- CGFloat scaleFactor = availableWidth / textWidth;
- if ([self respondsToSelector:@selector(minimumScaleFactor)] && self.minimumScaleFactor > scaleFactor) {
- scaleFactor = self.minimumScaleFactor;
- }
-
- self.attributedText = NSAttributedStringByScalingFontSize(self.attributedText, scaleFactor);
- }
- }
-
- CGContextRef c = UIGraphicsGetCurrentContext();
- CGContextSaveGState(c);
- {
- CGContextSetTextMatrix(c, CGAffineTransformIdentity);
-
- // Inverts the CTM to match iOS coordinates (otherwise text draws upside-down; Mac OS's system is different)
- CGContextTranslateCTM(c, 0.0f, insetRect.size.height);
- CGContextScaleCTM(c, 1.0f, -1.0f);
-
- CFRange textRange = CFRangeMake(0, (CFIndex)[self.attributedText length]);
-
- // First, get the text rect (which takes vertical centering into account)
- CGRect textRect = [self textRectForBounds:rect limitedToNumberOfLines:self.numberOfLines];
-
- // CoreText draws its text aligned to the bottom, so we move the CTM here to take our vertical offsets into account
- CGContextTranslateCTM(c, insetRect.origin.x, insetRect.size.height - textRect.origin.y - textRect.size.height);
-
- // Second, trace the shadow before the actual text, if we have one
- if (self.shadowColor && !self.highlighted) {
- CGContextSetShadowWithColor(c, self.shadowOffset, self.shadowRadius, [self.shadowColor CGColor]);
- } else if (self.highlightedShadowColor) {
- CGContextSetShadowWithColor(c, self.highlightedShadowOffset, self.highlightedShadowRadius, [self.highlightedShadowColor CGColor]);
- }
-
- // Finally, draw the text or highlighted text itself (on top of the shadow, if there is one)
- if (self.highlightedTextColor && self.highlighted) {
- NSMutableAttributedString *highlightAttributedString = [self.renderedAttributedText mutableCopy];
- [highlightAttributedString addAttribute:(__bridge NSString *)kCTForegroundColorAttributeName value:(id)[self.highlightedTextColor CGColor] range:NSMakeRange(0, highlightAttributedString.length)];
-
- if (![self highlightFramesetter]) {
- CTFramesetterRef highlightFramesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)highlightAttributedString);
- [self setHighlightFramesetter:highlightFramesetter];
- CFRelease(highlightFramesetter);
- }
-
- [self drawFramesetter:[self highlightFramesetter] attributedString:highlightAttributedString textRange:textRange inRect:textRect context:c];
- } else {
- [self drawFramesetter:[self framesetter] attributedString:self.renderedAttributedText textRange:textRange inRect:textRect context:c];
- }
-
- // If we adjusted the font size, set it back to its original size
- if (originalAttributedText) {
- // Use ivar directly to avoid clearing out framesetter and renderedAttributedText
- _attributedText = originalAttributedText;
- }
- }
- CGContextRestoreGState(c);
-}
-
-#pragma mark - UIAccessibilityElement
-
-- (BOOL)isAccessibilityElement {
- return NO;
-}
-
-- (NSInteger)accessibilityElementCount {
- return (NSInteger)[[self accessibilityElements] count];
-}
-
-- (id)accessibilityElementAtIndex:(NSInteger)index {
- return [[self accessibilityElements] objectAtIndex:(NSUInteger)index];
-}
-
-- (NSInteger)indexOfAccessibilityElement:(id)element {
- return (NSInteger)[[self accessibilityElements] indexOfObject:element];
-}
-
-- (NSArray *)accessibilityElements {
- if (!_accessibilityElements) {
- @synchronized(self) {
- NSMutableArray *mutableAccessibilityItems = [NSMutableArray array];
-
- for (BITAttributedLabelLink *link in self.linkModels) {
-
- if (link.result.range.location == NSNotFound) {
- continue;
- }
-
- NSString *sourceText = [self.text isKindOfClass:[NSString class]] ? self.text : [(NSAttributedString *)self.text string];
-
- NSString *accessibilityLabel = [sourceText substringWithRange:link.result.range];
- NSString *accessibilityValue = link.accessibilityValue;
-
- if (accessibilityLabel) {
- BITAccessibilityElement *linkElement = [[BITAccessibilityElement alloc] initWithAccessibilityContainer:self];
- linkElement.accessibilityTraits = UIAccessibilityTraitLink;
- linkElement.boundingRect = [self boundingRectForCharacterRange:link.result.range];
- linkElement.superview = self;
- linkElement.accessibilityLabel = accessibilityLabel;
-
- if (![accessibilityLabel isEqualToString:accessibilityValue]) {
- linkElement.accessibilityValue = accessibilityValue;
- }
-
- [mutableAccessibilityItems addObject:linkElement];
- }
- }
-
- BITAccessibilityElement *baseElement = [[BITAccessibilityElement alloc] initWithAccessibilityContainer:self];
- baseElement.accessibilityLabel = [super accessibilityLabel];
- baseElement.accessibilityHint = [super accessibilityHint];
- baseElement.accessibilityValue = [super accessibilityValue];
- baseElement.boundingRect = self.bounds;
- baseElement.superview = self;
- baseElement.accessibilityTraits = [super accessibilityTraits];
-
- [mutableAccessibilityItems addObject:baseElement];
-
- self.accessibilityElements = [NSArray arrayWithArray:mutableAccessibilityItems];
- }
- }
-
- return _accessibilityElements;
-}
-
-#pragma mark - UIView
-
-- (CGSize)sizeThatFits:(CGSize)size {
- if (!self.attributedText) {
- return [super sizeThatFits:size];
- } else {
- NSAttributedString *string = [self renderedAttributedText];
-
- CGSize labelSize = CTFramesetterSuggestFrameSizeForAttributedStringWithConstraints([self framesetter], string, size, (NSUInteger)self.numberOfLines);
- labelSize.width += self.textInsets.left + self.textInsets.right;
- labelSize.height += self.textInsets.top + self.textInsets.bottom;
-
- return labelSize;
- }
-}
-
-- (CGSize)intrinsicContentSize {
- // There's an implicit width from the original UILabel implementation
- return [self sizeThatFits:[super intrinsicContentSize]];
-}
-
-- (void)tintColorDidChange {
- if (!self.inactiveLinkAttributes || [self.inactiveLinkAttributes count] == 0) {
- return;
- }
-
- BOOL isInactive = (self.tintAdjustmentMode == UIViewTintAdjustmentModeDimmed);
-
- NSMutableAttributedString *mutableAttributedString = [self.attributedText mutableCopy];
- for (BITAttributedLabelLink *link in self.linkModels) {
- NSDictionary *attributesToRemove = isInactive ? link.attributes : link.inactiveAttributes;
- NSDictionary *attributesToAdd = isInactive ? link.inactiveAttributes : link.attributes;
-
- [attributesToRemove enumerateKeysAndObjectsUsingBlock:^(NSString *name, __unused id value, __unused BOOL *stop) {
- if (NSMaxRange(link.result.range) <= mutableAttributedString.length) {
- [mutableAttributedString removeAttribute:name range:link.result.range];
- }
- }];
-
- if (attributesToAdd) {
- if (NSMaxRange(link.result.range) <= mutableAttributedString.length) {
- [mutableAttributedString addAttributes:attributesToAdd range:link.result.range];
- }
- }
- }
-
- self.attributedText = mutableAttributedString;
-
- [self setNeedsDisplay];
-}
-
-- (UIView *)hitTest:(CGPoint)point
- withEvent:(UIEvent *)event
-{
- if (![self linkAtPoint:point] || !self.userInteractionEnabled || self.hidden || self.alpha < 0.01) {
- return [super hitTest:point withEvent:event];
- }
-
- return self;
-}
-
-#pragma mark - UIResponder
-
-- (BOOL)canBecomeFirstResponder {
- return YES;
-}
-
-- (BOOL)canPerformAction:(SEL)action
- withSender:(__unused id)sender
-{
-#if !TARGET_OS_TV
- return (action == @selector(copy:));
-#else
- return NO;
-#endif
-}
-
-- (void)touchesBegan:(NSSet *)touches
- withEvent:(UIEvent *)event
-{
- UITouch *touch = [touches anyObject];
-
- self.activeLink = [self linkAtPoint:[touch locationInView:self]];
-
- if (!self.activeLink) {
- [super touchesBegan:touches withEvent:event];
- }
-}
-
-- (void)touchesMoved:(NSSet *)touches
- withEvent:(UIEvent *)event
-{
- if (self.activeLink) {
- UITouch *touch = [touches anyObject];
-
- if (self.activeLink != [self linkAtPoint:[touch locationInView:self]]) {
- self.activeLink = nil;
- }
- } else {
- [super touchesMoved:touches withEvent:event];
- }
-}
-
-- (void)touchesEnded:(NSSet *)touches
- withEvent:(UIEvent *)event
-{
- if (self.activeLink) {
- if (self.activeLink.linkTapBlock) {
- self.activeLink.linkTapBlock(self, self.activeLink);
- self.activeLink = nil;
- return;
- }
-
- NSTextCheckingResult *result = self.activeLink.result;
- self.activeLink = nil;
-
- switch (result.resultType) {
- case NSTextCheckingTypeLink:
- if ([self.delegate respondsToSelector:@selector(attributedLabel:didSelectLinkWithURL:)]) {
- [self.delegate attributedLabel:self didSelectLinkWithURL:result.URL];
- return;
- }
- break;
- case NSTextCheckingTypeAddress:
- if ([self.delegate respondsToSelector:@selector(attributedLabel:didSelectLinkWithAddress:)]) {
- [self.delegate attributedLabel:self didSelectLinkWithAddress:result.addressComponents];
- return;
- }
- break;
- case NSTextCheckingTypePhoneNumber:
- if ([self.delegate respondsToSelector:@selector(attributedLabel:didSelectLinkWithPhoneNumber:)]) {
- [self.delegate attributedLabel:self didSelectLinkWithPhoneNumber:result.phoneNumber];
- return;
- }
- break;
- case NSTextCheckingTypeDate:
- if (result.timeZone && [self.delegate respondsToSelector:@selector(attributedLabel:didSelectLinkWithDate:timeZone:duration:)]) {
- [self.delegate attributedLabel:self didSelectLinkWithDate:result.date timeZone:result.timeZone duration:result.duration];
- return;
- } else if ([self.delegate respondsToSelector:@selector(attributedLabel:didSelectLinkWithDate:)]) {
- [self.delegate attributedLabel:self didSelectLinkWithDate:result.date];
- return;
- }
- break;
- case NSTextCheckingTypeTransitInformation:
- if ([self.delegate respondsToSelector:@selector(attributedLabel:didSelectLinkWithTransitInformation:)]) {
- [self.delegate attributedLabel:self didSelectLinkWithTransitInformation:result.components];
- return;
- }
- default:
- break;
- }
-
- // Fallback to `attributedLabel:didSelectLinkWithTextCheckingResult:` if no other delegate method matched.
- if ([self.delegate respondsToSelector:@selector(attributedLabel:didSelectLinkWithTextCheckingResult:)]) {
- [self.delegate attributedLabel:self didSelectLinkWithTextCheckingResult:result];
- }
- } else {
- [super touchesEnded:touches withEvent:event];
- }
-}
-
-- (void)touchesCancelled:(NSSet *)touches
- withEvent:(UIEvent *)event
-{
- if (self.activeLink) {
- self.activeLink = nil;
- } else {
- [super touchesCancelled:touches withEvent:event];
- }
-}
-
-#pragma mark - UIGestureRecognizerDelegate
-
-- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
- return [self containslinkAtPoint:[touch locationInView:self]];
-}
-
-#pragma mark - UILongPressGestureRecognizer
-
-- (void)longPressGestureDidFire:(UILongPressGestureRecognizer *)sender {
- switch (sender.state) {
- case UIGestureRecognizerStateBegan: {
- CGPoint touchPoint = [sender locationInView:self];
- BITAttributedLabelLink *link = [self linkAtPoint:touchPoint];
-
- if (link) {
- if (link.linkLongPressBlock) {
- link.linkLongPressBlock(self, link);
- return;
- }
-
- NSTextCheckingResult *result = link.result;
-
- if (!result) {
- return;
- }
-
- switch (result.resultType) {
- case NSTextCheckingTypeLink:
- if ([self.delegate respondsToSelector:@selector(attributedLabel:didLongPressLinkWithURL:atPoint:)]) {
- [self.delegate attributedLabel:self didLongPressLinkWithURL:result.URL atPoint:touchPoint];
- return;
- }
- break;
- case NSTextCheckingTypeAddress:
- if ([self.delegate respondsToSelector:@selector(attributedLabel:didLongPressLinkWithAddress:atPoint:)]) {
- [self.delegate attributedLabel:self didLongPressLinkWithAddress:result.addressComponents atPoint:touchPoint];
- return;
- }
- break;
- case NSTextCheckingTypePhoneNumber:
- if ([self.delegate respondsToSelector:@selector(attributedLabel:didLongPressLinkWithPhoneNumber:atPoint:)]) {
- [self.delegate attributedLabel:self didLongPressLinkWithPhoneNumber:result.phoneNumber atPoint:touchPoint];
- return;
- }
- break;
- case NSTextCheckingTypeDate:
- if (result.timeZone && [self.delegate respondsToSelector:@selector(attributedLabel:didLongPressLinkWithDate:timeZone:duration:atPoint:)]) {
- [self.delegate attributedLabel:self didLongPressLinkWithDate:result.date timeZone:result.timeZone duration:result.duration atPoint:touchPoint];
- return;
- } else if ([self.delegate respondsToSelector:@selector(attributedLabel:didLongPressLinkWithDate:atPoint:)]) {
- [self.delegate attributedLabel:self didLongPressLinkWithDate:result.date atPoint:touchPoint];
- return;
- }
- break;
- case NSTextCheckingTypeTransitInformation:
- if ([self.delegate respondsToSelector:@selector(attributedLabel:didLongPressLinkWithTransitInformation:atPoint:)]) {
- [self.delegate attributedLabel:self didLongPressLinkWithTransitInformation:result.components atPoint:touchPoint];
- return;
- }
- default:
- break;
- }
-
- // Fallback to `attributedLabel:didLongPressLinkWithTextCheckingResult:atPoint:` if no other delegate method matched.
- if ([self.delegate respondsToSelector:@selector(attributedLabel:didLongPressLinkWithTextCheckingResult:atPoint:)]) {
- [self.delegate attributedLabel:self didLongPressLinkWithTextCheckingResult:result atPoint:touchPoint];
- }
- }
- break;
- }
- default:
- break;
- }
-}
-
-#if !TARGET_OS_TV
-#pragma mark - UIResponderStandardEditActions
-
-- (void)copy:(__unused id)sender {
- [[UIPasteboard generalPasteboard] setString:self.text];
-}
-#endif
-
-#pragma mark - NSCoding
-
-- (void)encodeWithCoder:(NSCoder *)coder {
- [super encodeWithCoder:coder];
-
- [coder encodeObject:@(self.enabledTextCheckingTypes) forKey:NSStringFromSelector(@selector(enabledTextCheckingTypes))];
-
- [coder encodeObject:self.linkModels forKey:NSStringFromSelector(@selector(linkModels))];
- if ([NSMutableParagraphStyle class]) {
- [coder encodeObject:self.linkAttributes forKey:NSStringFromSelector(@selector(linkAttributes))];
- [coder encodeObject:self.activeLinkAttributes forKey:NSStringFromSelector(@selector(activeLinkAttributes))];
- [coder encodeObject:self.inactiveLinkAttributes forKey:NSStringFromSelector(@selector(inactiveLinkAttributes))];
- }
- [coder encodeObject:@(self.shadowRadius) forKey:NSStringFromSelector(@selector(shadowRadius))];
- [coder encodeObject:@(self.highlightedShadowRadius) forKey:NSStringFromSelector(@selector(highlightedShadowRadius))];
- [coder encodeCGSize:self.highlightedShadowOffset forKey:NSStringFromSelector(@selector(highlightedShadowOffset))];
- [coder encodeObject:self.highlightedShadowColor forKey:NSStringFromSelector(@selector(highlightedShadowColor))];
- [coder encodeObject:@(self.kern) forKey:NSStringFromSelector(@selector(kern))];
- [coder encodeObject:@(self.firstLineIndent) forKey:NSStringFromSelector(@selector(firstLineIndent))];
- [coder encodeObject:@(self.lineSpacing) forKey:NSStringFromSelector(@selector(lineSpacing))];
- [coder encodeObject:@(self.lineHeightMultiple) forKey:NSStringFromSelector(@selector(lineHeightMultiple))];
- [coder encodeUIEdgeInsets:self.textInsets forKey:NSStringFromSelector(@selector(textInsets))];
- [coder encodeInteger:self.verticalAlignment forKey:NSStringFromSelector(@selector(verticalAlignment))];
-
- [coder encodeObject:self.attributedTruncationToken forKey:NSStringFromSelector(@selector(attributedTruncationToken))];
-
- [coder encodeObject:NSStringFromUIEdgeInsets(self.linkBackgroundEdgeInset) forKey:NSStringFromSelector(@selector(linkBackgroundEdgeInset))];
- [coder encodeObject:self.attributedText forKey:NSStringFromSelector(@selector(attributedText))];
- [coder encodeObject:self.text forKey:NSStringFromSelector(@selector(text))];
-}
-
-- (id)initWithCoder:(NSCoder *)coder {
- self = [super initWithCoder:coder];
- if (!self) {
- return nil;
- }
-
- [self commonInit];
-
- if ([coder containsValueForKey:NSStringFromSelector(@selector(enabledTextCheckingTypes))]) {
- self.enabledTextCheckingTypes = [[coder decodeObjectForKey:NSStringFromSelector(@selector(enabledTextCheckingTypes))] unsignedLongLongValue];
- }
-
- if ([NSMutableParagraphStyle class]) {
- if ([coder containsValueForKey:NSStringFromSelector(@selector(linkAttributes))]) {
- self.linkAttributes = [coder decodeObjectForKey:NSStringFromSelector(@selector(linkAttributes))];
- }
-
- if ([coder containsValueForKey:NSStringFromSelector(@selector(activeLinkAttributes))]) {
- self.activeLinkAttributes = [coder decodeObjectForKey:NSStringFromSelector(@selector(activeLinkAttributes))];
- }
-
- if ([coder containsValueForKey:NSStringFromSelector(@selector(inactiveLinkAttributes))]) {
- self.inactiveLinkAttributes = [coder decodeObjectForKey:NSStringFromSelector(@selector(inactiveLinkAttributes))];
- }
- }
-
- if ([coder containsValueForKey:NSStringFromSelector(@selector(links))]) {
- NSArray *oldLinks = [coder decodeObjectForKey:NSStringFromSelector(@selector(links))];
- [self addLinksWithTextCheckingResults:oldLinks attributes:nil];
- }
-
- if ([coder containsValueForKey:NSStringFromSelector(@selector(linkModels))]) {
- self.linkModels = [coder decodeObjectForKey:NSStringFromSelector(@selector(linkModels))];
- }
-
- if ([coder containsValueForKey:NSStringFromSelector(@selector(shadowRadius))]) {
- self.shadowRadius = [[coder decodeObjectForKey:NSStringFromSelector(@selector(shadowRadius))] floatValue];
- }
-
- if ([coder containsValueForKey:NSStringFromSelector(@selector(highlightedShadowRadius))]) {
- self.highlightedShadowRadius = [[coder decodeObjectForKey:NSStringFromSelector(@selector(highlightedShadowRadius))] floatValue];
- }
-
- if ([coder containsValueForKey:NSStringFromSelector(@selector(highlightedShadowOffset))]) {
- self.highlightedShadowOffset = [coder decodeCGSizeForKey:NSStringFromSelector(@selector(highlightedShadowOffset))];
- }
-
- if ([coder containsValueForKey:NSStringFromSelector(@selector(highlightedShadowColor))]) {
- self.highlightedShadowColor = [coder decodeObjectForKey:NSStringFromSelector(@selector(highlightedShadowColor))];
- }
-
- if ([coder containsValueForKey:NSStringFromSelector(@selector(kern))]) {
- self.kern = [[coder decodeObjectForKey:NSStringFromSelector(@selector(kern))] floatValue];
- }
-
- if ([coder containsValueForKey:NSStringFromSelector(@selector(firstLineIndent))]) {
- self.firstLineIndent = [[coder decodeObjectForKey:NSStringFromSelector(@selector(firstLineIndent))] floatValue];
- }
-
- if ([coder containsValueForKey:NSStringFromSelector(@selector(lineSpacing))]) {
- self.lineSpacing = [[coder decodeObjectForKey:NSStringFromSelector(@selector(lineSpacing))] floatValue];
- }
-
- if ([coder containsValueForKey:NSStringFromSelector(@selector(minimumLineHeight))]) {
- self.minimumLineHeight = [[coder decodeObjectForKey:NSStringFromSelector(@selector(minimumLineHeight))] floatValue];
- }
-
- if ([coder containsValueForKey:NSStringFromSelector(@selector(maximumLineHeight))]) {
- self.maximumLineHeight = [[coder decodeObjectForKey:NSStringFromSelector(@selector(maximumLineHeight))] floatValue];
- }
-
- if ([coder containsValueForKey:NSStringFromSelector(@selector(lineHeightMultiple))]) {
- self.lineHeightMultiple = [[coder decodeObjectForKey:NSStringFromSelector(@selector(lineHeightMultiple))] floatValue];
- }
-
- if ([coder containsValueForKey:NSStringFromSelector(@selector(textInsets))]) {
- self.textInsets = [coder decodeUIEdgeInsetsForKey:NSStringFromSelector(@selector(textInsets))];
- }
-
- if ([coder containsValueForKey:NSStringFromSelector(@selector(verticalAlignment))]) {
- self.verticalAlignment = [coder decodeIntegerForKey:NSStringFromSelector(@selector(verticalAlignment))];
- }
-
- if ([coder containsValueForKey:NSStringFromSelector(@selector(attributedTruncationToken))]) {
- self.attributedTruncationToken = [coder decodeObjectForKey:NSStringFromSelector(@selector(attributedTruncationToken))];
- }
-
- if ([coder containsValueForKey:NSStringFromSelector(@selector(linkBackgroundEdgeInset))]) {
- self.linkBackgroundEdgeInset = UIEdgeInsetsFromString([coder decodeObjectForKey:NSStringFromSelector(@selector(linkBackgroundEdgeInset))]);
- }
-
- if ([coder containsValueForKey:NSStringFromSelector(@selector(attributedText))]) {
- self.attributedText = [coder decodeObjectForKey:NSStringFromSelector(@selector(attributedText))];
- } else {
- self.text = super.text;
- }
-
- return self;
-}
-
-@end
-
-#pragma mark - BITAttributedLabelLink
-
-@implementation BITAttributedLabelLink
-
-- (instancetype)initWithAttributes:(NSDictionary *)attributes
- activeAttributes:(NSDictionary *)activeAttributes
- inactiveAttributes:(NSDictionary *)inactiveAttributes
- textCheckingResult:(NSTextCheckingResult *)result {
-
- if ((self = [super init])) {
- _result = result;
- _attributes = [attributes copy];
- _activeAttributes = [activeAttributes copy];
- _inactiveAttributes = [inactiveAttributes copy];
- }
-
- return self;
-}
-
-- (instancetype)initWithAttributesFromLabel:(BITAttributedLabel*)label
- textCheckingResult:(NSTextCheckingResult *)result {
-
- return [self initWithAttributes:label.linkAttributes
- activeAttributes:label.activeLinkAttributes
- inactiveAttributes:label.inactiveLinkAttributes
- textCheckingResult:result];
-}
-
-#pragma mark - Accessibility
-
-- (NSString *) accessibilityValue {
- if ([_accessibilityValue length] == 0) {
- switch (self.result.resultType) {
- case NSTextCheckingTypeLink:
- _accessibilityValue = self.result.URL.absoluteString;
- break;
- case NSTextCheckingTypePhoneNumber:
- _accessibilityValue = self.result.phoneNumber;
- break;
- case NSTextCheckingTypeDate:
- _accessibilityValue = [NSDateFormatter localizedStringFromDate:self.result.date
- dateStyle:NSDateFormatterLongStyle
- timeStyle:NSDateFormatterLongStyle];
- break;
- default:
- break;
- }
- }
-
- return _accessibilityValue;
-}
-
-#pragma mark - NSCoding
-
-- (void)encodeWithCoder:(NSCoder *)aCoder {
- [aCoder encodeObject:self.result forKey:NSStringFromSelector(@selector(result))];
- [aCoder encodeObject:self.attributes forKey:NSStringFromSelector(@selector(attributes))];
- [aCoder encodeObject:self.activeAttributes forKey:NSStringFromSelector(@selector(activeAttributes))];
- [aCoder encodeObject:self.inactiveAttributes forKey:NSStringFromSelector(@selector(inactiveAttributes))];
- [aCoder encodeObject:self.accessibilityValue forKey:NSStringFromSelector(@selector(accessibilityValue))];
-}
-
-- (id)initWithCoder:(NSCoder *)aDecoder {
- if ((self = [super init])) {
- _result = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(result))];
- _attributes = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(attributes))];
- _activeAttributes = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(activeAttributes))];
- _inactiveAttributes = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(inactiveAttributes))];
- self.accessibilityValue = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(accessibilityValue))];
- }
-
- return self;
-}
-
-@end
-
-#pragma mark -
-
-static inline CGColorRef CGColorRefFromColor(id color) {
- return [color isKindOfClass:[UIColor class]] ? [color CGColor] : (__bridge CGColorRef)color;
-}
-
-static inline CTFontRef CTFontRefFromUIFont(UIFont * font) {
- CTFontRef ctfont = CTFontCreateWithName((__bridge CFStringRef)font.fontName, font.pointSize, NULL);
- return CFAutorelease(ctfont);
-}
-
-static inline NSDictionary * convertNSAttributedStringAttributesToCTAttributes(NSDictionary *attributes) {
- if (!attributes) return nil;
-
- NSMutableDictionary *mutableAttributes = [NSMutableDictionary dictionary];
-
- NSDictionary *NSToCTAttributeNamesMap = @{
- NSFontAttributeName: (NSString *)kCTFontAttributeName,
- NSBackgroundColorAttributeName: (NSString *)kBITBackgroundFillColorAttributeName,
- NSForegroundColorAttributeName: (NSString *)kCTForegroundColorAttributeName,
- NSUnderlineColorAttributeName: (NSString *)kCTUnderlineColorAttributeName,
- NSUnderlineStyleAttributeName: (NSString *)kCTUnderlineStyleAttributeName,
- NSStrokeWidthAttributeName: (NSString *)kCTStrokeWidthAttributeName,
- NSStrokeColorAttributeName: (NSString *)kCTStrokeWidthAttributeName,
- NSKernAttributeName: (NSString *)kCTKernAttributeName,
- NSLigatureAttributeName: (NSString *)kCTLigatureAttributeName
- };
-
- [attributes enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
- key = [NSToCTAttributeNamesMap objectForKey:key] ? : key;
-
- if (![NSMutableParagraphStyle class]) {
- if ([value isKindOfClass:[UIFont class]]) {
- value = (__bridge id)CTFontRefFromUIFont(value);
- } else if ([value isKindOfClass:[UIColor class]]) {
- value = (__bridge id)((UIColor *)value).CGColor;
- }
- }
-
- [mutableAttributes setObject:value forKey:key];
- }];
-
- return [NSDictionary dictionaryWithDictionary:mutableAttributes];
-}
-
-#pragma clang diagnostic pop
-
-#endif
diff --git a/submodules/HockeySDK-iOS/Classes/BITAuthenticationViewController.h b/submodules/HockeySDK-iOS/Classes/BITAuthenticationViewController.h
deleted file mode 100644
index 2eac237f18..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITAuthenticationViewController.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Author: Stephan Diederich
- *
- * Copyright (c) 2013-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import
-@protocol BITAuthenticationViewControllerDelegate;
-@class BITAuthenticator;
-@class BITHockeyAppClient;
-
-/**
- * View controller handling user interaction for `BITAuthenticator`
- */
-@interface BITAuthenticationViewController : UITableViewController
-
-- (instancetype) initWithDelegate:(id) delegate;
-
-/**
- * can be set to YES to show an additional button + description text
- * and allowing to login via external website/UDID.
- * if this is set to yes, no further email/password options are shown
- *
- * defaults to NO
- */
-@property (nonatomic, assign) BOOL showsLoginViaWebButton;
-
-/**
- * Description shown on top of view. Should tell why this view
- * was presented and what's next.
- */
-@property (nonatomic, copy) NSString* tableViewTitle;
-
-/**
- * can be set to YES to also require the users password
- *
- * defaults to NO
- */
-@property (nonatomic, assign) BOOL requirePassword;
-
-@property (nonatomic, weak) id delegate;
-
-/**
- * allows to pre-fill the email-addy
- */
-@property (nonatomic, copy) NSString* email;
-@end
-
-/**
- * BITAuthenticationViewController protocol
- */
-@protocol BITAuthenticationViewControllerDelegate
-
-- (void) authenticationViewControllerDidTapWebButton:(UIViewController*) viewController;
-
-/**
- * called when the user wants to login
- *
- * @param viewController the delegating view controller
- * @param email the content of the email-field
- * @param password the content of the password-field (if existent)
- * @param completion Must be called by the delegate once the auth-task completed
- * This view controller shows an activity-indicator in between and blocks
- * the UI. if succeeded is NO, it shows an alertView presenting the error
- * given by the completion block
- */
-- (void) authenticationViewController:(UIViewController*) viewController
- handleAuthenticationWithEmail:(NSString*) email
- password:(NSString*) password
- completion:(void(^)(BOOL succeeded, NSError *error)) completion;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITAuthenticationViewController.m b/submodules/HockeySDK-iOS/Classes/BITAuthenticationViewController.m
deleted file mode 100644
index bcf765683a..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITAuthenticationViewController.m
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Author: Stephan Diederich
- *
- * Copyright (c) 2013-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_AUTHENTICATOR
-
-#import "BITAuthenticationViewController.h"
-#import "BITAuthenticator_Private.h"
-#import "HockeySDKPrivate.h"
-#import "BITHockeyHelper.h"
-#import "BITHockeyAppClient.h"
-#import
-
-@interface BITAuthenticationViewController ()
-
-@property (nonatomic, weak) UITextField *emailField;
-@property (nonatomic, copy) NSString *password;
-
-@end
-
-@implementation BITAuthenticationViewController
-
-- (instancetype) initWithDelegate:(id)delegate {
- self = [super initWithStyle:UITableViewStyleGrouped];
- if (self) {
- self.title = BITHockeyLocalizedString(@"HockeyAuthenticatorViewControllerTitle");
- _delegate = delegate;
- }
- return self;
-}
-
-#pragma mark - view lifecycle
-
-- (void)viewDidLoad {
- [super viewDidLoad];
-
- [self.tableView setScrollEnabled:NO];
-
- [self updateWebLoginButton];
-}
-
-- (void)viewWillAppear:(BOOL)animated {
- [super viewWillAppear:animated];
-
- [self updateBarButtons];
-
- self.navigationItem.rightBarButtonItem.enabled = [self allRequiredFieldsEntered];
-}
-
-#pragma mark - Property overrides
-
-- (void) updateBarButtons {
- if(self.showsLoginViaWebButton) {
- self.navigationItem.rightBarButtonItem = nil;
- } else {
- self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
- target:self
- action:@selector(saveAction:)];
- }
-}
-
-- (void)setShowsLoginViaWebButton:(BOOL)showsLoginViaWebButton {
- if(_showsLoginViaWebButton != showsLoginViaWebButton) {
- _showsLoginViaWebButton = showsLoginViaWebButton;
- if(self.isViewLoaded) {
- [self.tableView reloadData];
- [self updateBarButtons];
- [self updateWebLoginButton];
- }
- }
-}
-
-- (void) updateWebLoginButton {
- if(self.showsLoginViaWebButton) {
- static const CGFloat kFooterHeight = 60.0;
- UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0,
- CGRectGetWidth(self.tableView.bounds),
- kFooterHeight)];
- UIButton *button = [UIButton buttonWithType:kBITButtonTypeSystem];
- [button setTitle:BITHockeyLocalizedString(@"HockeyAuthenticationViewControllerWebLoginButtonTitle") forState:UIControlStateNormal];
- CGSize buttonSize = [button sizeThatFits:CGSizeMake(CGRectGetWidth(self.tableView.bounds),
- kFooterHeight)];
- button.frame = CGRectMake(floor((CGRectGetWidth(containerView.bounds) - buttonSize.width) / (CGFloat)2.0),
- floor((kFooterHeight - buttonSize.height) / (CGFloat)2.0),
- buttonSize.width,
- buttonSize.height);
- button.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
- if ([UIButton instancesRespondToSelector:(NSSelectorFromString(@"setTintColor:"))]) {
- [button setTitleColor:BIT_RGBCOLOR(0, 122, 255) forState:UIControlStateNormal];
- }
- [containerView addSubview:button];
- [button addTarget:self
- action:@selector(handleWebLoginButton:)
- forControlEvents:UIControlEventTouchUpInside];
- self.tableView.tableFooterView = containerView;
- } else {
- self.tableView.tableFooterView = nil;
- }
-}
-
-- (IBAction) handleWebLoginButton:(id) __unused sender {
- [self.delegate authenticationViewControllerDidTapWebButton:self];
-}
-
-- (void)setEmail:(NSString *)email {
- _email = email;
- if(self.isViewLoaded) {
- self.emailField.text = email;
- }
-}
-
-- (void)setTableViewTitle:(NSString *)viewDescription {
- _tableViewTitle = [viewDescription copy];
- if(self.isViewLoaded) {
- [self.tableView reloadData];
- }
-}
-#pragma mark - UIViewController Rotation
-
--(UIInterfaceOrientationMask)supportedInterfaceOrientations {
- return UIInterfaceOrientationMaskAll;
-}
-
-#pragma mark - Private methods
-- (BOOL)allRequiredFieldsEntered {
- if (self.requirePassword && [self.password length] == 0)
- return NO;
-
- if (![self.email length] || !bit_validateEmail(self.email))
- return NO;
-
- return YES;
-}
-
-#pragma mark - Table view data source
-
-- (NSInteger)numberOfSectionsInTableView:(UITableView *) __unused tableView {
- return 2;
-}
-
-- (NSInteger)tableView:(UITableView *) __unused tableView numberOfRowsInSection:(NSInteger)section {
- if (section == 0) return 0;
-
- if(self.showsLoginViaWebButton) {
- return 0;
- } else {
- NSInteger rows = 1;
-
- if ([self requirePassword]) rows ++;
-
- return rows;
- }
-}
-
-- (NSString *)tableView:(UITableView *) __unused tableView titleForFooterInSection:(NSInteger)section {
- if (section == 0) {
- return self.tableViewTitle;
- }
-
- return nil;
-}
-
-- (UITableViewCell *)tableView:(UITableView *) __unused tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
- static NSString *CellIdentifier = @"InputCell";
-
- UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
- if (cell == nil) {
- cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
-
- cell.accessoryType = UITableViewCellAccessoryNone;
- cell.selectionStyle = UITableViewCellSelectionStyleNone;
- cell.backgroundColor = [UIColor whiteColor];
-
- UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(130, 11, self.view.frame.size.width - 130 - 25, 24)];
- if (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) {
- textField.autoresizingMask = UIViewAutoresizingFlexibleWidth;
- }
- textField.adjustsFontSizeToFitWidth = YES;
- textField.textColor = [UIColor blackColor];
- textField.backgroundColor = [UIColor lightGrayColor];
-
- if (0 == [indexPath row]) {
- textField.placeholder = BITHockeyLocalizedString(@"HockeyAuthenticationViewControllerEmailPlaceholder");
- textField.accessibilityHint = BITHockeyLocalizedString(@"HockeyAccessibilityHintRequired");
- textField.text = self.email;
- self.emailField = textField;
-
- textField.keyboardType = UIKeyboardTypeEmailAddress;
- if ([self requirePassword])
- textField.returnKeyType = UIReturnKeyNext;
- else
- textField.returnKeyType = UIReturnKeyDone;
-
- [textField addTarget:self action:@selector(userEmailEntered:) forControlEvents:UIControlEventEditingChanged];
- [textField becomeFirstResponder];
- } else {
- textField.placeholder = BITHockeyLocalizedString(@"HockeyAuthenticationViewControllerPasswordPlaceholder");
- textField.text = self.password;
-
- textField.keyboardType = UIKeyboardTypeDefault;
- textField.returnKeyType = UIReturnKeyDone;
- textField.secureTextEntry = YES;
- [textField addTarget:self action:@selector(userPasswordEntered:) forControlEvents:UIControlEventEditingChanged];
- }
-
- textField.backgroundColor = [UIColor whiteColor];
- textField.autocorrectionType = UITextAutocorrectionTypeNo;
- textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
- textField.textAlignment = NSTextAlignmentLeft;
- textField.delegate = self;
- textField.tag = indexPath.row;
-
- textField.clearButtonMode = UITextFieldViewModeWhileEditing;
- [textField setEnabled: YES];
-
- [cell addSubview:textField];
- }
-
- if (0 == [indexPath row]) {
- cell.textLabel.text = BITHockeyLocalizedString(@"HockeyAuthenticationViewControllerEmailDescription");
- } else {
- cell.textLabel.text = BITHockeyLocalizedString(@"HockeyAuthenticationViewControllerPasswordDescription");
- }
-
- return cell;
-}
-
-
-- (void)userEmailEntered:(id)sender {
- self.email = [(UITextField *)sender text];
-
- self.navigationItem.rightBarButtonItem.enabled = [self allRequiredFieldsEntered];
-}
-
-- (void)userPasswordEntered:(id)sender {
- self.password = [(UITextField *)sender text];
-
- self.navigationItem.rightBarButtonItem.enabled = [self allRequiredFieldsEntered];
-}
-
-#pragma mark - UITextFieldDelegate
-
-- (BOOL)textFieldShouldReturn:(UITextField *)textField {
- NSInteger nextTag = textField.tag + 1;
-
- UIResponder* nextResponder = [self.view viewWithTag:nextTag];
- if (nextResponder) {
- [nextResponder becomeFirstResponder];
- } else {
- if ([self allRequiredFieldsEntered]) {
- if ([textField isFirstResponder])
- [textField resignFirstResponder];
-
- [self saveAction:nil];
- }
- }
- return NO;
-}
-
-#pragma mark - Actions
-- (void)saveAction:(id) __unused sender {
- [self setLoginUIEnabled:NO];
-
- __weak typeof(self) weakSelf = self;
- [self.delegate authenticationViewController:self
- handleAuthenticationWithEmail:self.email
- password:self.password
- completion:^(BOOL succeeded, NSError *error) {
- if(succeeded) {
- //controller should dismiss us shortly..
- } else {
- dispatch_async(dispatch_get_main_queue(), ^{
- UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil
- message:error.localizedDescription
- preferredStyle:UIAlertControllerStyleAlert];
- UIAlertAction *okAction = [BITAlertAction actionWithTitle:BITHockeyLocalizedString(@"OK")
- style:UIAlertActionStyleCancel
- handler:^(UIAlertAction __unused *action) {}];
- [alertController addAction:okAction];
- [self presentViewController:alertController animated:YES completion:nil];
- typeof(self) strongSelf = weakSelf;
- [strongSelf setLoginUIEnabled:YES];
- });
- }
- }];
-}
-
-- (void) setLoginUIEnabled:(BOOL) enabled {
- self.navigationItem.rightBarButtonItem.enabled = enabled;
- self.tableView.userInteractionEnabled = enabled;
-}
-
-@end
-
-#endif /* HOCKEYSDK_FEATURE_AUTHENTICATOR */
diff --git a/submodules/HockeySDK-iOS/Classes/BITAuthenticator.h b/submodules/HockeySDK-iOS/Classes/BITAuthenticator.h
deleted file mode 100644
index a1eaac1ad6..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITAuthenticator.h
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * Author: Stephan Diederich, Andreas Linde
- *
- * Copyright (c) 2013-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import
-
-#import "BITHockeyBaseManager.h"
-
-/**
- * Identification Types
- */
-typedef NS_ENUM(NSUInteger, BITAuthenticatorIdentificationType) {
- /**
- * Assigns this app an anonymous user id.
- *
- * The user will not be asked anything and an anonymous ID will be generated.
- * This helps identifying this installation being unique but HockeyApp won't be able
- * to identify who actually is running this installation and on which device
- * the app is installed.
- */
- BITAuthenticatorIdentificationTypeAnonymous,
- /**
- * Ask for the HockeyApp account email
- *
- * This will present a user interface requesting the user to provide their
- * HockeyApp user email address.
- *
- * The provided email address has to match an email address of a registered
- * HockeyApp user who is a member or tester of the app
- */
- BITAuthenticatorIdentificationTypeHockeyAppEmail,
- /**
- * Ask for the HockeyApp account by email and password
- *
- * This will present a user interface requesting the user to provide their
- * HockeyApp user credentials.
- *
- * The provided user account has to match a registered HockeyApp user who is
- * a member or tester of the app
- */
- BITAuthenticatorIdentificationTypeHockeyAppUser,
- /**
- * Identifies the current device
- *
- * This will open the HockeyApp web page on the device in Safari and request the user
- * to submit the device's unique identifier to the app. If the web page session is not aware
- * of the current devices UDID, it will request the user to install the HockeyApp web clip
- * which will provide the UDID to users session in the browser.
- *
- * This requires the app to register an URL scheme. See the linked property and methods
- * for further documentation on this.
- */
- BITAuthenticatorIdentificationTypeDevice,
- /**
- * Ask for the HockeyApp account email.
- *
- * This will present a user interface requesting the user to start a Safari based
- * flow to login to HockeyApp (if not already logged in) and to share the hockeyapp
- * account's email.
- *
- * If restrictApplicationUsage is enabled, the provided user account has to match a
- * registered HockeyApp user who is a member or tester of the app.
- * For identification purpose any HockeyApp user is allowed.
- */
- BITAuthenticatorIdentificationTypeWebAuth,
-};
-
-/**
- * Restriction enforcement styles
- *
- * Specifies how often the Authenticator checks if the user is allowed to use
- * this app.
- */
-typedef NS_ENUM(NSUInteger, BITAuthenticatorAppRestrictionEnforcementFrequency) {
- /**
- * Checks if the user is allowed to use the app at the first time a version is started
- */
- BITAuthenticatorAppRestrictionEnforcementOnFirstLaunch,
- /**
- * Checks if the user is allowed to use the app every time the app becomes active
- */
- BITAuthenticatorAppRestrictionEnforcementOnAppActive,
-};
-
-@protocol BITAuthenticatorDelegate;
-
-
-/**
- * Identify and authenticate users of Ad-Hoc or Enterprise builds
- *
- * `BITAuthenticator` serves 2 purposes:
- *
- * 1. Identifying who is running your Ad-Hoc or Enterprise builds
- * `BITAuthenticator` provides an identifier for the rest of the HockeySDK
- * to work with, e.g. in-app update checks and crash reports.
- *
- * 2. Optional regular checking if an identified user is still allowed
- * to run this application. The `BITAuthenticator` can be used to make
- * sure only users who are testers of your app are allowed to run it.
- *
- * This module automatically disables itself when running in an App Store build by default!
- *
- * @warning It is mandatory to call `authenticateInstallation` somewhen after calling
- * `[[BITHockeyManager sharedHockeyManager] startManager]` or fully customize the identification
- * and validation workflow yourself.
- * If your app shows a modal view on startup, make sure to call `authenticateInstallation`
- * either once your modal view is fully presented (e.g. its `viewDidLoad:` method is processed)
- * or once your modal view is dismissed.
- */
-@interface BITAuthenticator : BITHockeyBaseManager
-
-#pragma mark - Configuration
-
-
-///-----------------------------------------------------------------------------
-/// @name Configuration
-///-----------------------------------------------------------------------------
-
-
-/**
- * Defines the identification mechanism to be used
- *
- * _Default_: `BITAuthenticatorIdentificationTypeAnonymous`
- *
- * @see BITAuthenticatorIdentificationType
- */
-@property (nonatomic, assign) BITAuthenticatorIdentificationType identificationType;
-
-
-/**
- * Enables or disables checking if the user is allowed to run this app
- *
- * If disabled, the Authenticator never validates, besides initial identification,
- * if the user is allowed to run this application.
- *
- * If enabled, the Authenticator checks depending on `restrictionEnforcementFrequency`
- * if the user is allowed to use this application.
- *
- * Enabling this property and setting `identificationType` to `BITAuthenticatorIdentificationTypeHockeyAppEmail`,
- * `BITAuthenticatorIdentificationTypeHockeyAppUser` or `BITAuthenticatorIdentificationTypeWebAuth` also allows
- * to remove access for users by removing them from the app's users list on HockeyApp.
- *
- * _Default_: `NO`
- *
- * @warning if `identificationType` is set to `BITAuthenticatorIdentificationTypeAnonymous`,
- * this property has no effect.
- *
- * @see BITAuthenticatorIdentificationType
- * @see restrictionEnforcementFrequency
- */
-@property (nonatomic, assign) BOOL restrictApplicationUsage;
-
-/**
- * Defines how often the BITAuthenticator checks if the user is allowed
- * to run this application
- *
- * This requires `restrictApplicationUsage` to be enabled.
- *
- * _Default_: `BITAuthenticatorAppRestrictionEnforcementOnFirstLaunch`
- *
- * @see BITAuthenticatorAppRestrictionEnforcementFrequency
- * @see restrictApplicationUsage
- */
-@property (nonatomic, assign) BITAuthenticatorAppRestrictionEnforcementFrequency restrictionEnforcementFrequency;
-
-/**
- * The authentication secret from HockeyApp. To find the right secret,
- * click on your app on the HockeyApp dashboard, then on Show next to
- * "Secret:".
- *
- * This is only needed if `identificationType` is set to `BITAuthenticatorIdentificationTypeHockeyAppEmail`
- *
- * @see identificationType
- */
-@property (nonatomic, copy) NSString *authenticationSecret;
-
-
-#pragma mark - Device based identification
-
-///-----------------------------------------------------------------------------
-/// @name Device based identification
-///-----------------------------------------------------------------------------
-
-
-/**
- * The baseURL of the webpage the user is redirected to if `identificationType` is
- * set to `BITAuthenticatorIdentificationTypeDevice`; defaults to https://rink.hockeyapp.net.
- *
- * @see identificationType
- */
-@property (nonatomic, strong) NSURL *webpageURL;
-
-/**
- * URL to query the device's id via external webpage
- * Built with the baseURL set in `webpageURL`.
- */
-- (NSURL*) deviceAuthenticationURL;
-
-/**
- * The url-scheme used to identify via `BITAuthenticatorIdentificationTypeDevice`
- *
- * Please make sure that the URL scheme is unique and not shared with other apps.
- *
- * If set to nil, the default scheme is used which is `ha`.
- *
- * @see identificationType
- * @see handleOpenURL:sourceApplication:annotation:
- */
-@property (nonatomic, copy) NSString *urlScheme;
-
-/**
- Should be used by the app-delegate to forward handle application:openURL:sourceApplication:annotation: calls.
-
- This is required if `identificationType` is set to `BITAuthenticatorIdentificationTypeDevice`.
- Your app needs to implement the default `ha` URL scheme or register its own scheme
- via `urlScheme`.
- BITAuthenticator checks if the given URL is actually meant to be parsed by it and will
- return NO if it doesn't think so. It does this by checking the 'host'-part of the URL to be 'authorize', as well
- as checking the protocol part.
- Please make sure that if you're using a custom URL scheme, it does _not_ conflict with BITAuthenticator's.
- If BITAuthenticator thinks the URL was meant to be an authorization URL, but could not find a valid token, it will
- reset the stored identification token and state.
-
- Sample usage (in AppDelegate):
-
- - (BOOL)application:(UIApplication *)application
- openURL:(NSURL *)url
- sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
- if ([[BITHockeyManager sharedHockeyManager].authenticator handleOpenURL:url
- sourceApplication:sourceApplication
- annotation:annotation]) {
- return YES;
- } else {
- //do your own URL handling, return appropriate value
- }
- return NO;
- }
-
- @param url Param `url` that was passed to the app
- @param sourceApplication Param `sourceApplication` that was passed to the app
- @param annotation Param `annotation` that was passed to the app
-
- @return YES if the URL request was handled, NO if the URL could not be handled/identified.
-
- @see identificationType
- @see urlScheme
- */
-- (BOOL) handleOpenURL:(NSURL *) url
- sourceApplication:(NSString *) sourceApplication
- annotation:(id) annotation;
-
-#pragma mark - Authentication
-
-///-----------------------------------------------------------------------------
-/// @name Authentication
-///-----------------------------------------------------------------------------
-
-/**
- * Invoked automatic identification and validation
- *
- * If the `BITAuthenticator` is in automatic mode this will initiate identifying
- * the current user according to the type specified in `identificationType` and
- * validate if the identified user is allowed to run this application.
- *
- * If the user is not yet identified it will present a modal view asking the user to
- * provide the required information.
- *
- * If your app provides it's own startup modal screen, e.g. a guide or a login, then
- * you might either call this method once that UI is fully presented or once
- * the user e.g. did actually login already.
- *
- * @warning You need to call this method in your code even if automatic mode is enabled!
- *
- * @see identificationType
- */
-- (void) authenticateInstallation;
-
-/**
- * Identifies the user according to the type specified in `identificationType`.
- *
- * If the `BITAuthenticator` is in manual mode, it's your responsibility to call
- * this method. Depending on the `identificationType`, this method
- * might present a viewController to let the user enter his/her credentials.
- *
- * If the Authenticator is in auto-mode, this is called by the authenticator itself
- * once needed.
- *
- * @see identificationType
- * @see authenticateInstallation
- * @see validateWithCompletion:
- *
- * @param completion Block being executed once identification completed. Be sure to properly dispatch code to the main queue if necessary.
- */
-- (void) identifyWithCompletion:(void(^)(BOOL identified, NSError *error)) completion;
-
-/**
- * Returns YES if this app is identified according to the setting in `identificationType`.
- *
- * Since the identification process is done asynchronously (contacting the server),
- * you need to observe the value change via KVO.
- *
- * @see identificationType
- */
-@property (nonatomic, assign, readonly, getter = isIdentified) BOOL identified;
-
-/**
- * Validates if the identified user is allowed to run this application. This checks
- * with the HockeyApp backend and calls the completion-block once completed.
- *
- * If the `BITAuthenticator` is in manual mode, it's your responsibility to call
- * this method. If the application is not yet identified, validation is not possible
- * and the completion-block is called with an error set.
- *
- * If the `BITAuthenticator` is in auto-mode, this is called by the authenticator itself
- * once needed.
- *
- * @see identificationType
- * @see authenticateInstallation
- * @see identifyWithCompletion:
- *
- * @param completion Block being executed once validation completed. Be sure to properly dispatch code to the main queue if necessary.
- */
-- (void) validateWithCompletion:(void(^)(BOOL validated, NSError *error)) completion;
-
-/**
- * Indicates if this installation is validated.
- */
-@property (nonatomic, assign, readonly, getter = isValidated) BOOL validated;
-
-/**
- * Removes all previously stored authentication tokens, UDIDs, etc.
- */
-- (void) cleanupInternalStorage;
-
-/**
- * Returns different values depending on `identificationType`. This can be used
- * by the application to identify the user.
- *
- * @see identificationType
- */
-- (NSString*) publicInstallationIdentifier;
-@end
-
-#pragma mark - Protocol
-
-/**
- * `BITAuthenticator` protocol
- */
-@protocol BITAuthenticatorDelegate
-
-@optional
-/**
- * If the authentication (or validation) needs to identify the user,
- * this delegate method is called with the viewController that we'll present.
- *
- * @param authenticator `BITAuthenticator` object
- * @param viewController `UIViewController` used to identify the user
- *
- */
-- (void) authenticator:(BITAuthenticator *)authenticator willShowAuthenticationController:(UIViewController*) viewController;
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITAuthenticator.m b/submodules/HockeySDK-iOS/Classes/BITAuthenticator.m
deleted file mode 100644
index f197219992..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITAuthenticator.m
+++ /dev/null
@@ -1,990 +0,0 @@
-/*
- * Author: Stephan Diederich
- *
- * Copyright (c) 2013-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_AUTHENTICATOR
-
-#import "HockeySDKPrivate.h"
-#import "BITAuthenticator_Private.h"
-#import "BITAuthenticationViewController.h"
-#import "BITHockeyAppClient.h"
-#import "BITHockeyHelper.h"
-#import "BITHockeyHelper+Application.h"
-#import "BITHockeyBaseManagerPrivate.h"
-
-#include
-
-static NSString *const kBITAuthenticatorUUIDKey = @"BITAuthenticatorUUIDKey";
-static NSString *const kBITAuthenticatorIdentifierKey = @"BITAuthenticatorIdentifierKey";
-static NSString *const kBITAuthenticatorIdentifierTypeKey = @"BITAuthenticatorIdentifierTypeKey";
-static NSString *const kBITAuthenticatorLastAuthenticatedVersionKey = @"BITAuthenticatorLastAuthenticatedVersionKey";
-static NSString *const kBITAuthenticatorUserEmailKey = @"BITAuthenticatorUserEmailKey";
-
-//deprecated
-static NSString *const kBITAuthenticatorAuthTokenKey = @"BITAuthenticatorAuthTokenKey";
-static NSString *const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAuthTokenTypeKey";
-
-typedef unsigned int bit_uint32;
-static unsigned char kBITPNGHeader[8] = {137, 80, 78, 71, 13, 10, 26, 10};
-static unsigned char kBITPNGEndChunk[4] = {0x49, 0x45, 0x4e, 0x44};
-
-
-@interface BITAuthenticator()
-
-@property (nonatomic, assign) BOOL isSetup;
-
-@property (nonatomic, strong) id appDidBecomeActiveObserver;
-@property (nonatomic, strong) id appDidEnterBackgroundObserver;
-@property (nonatomic, strong) UIViewController *authenticationController;
-
-@end
-
-
-@implementation BITAuthenticator
-
-- (instancetype)initWithAppIdentifier:(NSString *)appIdentifier appEnvironment:(BITEnvironment)environment {
- self = [super initWithAppIdentifier:appIdentifier appEnvironment:environment];
- if (self) {
- _webpageURL = [NSURL URLWithString:@"https://rink.hockeyapp.net/"];
-
- _identificationType = BITAuthenticatorIdentificationTypeAnonymous;
- _isSetup = NO;
- _restrictApplicationUsage = NO;
- _restrictionEnforcementFrequency = BITAuthenticatorAppRestrictionEnforcementOnFirstLaunch;
- }
- return self;
-}
-
-- (void)dealloc {
- [self unregisterObservers];
-}
-
-#pragma mark - BITHockeyBaseManager overrides
-
-- (void)startManager {
- //disabled in TestFlight and the AppStore
- if (self.appEnvironment != BITEnvironmentOther) { return; }
-
- self.isSetup = YES;
-}
-
-#pragma mark -
-
-- (void)authenticateInstallation {
- //disabled in TestFlight and the AppStore
- if (self.appEnvironment != BITEnvironmentOther) { return; }
-
- // make sure this is called after startManager so all modules are fully setup
- if (!self.isSetup) {
- [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(authenticateInstallation) object:nil];
- [self performSelector:@selector(authenticateInstallation) withObject:nil afterDelay:0.1];
- } else {
- switch ([BITHockeyHelper applicationState]) {
- case BITApplicationStateActive:
- [self authenticate];
- break;
- case BITApplicationStateBackground:
- case BITApplicationStateInactive:
- case BITApplicationStateUnknown:
- // do nothing, wait for active state
- break;
- }
- }
- [self registerObservers];
-}
-
-- (void)authenticate {
- [self identifyWithCompletion:^(BOOL identified, NSError *error) {
- if (identified) {
- if ([self needsValidation]) {
- [self validate];
- } else {
- [self dismissAuthenticationControllerAnimated:YES completion:nil];
- }
- } else {
- BITHockeyLogError(@"Failed to identify. Error: %@", error);
- }
- }];
-}
-
-#pragma mark - Identification
-
-- (void)identifyWithCompletion:(void (^)(BOOL identified, NSError *))completion {
- if (self.authenticationController) {
- BITHockeyLogDebug(@"Authentication controller already visible. Ignoring identify request");
- if (completion) { completion(NO, nil); }
- return;
- }
- //first check if the stored identification type matches the one currently configured
- NSString *storedTypeString = [self stringValueFromKeychainForKey:kBITAuthenticatorIdentifierTypeKey];
- NSString *configuredTypeString = [self.class stringForIdentificationType:self.identificationType];
- if (storedTypeString && ![storedTypeString isEqualToString:configuredTypeString]) {
- BITHockeyLogDebug(@"Identification type mismatch for stored auth-token. Resetting.");
- [self storeInstallationIdentifier:nil withType:BITAuthenticatorIdentificationTypeAnonymous];
- }
-
- NSString *identification = [self installationIdentifier];
-
- if (identification) {
- self.identified = YES;
- if (completion) { completion(YES, nil); }
- return;
- }
-
- [self processFullSizeImage];
- if (self.identified) {
- if (completion) { completion(YES, nil); }
- return;
- }
-
- //it's not identified yet, do it now
- BITAuthenticationViewController *viewController = nil;
- switch (self.identificationType) {
- case BITAuthenticatorIdentificationTypeAnonymous:
- [self storeInstallationIdentifier:bit_UUID() withType:BITAuthenticatorIdentificationTypeAnonymous];
- self.identified = YES;
- if (completion) { completion(YES, nil); }
- return;
- case BITAuthenticatorIdentificationTypeHockeyAppUser:
- viewController = [[BITAuthenticationViewController alloc] initWithDelegate:self];
- viewController.requirePassword = YES;
- viewController.tableViewTitle = BITHockeyLocalizedString(@"HockeyAuthenticationViewControllerDataEmailAndPasswordDescription");
- break;
- case BITAuthenticatorIdentificationTypeDevice:
- viewController = [[BITAuthenticationViewController alloc] initWithDelegate:self];
- viewController.requirePassword = NO;
- viewController.showsLoginViaWebButton = YES;
- viewController.tableViewTitle = BITHockeyLocalizedString(@"HockeyAuthenticationViewControllerWebUDIDLoginDescription");
- break;
- case BITAuthenticatorIdentificationTypeWebAuth:
- viewController = [[BITAuthenticationViewController alloc] initWithDelegate:self];
- viewController.requirePassword = NO;
- viewController.showsLoginViaWebButton = YES;
- viewController.tableViewTitle = BITHockeyLocalizedString(@"HockeyAuthenticationViewControllerWebAuthLoginDescription");
- break;
- case BITAuthenticatorIdentificationTypeHockeyAppEmail:
- if (nil == self.authenticationSecret) {
- NSError *error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
- code:BITAuthenticatorAuthorizationSecretMissing
- userInfo:@{NSLocalizedDescriptionKey:@"For email identification, the authentication secret must be set"}];
- if (completion) { completion(NO, error); }
- return;
- }
- viewController = [[BITAuthenticationViewController alloc] initWithDelegate:self];
- viewController.requirePassword = NO;
- viewController.tableViewTitle = BITHockeyLocalizedString(@"HockeyAuthenticationViewControllerDataEmailDescription");
- break;
- }
- id strongDelegate = self.delegate;
- if ([strongDelegate respondsToSelector:@selector(authenticator:willShowAuthenticationController:)]) {
- [strongDelegate authenticator:self willShowAuthenticationController:viewController];
- }
-
- NSAssert(viewController, @"ViewController should've been created");
-
- viewController.email = [self stringValueFromKeychainForKey:kBITAuthenticatorUserEmailKey];
- self.authenticationController = viewController;
- self.identificationCompletion = completion;
- dispatch_async(dispatch_get_main_queue(), ^{
- [self showView:viewController];
- });
-}
-
-#pragma mark - Validation
-
-- (BOOL)needsValidation {
- if (BITAuthenticatorIdentificationTypeAnonymous == self.identificationType) {
- return NO;
- }
- if (NO == self.restrictApplicationUsage) {
- return NO;
- }
- if (self.restrictionEnforcementFrequency == BITAuthenticatorAppRestrictionEnforcementOnFirstLaunch &&
- ![self.executableUUID isEqualToString:self.lastAuthenticatedVersion]) {
- return YES;
- }
- if (NO == self.isValidated && self.restrictionEnforcementFrequency == BITAuthenticatorAppRestrictionEnforcementOnAppActive) {
- return YES;
- }
- return NO;
-}
-
-- (void)validate {
- [self validateWithCompletion:^(BOOL validated, NSError *error) {
- dispatch_async(dispatch_get_main_queue(), ^{
- if (validated) {
- [self dismissAuthenticationControllerAnimated:YES completion:nil];
- } else {
- BITHockeyLogError(@"Validation failed with error: %@", error);
- __weak typeof(self) weakSelf = self;
-
- UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil
- message:error.localizedDescription
- preferredStyle:UIAlertControllerStyleAlert];
- UIAlertAction *okAction = [BITAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyOK")
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction __unused *action) {
- typeof(self) strongSelf = weakSelf;
- [strongSelf validate];
- }];
-
- [alertController addAction:okAction];
- [self showAlertController:alertController];
- }
- });
- }];
-}
-
-- (void)validateWithCompletion:(void (^)(BOOL validated, NSError *))completion {
- BOOL requirementsFulfilled = YES;
- NSError *error = nil;
- switch (self.identificationType) {
- case BITAuthenticatorIdentificationTypeAnonymous: {
- error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
- code:BITAuthenticatorErrorUnknown
- userInfo:@{NSLocalizedDescriptionKey:@"Anonymous users can't be validated"}];
- requirementsFulfilled = NO;
- break;
- }
- case BITAuthenticatorIdentificationTypeHockeyAppEmail:
- if (nil == self.authenticationSecret) {
- error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
- code:BITAuthenticatorAuthorizationSecretMissing
- userInfo:@{NSLocalizedDescriptionKey:@"For email validation, the authentication secret must be set"}];
- requirementsFulfilled = NO;
- break;
- }
- //no break
- case BITAuthenticatorIdentificationTypeDevice:
- case BITAuthenticatorIdentificationTypeHockeyAppUser:
- case BITAuthenticatorIdentificationTypeWebAuth:
- if (nil == self.installationIdentifier) {
- error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
- code:BITAuthenticatorNotIdentified
- userInfo:@{NSLocalizedDescriptionKey:@"Make sure to identify the installation first"}];
- requirementsFulfilled = NO;
- }
- break;
- }
- if (NO == requirementsFulfilled) {
- if (completion) {
- completion(NO, error);
- }
- return;
- }
-
- NSString *validationPath = [NSString stringWithFormat:@"api/3/apps/%@/identity/validate", self.encodedAppIdentifier];
-
- __weak typeof(self) weakSelf = self;
- NSURLRequest *request = [self.hockeyAppClient requestWithMethod:@"GET" path:validationPath parameters:[self validationParameters]];
-
- NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
- __block NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
-
- NSURLSessionDataTask *task = [session dataTaskWithRequest:request
- completionHandler:^(NSData *data, NSURLResponse __unused *response, NSError *innerError) {
- typeof(self) strongSelf = weakSelf;
-
- [session finishTasksAndInvalidate];
-
- [strongSelf handleValidationResponseWithData:data error:innerError completion:completion];
- }];
- [task resume];
-}
-
-- (void)handleValidationResponseWithData:(NSData *)responseData error:(NSError *)error completion:(void (^)(BOOL validated, NSError *))completion {
- if (nil == responseData) {
- NSDictionary *userInfo = @{NSLocalizedDescriptionKey:BITHockeyLocalizedString(@"HockeyAuthenticationFailedAuthenticate")};
- if (error) {
- NSMutableDictionary *dict = [userInfo mutableCopy];
- dict[NSUnderlyingErrorKey] = error;
- userInfo = dict;
- }
- NSError *localError = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
- code:BITAuthenticatorNetworkError
- userInfo:userInfo];
- self.validated = NO;
- if (completion) { completion(NO, localError); }
- } else {
- NSError *validationParseError = nil;
- BOOL valid = [self.class isValidationResponseValid:responseData error:&validationParseError];
- self.validated = valid;
- if (valid) {
- [self setLastAuthenticatedVersion:self.executableUUID];
- }
- if (completion) { completion(valid, validationParseError); }
- }
-}
-
-- (NSDictionary *)validationParameters {
- NSParameterAssert(self.installationIdentifier);
- NSParameterAssert(self.installationIdentifierParameterString);
-
- NSString *installString = bit_appAnonID(NO);
- if (installString) {
- return @{self.installationIdentifierParameterString:self.installationIdentifier, @"install_string":installString};
- }
-
- return @{self.installationIdentifierParameterString:self.installationIdentifier};
-}
-
-+ (BOOL)isValidationResponseValid:(id)response error:(NSError *__autoreleasing *)error {
- NSParameterAssert(response);
-
- NSError *jsonParseError = nil;
- id jsonObject = [NSJSONSerialization JSONObjectWithData:response
- options:0
- error:&jsonParseError];
- if (nil == jsonObject) {
- if (error) {
- *error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
- code:BITAuthenticatorAPIServerReturnedInvalidResponse
- userInfo:@{NSLocalizedDescriptionKey:BITHockeyLocalizedString(@"HockeyAuthenticationFailedAuthenticate")}];
- }
- return NO;
- }
- if (![jsonObject isKindOfClass:[NSDictionary class]]) {
- if (error) {
- *error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
- code:BITAuthenticatorAPIServerReturnedInvalidResponse
- userInfo:@{NSLocalizedDescriptionKey:BITHockeyLocalizedString(@"HockeyAuthenticationFailedAuthenticate")}];
- }
- return NO;
- }
-
- NSString *status = jsonObject[@"status"];
- if ([status isEqualToString:@"not authorized"]) {
- if (error) {
- *error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
- code:BITAuthenticatorNotAuthorized
- userInfo:@{NSLocalizedDescriptionKey:BITHockeyLocalizedString(@"HockeyAuthenticationNotMember")}];
- }
- return NO;
- } else if ([status isEqualToString:@"not found"]) {
- if (error) {
- *error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
- code:BITAuthenticatorUnknownApplicationID
- userInfo:@{NSLocalizedDescriptionKey:BITHockeyLocalizedString(@"HockeyAuthenticationContactDeveloper")}];
- }
- return NO;
- } else if ([status isEqualToString:@"validated"]) {
- return YES;
- } else {
- if (error) {
- *error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
- code:BITAuthenticatorAPIServerReturnedInvalidResponse
- userInfo:@{NSLocalizedDescriptionKey:BITHockeyLocalizedString(@"HockeyAuthenticationFailedAuthenticate")}];
- }
- return NO;
- }
-}
-
-#pragma mark - AuthenticationViewController Helper
-
-/**
- * This method has to be called on the main queue
- */
-- (void)dismissAuthenticationControllerAnimated:(BOOL)animated completion:(void (^)(void))completion {
- if (!self.authenticationController) { return; }
- UIViewController *presentingViewController = [self.authenticationController presentingViewController];
-
- // If there is no presenting view controller just remove view
- if (presentingViewController) {
- [self.authenticationController dismissViewControllerAnimated:animated completion:completion];
- } else {
- [self.authenticationController.navigationController.view removeFromSuperview];
- if (completion) {
- completion();
- }
- }
- self.authenticationController = nil;
-}
-
-#pragma mark - AuthenticationViewControllerDelegate
-
-- (void)authenticationViewController:(UIViewController *)viewController
- handleAuthenticationWithEmail:(NSString *)email
- password:(NSString *)password
- completion:(void (^)(BOOL, NSError *))completion {
-
- NSParameterAssert(email && email.length);
- NSParameterAssert(self.identificationType == BITAuthenticatorIdentificationTypeHockeyAppEmail || (password && password.length));
-
- // Trim whitespace from email in case the user has added a whitespace at the end of the email address. This shouldn't
- // happen if devs use our UI but we've had 1-2 support tickets where the email contained whitespace at the end and
- // verification failed because of that.
- email = [email stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
-
- NSURLRequest *request = [self requestForAuthenticationEmail:email password:password];
-
- [self authenticationViewController:viewController handleAuthenticationWithEmail:email request:request completion:completion];
-}
-
-- (void)authenticationViewController:(UIViewController *) __unused viewController
- handleAuthenticationWithEmail:(NSString *)email
- request:(NSURLRequest *)request
- completion:(void (^)(BOOL, NSError *))completion {
-
- __weak typeof(self) weakSelf = self;
- NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
- __block NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
-
- NSURLSessionDataTask *task = [session dataTaskWithRequest:request
- completionHandler:^(NSData *data, NSURLResponse *response, NSError __unused *error) {
- typeof(self) strongSelf = weakSelf;
- NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
-
- [session finishTasksAndInvalidate];
-
- [strongSelf handleAuthenticationWithResponse:httpResponse email:email data:data completion:completion];
- }];
- [task resume];
-}
-
-- (void)authenticationViewControllerDidTapWebButton:(UIViewController *) __unused viewController {
- NSURL *url = [self deviceAuthenticationURL];
- if (url) {
- [[UIApplication sharedApplication] openURL:url];
- }
-}
-
-#pragma mark - Networking
-
-- (void)handleAuthenticationWithResponse:(NSHTTPURLResponse *)response email:(NSString *)email data:(NSData *)data completion:(void (^)(BOOL, NSError *))completion {
- NSError *authParseError = nil;
- NSString *authToken = [self.class authenticationTokenFromURLResponse:response
- data:data
- error:&authParseError];
- BOOL identified;
- if (authToken) {
- identified = YES;
- [self storeInstallationIdentifier:authToken withType:self.identificationType];
- dispatch_async(dispatch_get_main_queue(), ^{
- [self dismissAuthenticationControllerAnimated:YES completion:nil];
- });
- BOOL success = [self addStringValueToKeychain:email forKey:kBITAuthenticatorUserEmailKey];
- if (!success) {
- [self alertOnFailureStoringTokenInKeychain];
- }
- } else {
- identified = NO;
- }
- self.identified = identified;
- if (completion) { completion(identified, authParseError); }
- if (self.identificationCompletion) {
- self.identificationCompletion(identified, authParseError);
- self.identificationCompletion = nil;
- }
-}
-
-- (NSURLRequest *)requestForAuthenticationEmail:(NSString *)email password:(NSString *)password {
- NSString *authenticationPath = [self authenticationPath];
- NSMutableDictionary *params = [NSMutableDictionary dictionary];
-
- NSString *installString = bit_appAnonID(NO);
- if (installString) {
- params[@"install_string"] = installString;
- }
-
- if (BITAuthenticatorIdentificationTypeHockeyAppEmail == self.identificationType) {
- NSString *authCode = BITHockeyMD5([NSString stringWithFormat:@"%@%@",
- self.authenticationSecret ?: @"",
- email ?: @""]);
-
- params[@"email"] = email ?: @"";
- params[@"authcode"] = authCode.lowercaseString;
- }
-
- NSMutableURLRequest *request = [self.hockeyAppClient requestWithMethod:@"POST"
- path:authenticationPath
- parameters:params];
- if (BITAuthenticatorIdentificationTypeHockeyAppUser == self.identificationType) {
- NSString *authStr = [NSString stringWithFormat:@"%@:%@", email, password];
- NSData *authData = [authStr dataUsingEncoding:NSUTF8StringEncoding];
- NSString *authValue = [NSString stringWithFormat:@"Basic %@", [authData base64EncodedStringWithOptions:0]];
- [request setValue:authValue forHTTPHeaderField:@"Authorization"];
- }
-
- return request;
-}
-
-- (NSString *)authenticationPath {
- if (BITAuthenticatorIdentificationTypeHockeyAppUser == self.identificationType) {
- return [NSString stringWithFormat:@"api/3/apps/%@/identity/authorize", self.encodedAppIdentifier];
- } else {
- return [NSString stringWithFormat:@"api/3/apps/%@/identity/check", self.encodedAppIdentifier];
- }
-}
-
-+ (NSString *)authenticationTokenFromURLResponse:(NSHTTPURLResponse *)urlResponse data:(NSData *)data error:(NSError *__autoreleasing *)error {
- if (nil == urlResponse) {
- if (error) {
- *error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
- code:BITAuthenticatorAPIServerReturnedInvalidResponse
- userInfo:@{NSLocalizedDescriptionKey:BITHockeyLocalizedString(@"HockeyAuthenticationFailedAuthenticate")}];
- }
- return nil;
- }
-
- switch (urlResponse.statusCode) {
- case 401:
- if (error) {
- *error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
- code:BITAuthenticatorNotAuthorized
- userInfo:@{
- NSLocalizedDescriptionKey:BITHockeyLocalizedString(@"HockeyAuthenticationWrongEmailPassword")
- }];
- }
- break;
- case 200:
- case 404:
- //Do nothing, handled below
- break;
- default:
- if (error) {
- *error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
- code:BITAuthenticatorAPIServerReturnedInvalidResponse
- userInfo:@{NSLocalizedDescriptionKey:BITHockeyLocalizedString(@"HockeyAuthenticationFailedAuthenticate")}];
-
- }
- break;
- }
- if (200 != urlResponse.statusCode && 404 != urlResponse.statusCode) {
- //make sure we have an error created if user wanted to have one
- NSParameterAssert(nil == error || *error);
- return nil;
- }
-
- NSError *jsonParseError = nil;
- id jsonObject = [NSJSONSerialization JSONObjectWithData:data
- options:0
- error:&jsonParseError];
- //no json or unexpected json
- if (nil == jsonObject || ![jsonObject isKindOfClass:[NSDictionary class]]) {
- if (error) {
- NSDictionary *userInfo = @{NSLocalizedDescriptionKey:BITHockeyLocalizedString(@"HockeyAuthenticationFailedAuthenticate")};
- if (jsonParseError) {
- NSMutableDictionary *userInfoMutable = [userInfo mutableCopy];
- userInfoMutable[NSUnderlyingErrorKey] = jsonParseError;
- userInfo = userInfoMutable;
- }
- *error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
- code:BITAuthenticatorAPIServerReturnedInvalidResponse
- userInfo:userInfo];
- }
- return nil;
- }
-
- NSString *status = jsonObject[@"status"];
- NSString *authToken = nil;
- if ([status isEqualToString:@"identified"]) {
- authToken = jsonObject[@"iuid"];
- } else if ([status isEqualToString:@"authorized"]) {
- authToken = jsonObject[@"auid"];
- } else if ([status isEqualToString:@"not authorized"]) {
- if (error) {
- *error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
- code:BITAuthenticatorNotAuthorized
- userInfo:@{NSLocalizedDescriptionKey:BITHockeyLocalizedString(@"HockeyAuthenticationNotMember")}];
-
- }
- }
- //if no error is set yet, but error parameter is given, return a generic error
- if (nil == authToken && error && nil == *error) {
- *error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
- code:BITAuthenticatorAPIServerReturnedInvalidResponse
- userInfo:@{NSLocalizedDescriptionKey:BITHockeyLocalizedString(@"HockeyAuthenticationFailedAuthenticate")}];
- }
- return authToken;
-}
-
-- (NSURL *)deviceAuthenticationURL {
- NSString *whatParameter = nil;
- switch (self.identificationType) {
- case BITAuthenticatorIdentificationTypeWebAuth:
- whatParameter = @"email";
- break;
- case BITAuthenticatorIdentificationTypeDevice:
- whatParameter = @"udid";
- break;
- case BITAuthenticatorIdentificationTypeAnonymous:
- case BITAuthenticatorIdentificationTypeHockeyAppEmail:
- case BITAuthenticatorIdentificationTypeHockeyAppUser:
- return nil;
- }
- NSURL *url = [self.webpageURL URLByAppendingPathComponent:[NSString stringWithFormat:@"apps/%@/authorize", self.encodedAppIdentifier]];
- NSParameterAssert(whatParameter && url.absoluteString);
- url = [NSURL URLWithString:[NSString stringWithFormat:@"%@?what=%@", url.absoluteString, whatParameter]];
- return url;
-}
-
-- (BOOL)handleOpenURL:(NSURL *)url
- sourceApplication:(NSString *) __unused sourceApplication
- annotation:(id)annotation {
- //check if this URL was meant for us, if not return NO so the user can
- //handle it
- NSString *const kAuthorizationHost = @"authorize";
- NSString *urlScheme = self.urlScheme ?: [NSString stringWithFormat:@"ha%@", self.appIdentifier];
- if (!([[url scheme] isEqualToString:urlScheme] && [[url host] isEqualToString:kAuthorizationHost])) {
- BITHockeyLogWarning(@"WARNING: URL scheme for authentication doesn't match!");
- return NO;
- }
-
- NSString *installationIdentifier = nil;
- NSString *localizedErrorDescription = nil;
- switch (self.identificationType) {
- case BITAuthenticatorIdentificationTypeWebAuth: {
- NSString *email = nil;
- [self.class email:&email andIUID:&installationIdentifier fromOpenURL:url];
- if (email) {
- BOOL success = [self addStringValueToKeychain:email forKey:kBITAuthenticatorUserEmailKey];
- if (!success) {
- [self alertOnFailureStoringTokenInKeychain];
- }
- } else {
- BITHockeyLogDebug(@"No email found in URL: %@", url);
- }
- localizedErrorDescription = @"Failed to retrieve parameters from URL.";
- break;
- }
- case BITAuthenticatorIdentificationTypeDevice: {
- installationIdentifier = [self.class UDIDFromOpenURL:url annotation:annotation];
- localizedErrorDescription = @"Failed to retrieve UDID from URL.";
- break;
- }
- case BITAuthenticatorIdentificationTypeHockeyAppEmail:
- case BITAuthenticatorIdentificationTypeAnonymous:
- case BITAuthenticatorIdentificationTypeHockeyAppUser:
- return NO;
- }
-
- if (installationIdentifier) {
- BITHockeyLogDebug(@"Authentication succeeded.");
- if (NO == self.restrictApplicationUsage) {
- [self dismissAuthenticationControllerAnimated:YES completion:nil];
- }
- [self storeInstallationIdentifier:installationIdentifier withType:self.identificationType];
- self.identified = YES;
- if (self.identificationCompletion) {
- self.identificationCompletion(YES, nil);
- self.identificationCompletion = nil;
- }
- } else {
- //reset token
- BITHockeyLogDebug(@"Resetting authentication token");
- [self storeInstallationIdentifier:nil withType:self.identificationType];
- self.identified = NO;
- if (self.identificationCompletion) {
- NSError *error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
- code:BITAuthenticatorErrorUnknown
- userInfo:@{NSLocalizedDescriptionKey:localizedErrorDescription}];
- self.identificationCompletion(NO, error);
- self.identificationCompletion = nil;
- }
- }
- return YES;
-}
-
-+ (NSString *)UDIDFromOpenURL:(NSURL *)url annotation:(id) __unused annotation {
- NSString *query = [url query];
- NSString *udid = nil;
- //there should actually only one
- static NSString *const UDIDQuerySpecifier = @"udid";
- for (NSString *queryComponents in [query componentsSeparatedByString:@"&"]) {
- NSArray *parameterComponents = [queryComponents componentsSeparatedByString:@"="];
- if (2 == parameterComponents.count && [parameterComponents[0] isEqualToString:UDIDQuerySpecifier]) {
- udid = parameterComponents[1];
- break;
- }
- }
- return udid;
-}
-
-+ (void)email:(NSString *__autoreleasing *)email andIUID:(NSString *__autoreleasing *)iuid fromOpenURL:(NSURL *)url {
- NSString *query = [url query];
- //there should actually only one
- static NSString *const EmailQuerySpecifier = @"email";
- static NSString *const IUIDQuerySpecifier = @"iuid";
- for (NSString *queryComponents in [query componentsSeparatedByString:@"&"]) {
- NSArray *parameterComponents = [queryComponents componentsSeparatedByString:@"="];
- if (email && 2 == parameterComponents.count && [parameterComponents[0] isEqualToString:EmailQuerySpecifier]) {
- *email = parameterComponents[1];
- } else if (iuid && 2 == parameterComponents.count && [parameterComponents[0] isEqualToString:IUIDQuerySpecifier]) {
- *iuid = parameterComponents[1];
- }
- }
-}
-
-#pragma mark - Private helpers
-
-- (void)alertOnFailureStoringTokenInKeychain {
- if ([BITHockeyHelper applicationState] != BITApplicationStateActive) {
- return;
- }
-
- BITHockeyLogError(@"[HockeySDK] ERROR: The authentication token could not be stored due to a keychain error. This is most likely a signing or keychain entitlement issue!");
-}
-
-- (void)cleanupInternalStorage {
- [self removeKeyFromKeychain:kBITAuthenticatorIdentifierTypeKey];
- [self removeKeyFromKeychain:kBITAuthenticatorIdentifierKey];
- [self removeKeyFromKeychain:kBITAuthenticatorUUIDKey];
- [self removeKeyFromKeychain:kBITAuthenticatorUserEmailKey];
- [self setLastAuthenticatedVersion:nil];
- self.identified = NO;
- self.validated = NO;
-
- //cleanup values stored from 3.5 Beta1..Beta3
- [self removeKeyFromKeychain:kBITAuthenticatorAuthTokenKey];
- [self removeKeyFromKeychain:kBITAuthenticatorAuthTokenTypeKey];
-}
-
-- (void)processFullSizeImage {
-#ifdef BIT_INTERNAL_DEBUG
- NSString* path = [[NSBundle mainBundle] pathForResource:@"iTunesArtwork" ofType:@"png"];
-#else
- NSString *path = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/../iTunesArtwork"];
-#endif
-
- struct stat fs;
- int fd = open([path UTF8String], O_RDONLY, 0);
- if (fstat(fd, &fs) < 0) {
- // File not found
- close(fd);
- return;
- }
-
- BITHockeyLogDebug(@"Processing full size image for possible authentication");
-
- unsigned char *buffer, *source;
- source = (unsigned char *)malloc((unsigned long)fs.st_size);
- if (read(fd, source, (unsigned long)fs.st_size) != fs.st_size) {
- close(fd);
- // Couldn't read file
- free(source);
- return;
- }
-
- if ((fs.st_size < 20) || (memcmp(source, kBITPNGHeader, 8))) {
- // Not a PNG
- free(source);
- return;
- }
-
- buffer = source + 8;
-
- NSString *result = nil;
- bit_uint32 length;
- unsigned char *name;
- unsigned char *data;
- int chunk_index = 0;
- long long bytes_left = fs.st_size - 8;
- do {
- memcpy(&length, buffer, 4);
- length = ntohl(length);
-
- buffer += 4;
- name = (unsigned char *)malloc(5);
- name[4] = 0;
- memcpy(name, buffer, 4);
-
- buffer += 4;
- data = (unsigned char *)malloc(length + 1);
-
- if (bytes_left >= length) {
- memcpy(data, buffer, length);
-
- buffer += length;
- buffer += 4;
- if (!strcmp((const char *)name, "tEXt")) {
- data[length] = 0;
- NSString *key = [NSString stringWithCString:(char *)data encoding:NSUTF8StringEncoding];
-
- if ([key isEqualToString:@"Data"]) {
- result = [NSString stringWithCString:(char *)(data + key.length + 1) encoding:NSUTF8StringEncoding];
- }
- }
-
- if (!memcmp(name, kBITPNGEndChunk, 4)) {
- chunk_index = 128;
- }
- }
-
- free(data);
- free(name);
-
- bytes_left -= (length + 3 * 4);
- } while ((chunk_index++ < 128) && (bytes_left > 8));
-
- free(source);
-
- if (result) {
- BITHockeyLogDebug(@"Authenticating using full size image information: %@", result);
- [self handleOpenURL:[NSURL URLWithString:result] sourceApplication:nil annotation:nil];
- } else {
- BITHockeyLogDebug(@"No authentication information found");
- }
-}
-
-#pragma mark - NSNotification
-
-- (void)registerObservers {
- __weak typeof(self) weakSelf = self;
- if (nil == self.appDidBecomeActiveObserver) {
- self.appDidBecomeActiveObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification
- object:nil
- queue:NSOperationQueue.mainQueue
- usingBlock:^(NSNotification *note) {
- typeof(self) strongSelf = weakSelf;
- [strongSelf applicationDidBecomeActive:note];
- }];
- }
- if (nil == self.appDidEnterBackgroundObserver) {
- self.appDidEnterBackgroundObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidEnterBackgroundNotification
- object:nil
- queue:NSOperationQueue.mainQueue
- usingBlock:^(NSNotification *note) {
- typeof(self) strongSelf = weakSelf;
- [strongSelf applicationDidEnterBackground:note];
- }];
- }
-}
-
-- (void)unregisterObservers {
- if (self.appDidBecomeActiveObserver) {
- [[NSNotificationCenter defaultCenter] removeObserver:self.appDidBecomeActiveObserver];
- self.appDidBecomeActiveObserver = nil;
- }
- if (self.appDidEnterBackgroundObserver) {
- [[NSNotificationCenter defaultCenter] removeObserver:self.appDidEnterBackgroundObserver];
- self.appDidEnterBackgroundObserver = nil;
- }
-}
-
-#pragma mark - Property overrides
-
-- (void)storeInstallationIdentifier:(NSString *)installationIdentifier withType:(BITAuthenticatorIdentificationType)type {
- if (nil == installationIdentifier) {
- [self removeKeyFromKeychain:kBITAuthenticatorIdentifierKey];
- [self removeKeyFromKeychain:kBITAuthenticatorIdentifierTypeKey];
- } else {
- BOOL success1 = [self addStringValueToKeychainForThisDeviceOnly:installationIdentifier
- forKey:kBITAuthenticatorIdentifierKey];
- BOOL success2 = [self addStringValueToKeychainForThisDeviceOnly:[self.class stringForIdentificationType:type]
- forKey:kBITAuthenticatorIdentifierTypeKey];
- if (!success1 || !success2) {
- [self alertOnFailureStoringTokenInKeychain];
- }
- }
-}
-
-- (NSString *)installationIdentifier {
- NSString *identifier = [self stringValueFromKeychainForKey:kBITAuthenticatorIdentifierKey];
- return identifier;
-}
-
-- (void)setLastAuthenticatedVersion:(NSString *)lastAuthenticatedVersion {
- NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
- if (nil == lastAuthenticatedVersion) {
- [defaults removeObjectForKey:kBITAuthenticatorLastAuthenticatedVersionKey];
- } else {
- [defaults setObject:lastAuthenticatedVersion
- forKey:kBITAuthenticatorLastAuthenticatedVersionKey];
- }
-}
-
-- (NSString *)lastAuthenticatedVersion {
- return [[NSUserDefaults standardUserDefaults] objectForKey:kBITAuthenticatorLastAuthenticatedVersionKey];
-}
-
-- (NSString *)installationIdentifierParameterString {
- switch (self.identificationType) {
- case BITAuthenticatorIdentificationTypeHockeyAppEmail:
- case BITAuthenticatorIdentificationTypeWebAuth:
- return @"iuid";
- case BITAuthenticatorIdentificationTypeHockeyAppUser:
- return @"auid";
- case BITAuthenticatorIdentificationTypeDevice:
- return @"udid";
- case BITAuthenticatorIdentificationTypeAnonymous:
- return @"uuid";
- }
-}
-
-+ (NSString *)stringForIdentificationType:(BITAuthenticatorIdentificationType)identificationType {
- switch (identificationType) {
- case BITAuthenticatorIdentificationTypeHockeyAppEmail:
- return @"iuid";
- case BITAuthenticatorIdentificationTypeWebAuth:
- return @"webAuth";
- case BITAuthenticatorIdentificationTypeHockeyAppUser:
- return @"auid";
- case BITAuthenticatorIdentificationTypeDevice:
- return @"udid";
- case BITAuthenticatorIdentificationTypeAnonymous:
- return @"uuid";
- }
-}
-
-- (void)setIdentificationType:(BITAuthenticatorIdentificationType)identificationType {
- if (_identificationType != identificationType) {
- _identificationType = identificationType;
- self.identified = NO;
- self.validated = NO;
- }
-}
-
-- (NSString *)publicInstallationIdentifier {
- switch (self.identificationType) {
- case BITAuthenticatorIdentificationTypeHockeyAppEmail:
- case BITAuthenticatorIdentificationTypeHockeyAppUser:
- case BITAuthenticatorIdentificationTypeWebAuth:
- return [self stringValueFromKeychainForKey:kBITAuthenticatorUserEmailKey];
- case BITAuthenticatorIdentificationTypeAnonymous:
- case BITAuthenticatorIdentificationTypeDevice:
- return [self stringValueFromKeychainForKey:kBITAuthenticatorIdentifierKey];
- }
-}
-
-#pragma mark - Application Lifecycle
-
-- (void)applicationDidBecomeActive:(NSNotification *) __unused note {
- [self authenticate];
-}
-
-- (void)applicationDidEnterBackground:(NSNotification *) __unused note {
- if (BITAuthenticatorAppRestrictionEnforcementOnAppActive == self.restrictionEnforcementFrequency) {
- self.validated = NO;
- }
-}
-
-@end
-
-#endif /* HOCKEYSDK_FEATURE_AUTHENTICATOR */
diff --git a/submodules/HockeySDK-iOS/Classes/BITAuthenticator_Private.h b/submodules/HockeySDK-iOS/Classes/BITAuthenticator_Private.h
deleted file mode 100644
index b0a97ea5b8..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITAuthenticator_Private.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Author: Stephan Diederich
- *
- * Copyright (c) 2013-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_AUTHENTICATOR
-
-#import "BITAuthenticationViewController.h"
-
-@class BITHockeyAppClient;
-
-@interface BITAuthenticator ()
-
-/**
- Delegate that can be used to do any last minute configurations on the
- presented viewController.
-
- The delegate is automatically set by using `[BITHockeyManager setDelegate:]`. You
- should not need to set this delegate individually.
-
- @see `[BITHockeyManager setDelegate:]`
- @see BITAuthenticatorDelegate
- */
-@property (nonatomic, weak) id delegate;
-
-/**
- * must be set
- */
-@property (nonatomic, strong) BITHockeyAppClient *hockeyAppClient;
-
-#pragma mark -
-/**
- * holds the identifier of the last version that was authenticated
- * only used if validation is set BITAuthenticatorValidationTypeOnFirstLaunch
- */
-@property (nonatomic, copy) NSString *lastAuthenticatedVersion;
-
-/**
- * returns the type of the string stored in installationIdentifierParameterString
- */
-@property (nonatomic, copy, readonly) NSString *installationIdentifierParameterString;
-
-/**
- * returns the string used to identify this app against the HockeyApp backend.
- */
-@property (nonatomic, copy, readonly) NSString *installationIdentifier;
-
-/**
- * method registered as observer for applicationDidEnterBackground events
- *
- * @param note NSNotification
- */
-- (void) applicationDidEnterBackground:(NSNotification*) note;
-
-/**
- * method registered as observer for applicationsDidBecomeActive events
- *
- * @param note NSNotification
- */
-- (void) applicationDidBecomeActive:(NSNotification*) note;
-
-@property (nonatomic, copy) void(^identificationCompletion)(BOOL identified, NSError* error);
-
-#pragma mark - Overrides
-@property (nonatomic, assign, readwrite, getter = isIdentified) BOOL identified;
-@property (nonatomic, assign, readwrite, getter = isValidated) BOOL validated;
-
-#pragma mark - Testing
-- (void) storeInstallationIdentifier:(NSString*) identifier withType:(BITAuthenticatorIdentificationType) type;
-- (void)validateWithCompletion:(void (^)(BOOL validated, NSError *))completion;
-- (void)authenticationViewController:(UIViewController *)viewController
- handleAuthenticationWithEmail:(NSString *)email
- request:(NSURLRequest *)request
- completion:(void (^)(BOOL, NSError *))completion;
-- (BOOL) needsValidation;
-- (void) authenticate;
-@end
-
-#endif /* HOCKEYSDK_FEATURE_AUTHENTICATOR */
diff --git a/submodules/HockeySDK-iOS/Classes/BITBase.h b/submodules/HockeySDK-iOS/Classes/BITBase.h
deleted file mode 100644
index 4cc3cdc0c8..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITBase.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#import "BITTelemetryObject.h"
-#import "BITTelemetryData.h"
-
-@interface BITBase : BITTelemetryData
-
-@property (nonatomic, copy) NSString *baseType;
-
-- (instancetype)initWithCoder:(NSCoder *)coder;
-
-- (void)encodeWithCoder:(NSCoder *)coder;
-
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITBase.m b/submodules/HockeySDK-iOS/Classes/BITBase.m
deleted file mode 100644
index efb54b7e26..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITBase.m
+++ /dev/null
@@ -1,34 +0,0 @@
-#import "BITBase.h"
-
-/// Data contract class for type Base.
-@implementation BITBase
-
-///
-/// Adds all members of this class to a dictionary
-/// @returns dictionary to which the members of this class will be added.
-///
-- (NSDictionary *)serializeToDictionary {
- NSMutableDictionary *dict = [super serializeToDictionary].mutableCopy;
- if (self.baseType != nil) {
- [dict setObject:self.baseType forKey:@"baseType"];
- }
- return dict;
-}
-
-#pragma mark - NSCoding
-
-- (instancetype)initWithCoder:(NSCoder *)coder {
- self = [super initWithCoder:coder];
- if(self) {
- _baseType = [coder decodeObjectForKey:@"self.baseType"];
- }
-
- return self;
-}
-
-- (void)encodeWithCoder:(NSCoder *)coder {
- [super encodeWithCoder:coder];
- [coder encodeObject:self.baseType forKey:@"self.baseType"];
-}
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITBlurImageAnnotation.h b/submodules/HockeySDK-iOS/Classes/BITBlurImageAnnotation.h
deleted file mode 100644
index cb5a1f3ecc..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITBlurImageAnnotation.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Author: Moritz Haarmann
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import "BITImageAnnotation.h"
-
-@interface BITBlurImageAnnotation : BITImageAnnotation
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITBlurImageAnnotation.m b/submodules/HockeySDK-iOS/Classes/BITBlurImageAnnotation.m
deleted file mode 100644
index 9b1fd3f941..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITBlurImageAnnotation.m
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Author: Moritz Haarmann
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_FEEDBACK
-
-#import "BITBlurImageAnnotation.h"
-
-@interface BITBlurImageAnnotation()
-
-@property (nonatomic, strong) CALayer* imageLayer;
-@property (nonatomic, strong) UIImage* scaledImage;
-@property (nonatomic, strong) CALayer* selectedLayer;
-
-
-@end
-
-@implementation BITBlurImageAnnotation
-
-- (instancetype)initWithFrame:(CGRect)frame {
- self = [super initWithFrame:frame];
- if (self) {
- self.clipsToBounds = YES;
- self.imageLayer = [CALayer layer];
- [self.layer addSublayer:self.imageLayer];
-
- self.selectedLayer = [CALayer layer];
- [self.layer insertSublayer:self.selectedLayer above:self.imageLayer];
-
- self.selectedLayer.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.5].CGColor;
- self.selectedLayer.opacity = 0.6f;
- self.clipsToBounds = YES;
- }
- return self;
-}
-
-- (void)setSourceImage:(UIImage *)sourceImage {
- CGSize size = CGSizeMake(sourceImage.size.width/30, sourceImage.size.height/30);
-
- UIGraphicsBeginImageContext(size);
-
- [sourceImage drawInRect:CGRectMake(0, 0, size.width, size.height)];
- self.scaledImage = UIGraphicsGetImageFromCurrentImageContext();
- self.imageLayer.shouldRasterize = YES;
- self.imageLayer.rasterizationScale = 1;
- self.imageLayer.magnificationFilter = kCAFilterNearest;
- self.imageLayer.contents = (id)self.scaledImage.CGImage;
-
- UIGraphicsEndImageContext();
-}
-
-- (void)setSelected:(BOOL)selected {
- super.selected = selected;
-
- if (selected){
- self.selectedLayer.opacity = 0.6f;
- } else {
- self.selectedLayer.opacity = 0.0f;
- }
-}
-
-- (void)layoutSubviews {
- [super layoutSubviews];
-
- [CATransaction begin];
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wcast-qual"
- [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
-#pragma clang diagnostic pop
- self.imageLayer.frame = self.imageFrame;
- self.imageLayer.masksToBounds = YES;
-
- self.selectedLayer.frame= self.bounds;
- [CATransaction commit];
-}
-
-- (BOOL)resizable {
- return YES;
-}
-
-@end
-
-#endif /* HOCKEYSDK_FEATURE_FEEDBACK */
diff --git a/submodules/HockeySDK-iOS/Classes/BITCategoryContainer.h b/submodules/HockeySDK-iOS/Classes/BITCategoryContainer.h
deleted file mode 100644
index 97b25740cd..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITCategoryContainer.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#import
-#import "HockeySDKFeatureConfig.h"
-
-#if HOCKEYSDK_FEATURE_METRICS
-
-#import "HockeySDKNullability.h"
-NS_ASSUME_NONNULL_BEGIN
-
-@interface BITCategoryContainer : NSObject
-
-+ (void)activateCategory;
-
-@end
-
-NS_ASSUME_NONNULL_END
-
-#endif /* HOCKEYSDK_FEATURE_METRICS */
diff --git a/submodules/HockeySDK-iOS/Classes/BITCategoryContainer.m b/submodules/HockeySDK-iOS/Classes/BITCategoryContainer.m
deleted file mode 100644
index 81f23e97f2..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITCategoryContainer.m
+++ /dev/null
@@ -1,144 +0,0 @@
-#import "BITCategoryContainer.h"
-#import "HockeySDKFeatureConfig.h"
-#import
-
-#if HOCKEYSDK_FEATURE_METRICS
-
-@implementation BITCategoryContainer
-
-+ (void)activateCategory {
-
-}
-
-@end
-
-
-#pragma mark - GZIP library
-
-
-//
-// GZIP.m
-//
-// Version 1.0.3
-//
-// Created by Nick Lockwood on 03/06/2012.
-// Copyright (C) 2012 Charcoal Design
-//
-// Distributed under the permissive zlib License
-// Get the latest version from here:
-//
-// https://github.com/nicklockwood/GZIP
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-// claim that you wrote the original software. If you use this software
-// in a product, an acknowledgment in the product documentation would be
-// appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such, and must not be
-// misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source distribution.
-//
-
-#import
-
-static const NSUInteger ChunkSize = 16384;
-
-@implementation NSData (BITGZIP)
-
-- (NSData *)bit_gzippedDataWithCompressionLevel:(float)level
-{
- if ([self length])
- {
- z_stream stream;
- stream.zalloc = Z_NULL;
- stream.zfree = Z_NULL;
- stream.opaque = Z_NULL;
- stream.avail_in = (uint)[self length];
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wcast-qual"
- stream.next_in = (Bytef *)[self bytes];
-#pragma clang diagnostic pop
- stream.total_out = 0;
- stream.avail_out = 0;
-
- int compression = (level < 0.0f)? Z_DEFAULT_COMPRESSION: (int)(roundf(level * 9));
- if (deflateInit2(&stream, compression, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY) == Z_OK)
- {
- NSMutableData *data = [NSMutableData dataWithLength:ChunkSize];
- while (stream.avail_out == 0)
- {
- if (stream.total_out >= [data length])
- {
- data.length += ChunkSize;
- }
- stream.next_out = (uint8_t *)[data mutableBytes] + stream.total_out;
- stream.avail_out = (uInt)([data length] - stream.total_out);
- deflate(&stream, Z_FINISH);
- }
- deflateEnd(&stream);
- data.length = stream.total_out;
- return data;
- }
- }
- return nil;
-}
-
-- (NSData *)bit_gzippedData
-{
- return [self bit_gzippedDataWithCompressionLevel:-1.0f];
-}
-
-- (NSData *)bit_gunzippedData
-{
- if ([self length])
- {
- z_stream stream;
- stream.zalloc = Z_NULL;
- stream.zfree = Z_NULL;
- stream.avail_in = (uint)[self length];
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wcast-qual"
- stream.next_in = (Bytef *)[self bytes];
-#pragma clang diagnostic pop
- stream.total_out = 0;
- stream.avail_out = 0;
-
- NSMutableData *data = [NSMutableData dataWithLength:(NSUInteger)([self length] * 1.5)];
- if (inflateInit2(&stream, 47) == Z_OK)
- {
- int status = Z_OK;
- while (status == Z_OK)
- {
- if (stream.total_out >= [data length])
- {
- data.length += [self length] / 2;
- }
- stream.next_out = (uint8_t *)[data mutableBytes] + stream.total_out;
- stream.avail_out = (uInt)([data length] - stream.total_out);
- status = inflate (&stream, Z_SYNC_FLUSH);
- }
- if (inflateEnd(&stream) == Z_OK)
- {
- if (status == Z_STREAM_END)
- {
- data.length = stream.total_out;
- return data;
- }
- }
- }
- }
- return nil;
-}
-
-@end
-
-#endif /* HOCKEYSDK_FEATURE_METRICS */
diff --git a/submodules/HockeySDK-iOS/Classes/BITChannel.h b/submodules/HockeySDK-iOS/Classes/BITChannel.h
deleted file mode 100644
index 3e4e5cbe77..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITChannel.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#import
-#import "HockeySDKFeatureConfig.h"
-
-#if HOCKEYSDK_FEATURE_METRICS
-
-@class BITConfiguration;
-@class BITTelemetryData;
-@class BITTelemetryContext;
-@class BITPersistence;
-
-#import "HockeySDKNullability.h"
-NS_ASSUME_NONNULL_BEGIN
-
-/**
- * Buffer of telemtry events, will be written to disk. Make sure the buffer is used in a threadsafe way.
- */
-FOUNDATION_EXPORT char *_Nullable BITTelemetryEventBuffer;
-
-/**
- * Items get queued before they are persisted and sent out as a batch. This class managed the queue, and forwards the batch
- * to the persistence layer once the max batch count has been reached.
- */
-@interface BITChannel : NSObject
-
-
-/**
- * Initializes a new BITChannel instance.
- *
- * @param telemetryContext the context used to add context values to the metrics payload
- * @param persistence the persistence used to save metrics after the queue gets flushed
- *
- * @return the telemetry context
- */
-- (instancetype)initWithTelemetryContext:(BITTelemetryContext *)telemetryContext persistence:(BITPersistence *) persistence;
-
-/**
- * Reset BITSafeJsonEventsString so we can start appending JSON dictionaries.
- *
- * @param item The telemetry object, which should be processed
- */
-- (void)enqueueTelemetryItem:(BITTelemetryData *)item;
-
-@end
-
-NS_ASSUME_NONNULL_END
-
-#endif /* HOCKEYSDK_FEATURE_METRICS */
diff --git a/submodules/HockeySDK-iOS/Classes/BITChannel.m b/submodules/HockeySDK-iOS/Classes/BITChannel.m
deleted file mode 100644
index af43b50b36..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITChannel.m
+++ /dev/null
@@ -1,505 +0,0 @@
-#import "HockeySDKFeatureConfig.h"
-
-#if HOCKEYSDK_FEATURE_METRICS
-
-#import "HockeySDKPrivate.h"
-#import "BITHockeyManager.h"
-#import "BITChannelPrivate.h"
-#import "BITHockeyHelper.h"
-#import "BITHockeyHelper+Application.h"
-#import "BITTelemetryContext.h"
-#import "BITTelemetryData.h"
-#import "BITEnvelope.h"
-#import "BITData.h"
-#import "BITDevice.h"
-#import "BITPersistencePrivate.h"
-#import "BITSender.h"
-#import
-
-
-static char *const BITDataItemsOperationsQueue = "net.hockeyapp.senderQueue";
-char *BITTelemetryEventBuffer;
-
-NSString *const BITChannelBlockedNotification = @"BITChannelBlockedNotification";
-
-static NSInteger const BITDefaultMaxBatchSize = 50;
-static NSInteger const BITDefaultBatchInterval = 15;
-static NSInteger const BITSchemaVersion = 2;
-
-static NSInteger const BITDebugMaxBatchSize = 5;
-static NSInteger const BITDebugBatchInterval = 3;
-
-typedef _Atomic(char*) atomic_charptr;
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface BITChannel ()
-
-@property (nonatomic, weak, nullable) id appDidEnterBackgroundObserver;
-
-@end
-
-@implementation BITChannel
-
-@synthesize persistence = _persistence;
-@synthesize channelBlocked = _channelBlocked;
-
-#pragma mark - Initialisation
-
-- (instancetype)init {
- if ((self = [super init])) {
- bit_resetEventBuffer(&BITTelemetryEventBuffer);
- _dataItemCount = 0;
- if (bit_isDebuggerAttached()) {
- _maxBatchSize = BITDebugMaxBatchSize;
- _batchInterval = BITDebugBatchInterval;
- } else {
- _maxBatchSize = BITDefaultMaxBatchSize;
- _batchInterval = BITDefaultBatchInterval;
- }
- dispatch_queue_t serialQueue = dispatch_queue_create(BITDataItemsOperationsQueue, DISPATCH_QUEUE_SERIAL);
- _dataItemsOperations = serialQueue;
-
- [self registerObservers];
- }
- return self;
-}
-
-- (instancetype)initWithTelemetryContext:(BITTelemetryContext *)telemetryContext persistence:(BITPersistence *)persistence {
- if ((self = [self init])) {
- _telemetryContext = telemetryContext;
- _persistence = persistence;
- }
- return self;
-}
-
-- (void)dealloc {
- [self unregisterObservers];
- [self invalidateTimer];
-}
-
-#pragma mark - Observers
-
-- (void) registerObservers {
- NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
- __weak typeof(self) weakSelf = self;
-
- if (nil == self.appDidEnterBackgroundObserver) {
- void (^notificationBlock)(NSNotification *note) = ^(NSNotification __unused *note) {
- typeof(self) strongSelf = weakSelf;
- if ([strongSelf timerIsRunning]) {
-
- /**
- * From the documentation for applicationDidEnterBackground:
- * It's likely any background tasks you start in applicationDidEnterBackground: will not run until after that method exits,
- * you should request additional background execution time before starting those tasks. In other words,
- * first call beginBackgroundTaskWithExpirationHandler: and then run the task on a dispatch queue or secondary thread.
- */
- UIApplication *application = [UIApplication sharedApplication];
- [strongSelf persistDataItemQueueWithBackgroundTask: application];
- }
- };
- self.appDidEnterBackgroundObserver = [center addObserverForName:UIApplicationDidEnterBackgroundNotification
- object:nil
- queue:NSOperationQueue.mainQueue
- usingBlock:notificationBlock];
- }
-}
-
-- (void) unregisterObservers {
- NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
- id appDidEnterBackgroundObserver = self.appDidEnterBackgroundObserver;
- if (appDidEnterBackgroundObserver) {
- [center removeObserver:appDidEnterBackgroundObserver];
- self.appDidEnterBackgroundObserver = nil;
- }
-}
-
-#pragma mark - Queue management
-
-- (BOOL)isQueueBusy {
- if (!self.channelBlocked) {
- BOOL persistenceBusy = ![self.persistence isFreeSpaceAvailable];
- if (persistenceBusy) {
- self.channelBlocked = YES;
- [self sendBlockingChannelNotification];
- }
- }
- return self.channelBlocked;
-}
-
-- (void)persistDataItemQueue:(char **)eventBuffer {
- [self invalidateTimer];
-
- // Make sure string (which points to BITTelemetryEventBuffer) is not changed.
- char *previousBuffer = NULL;
- char *newEmptyString = strdup("");
- do {
- previousBuffer = *eventBuffer;
-
- // This swaps pointers and makes sure eventBuffer now has the balue of newEmptyString.
- if (atomic_compare_exchange_strong((atomic_charptr *)eventBuffer, &previousBuffer, newEmptyString)) {
- @synchronized(self) {
- self.dataItemCount = 0;
- }
- break;
- }
- } while(true);
-
- // Nothing to persist, freeing memory and existing.
- if (!previousBuffer || strlen(previousBuffer) == 0) {
- free(previousBuffer);
- return;
- }
-
- // Persist the data
- NSData *bundle = [NSData dataWithBytes:previousBuffer length:strlen(previousBuffer)];
- [self.persistence persistBundle:bundle];
- free(previousBuffer);
-
- // Reset both, the async-signal-safe and item counter.
- [self resetQueue];
-}
-
-- (void)persistDataItemQueueWithBackgroundTask:(UIApplication *)application {
- __weak typeof(self) weakSelf = self;
- dispatch_async(self.dataItemsOperations, ^{
- typeof(self) strongSelf = weakSelf;
- [strongSelf persistDataItemQueue:&BITTelemetryEventBuffer];
- });
- [self createBackgroundTaskWhileDataIsSending:application withWaitingGroup:nil];
-}
-
-- (void)createBackgroundTaskWhileDataIsSending:(UIApplication *)application
- withWaitingGroup:(nullable dispatch_group_t)group {
- if (application == nil) {
- return;
- }
-
- // Queues needs for waiting consistently.
- NSArray *queues = @[
- self.dataItemsOperations, // For enqueue
- self.persistence.persistenceQueue, // For persist
- dispatch_get_main_queue() // For notification
- ];
-
- // Tracking for sender activity.
- // BITPersistenceSuccessNotification - start sending
- // BITSenderFinishSendingDataNotification - finish sending
- __block dispatch_group_t senderGroup = dispatch_group_create();
- __block NSInteger senderCounter = 0;
- __block id persistenceSuccessObserver = [[NSNotificationCenter defaultCenter]
- addObserverForName:BITPersistenceSuccessNotification
- object:nil
- queue:nil
- usingBlock:^(__unused NSNotification *notification) {
- dispatch_group_enter(senderGroup);
- senderCounter++;
- if (persistenceSuccessObserver) {
- [[NSNotificationCenter defaultCenter] removeObserver:persistenceSuccessObserver];
- persistenceSuccessObserver = nil;
- }
- }];
- __block id senderFinishSendingDataObserver = [[NSNotificationCenter defaultCenter]
- addObserverForName:BITSenderFinishSendingDataNotification
- object:nil
- queue:nil
- usingBlock:^(__unused NSNotification *notification) {
- if (senderCounter > 0) {
- dispatch_group_leave(senderGroup);
- senderCounter--;
- }
- if (senderFinishSendingDataObserver) {
- [[NSNotificationCenter defaultCenter] removeObserver:senderFinishSendingDataObserver];
- senderFinishSendingDataObserver = nil;
- }
- }];
-
- BITHockeyLogVerbose(@"BITChannel: Start background task");
- __block UIBackgroundTaskIdentifier backgroundTask = [application beginBackgroundTaskWithExpirationHandler:^{
- BITHockeyLogVerbose(@"BITChannel: Background task is expired");
- [application endBackgroundTask:backgroundTask];
- backgroundTask = UIBackgroundTaskInvalid;
- }];
- __block NSUInteger i = 0;
- __block __weak void (^weakWaitBlock)(void);
- void (^waitBlock)(void);
- weakWaitBlock = waitBlock = ^{
- if (i < queues.count) {
- dispatch_queue_t queue = [queues objectAtIndex:i++];
- BITHockeyLogVerbose(@"BITChannel: Waiting queue: %@", [[NSString alloc] initWithUTF8String:dispatch_queue_get_label(queue)]);
- dispatch_async(queue, weakWaitBlock);
- } else {
- BITHockeyLogVerbose(@"BITChannel: Waiting sender");
- dispatch_group_notify(senderGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- if (backgroundTask != UIBackgroundTaskInvalid) {
- BITHockeyLogVerbose(@"BITChannel: Cancel background task");
- [application endBackgroundTask:backgroundTask];
- backgroundTask = UIBackgroundTaskInvalid;
- }
- });
- }
- };
- if (group != nil) {
- BITHockeyLogVerbose(@"BITChannel: Waiting group");
- dispatch_group_notify((dispatch_group_t)group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), waitBlock);
- } else {
- waitBlock();
- }
-}
-
-// Resets the event buffer and count of events in the queue.
-- (void)resetQueue {
- @synchronized (self) {
- bit_resetEventBuffer(&BITTelemetryEventBuffer);
- self.dataItemCount = 0;
- }
-}
-
-#pragma mark - Adding to queue
-
-- (void)enqueueTelemetryItem:(BITTelemetryData *)item {
- [self enqueueTelemetryItem:item completionHandler:nil];
-}
-
-- (void)enqueueTelemetryItem:(BITTelemetryData *)item completionHandler:(nullable void (^)(void))completionHandler {
- if (!item) {
-
- // Item is nil: Do not enqueue item and abort operation.
- BITHockeyLogWarning(@"WARNING: TelemetryItem was nil.");
- if(completionHandler) {
- completionHandler();
- }
- return;
- }
-
- // First assigning self to weakSelf and then assigning this to strongSelf in the block is not very intuitive, this
- // blog post explains it very well: https://dhoerl.wordpress.com/2013/04/23/i-finally-figured-out-weakself-and-strongself/
- __weak typeof(self) weakSelf = self;
- dispatch_async(self.dataItemsOperations, ^{
-
- typeof(self) strongSelf = weakSelf;
- if (strongSelf.isQueueBusy) {
-
- // Case 1: Channel is in blocked state: Trigger sender, start timer to check after again after a while and abort operation.
- BITHockeyLogDebug(@"INFO: The channel is saturated. %@ was dropped.", item.debugDescription);
- if (![strongSelf timerIsRunning]) {
- [strongSelf startTimer];
- }
-
- if(completionHandler) {
- completionHandler();
- }
-
- return;
- }
-
- // Should be outside of @synchronized block!
- BOOL applicationIsInBackground = ([BITHockeyHelper applicationState] == BITApplicationStateBackground);
-
- // Enqueue item.
- @synchronized(self) {
- NSDictionary *dict = [strongSelf dictionaryForTelemetryData:item];
- [strongSelf appendDictionaryToEventBuffer:dict];
-
- // If the app is running in the background.
- if (strongSelf.dataItemCount >= strongSelf.maxBatchSize || applicationIsInBackground) {
-
- // Case 2: Max batch count has been reached or the app is running in the background, so write queue to disk and delete all items.
- [strongSelf persistDataItemQueue:&BITTelemetryEventBuffer];
- } else if (strongSelf.dataItemCount > 0) {
-
- // Case 3: It is the first item, let's start the timer.
- if (![strongSelf timerIsRunning]) {
- [strongSelf startTimer];
- }
- }
-
- if(completionHandler) {
- completionHandler();
- }
- }
- });
-}
-
-#pragma mark - Envelope telemerty items
-
-- (NSDictionary *)dictionaryForTelemetryData:(BITTelemetryData *) telemetryData {
-
- BITEnvelope *envelope = [self envelopeForTelemetryData:telemetryData];
- NSDictionary *dict = [envelope serializeToDictionary];
- return dict;
-}
-
-- (BITEnvelope *)envelopeForTelemetryData:(BITTelemetryData *)telemetryData {
- telemetryData.version = @(BITSchemaVersion);
-
- BITData *data = [BITData new];
- data.baseData = telemetryData;
- data.baseType = telemetryData.dataTypeName;
-
- BITEnvelope *envelope = [BITEnvelope new];
- envelope.time = bit_utcDateString([NSDate date]);
- envelope.iKey = self.telemetryContext.appIdentifier;
-
- envelope.tags = self.telemetryContext.contextDictionary;
- envelope.data = data;
- envelope.name = telemetryData.envelopeTypeName;
-
- return envelope;
-}
-
-#pragma mark - Serialization Helper
-
-- (NSString *)serializeDictionaryToJSONString:(NSDictionary *)dictionary {
- NSError *error;
- NSData *data = [NSJSONSerialization dataWithJSONObject:dictionary options:(NSJSONWritingOptions)0 error:&error];
- if (!data) {
- BITHockeyLogError(@"ERROR: JSONSerialization error: %@", error.localizedDescription);
- return @"{}";
- } else {
- return (NSString *)[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
- }
-}
-
-#pragma mark JSON Stream
-
-- (void)appendDictionaryToEventBuffer:(NSDictionary *)dictionary {
- if (dictionary) {
- NSString *string = [self serializeDictionaryToJSONString:dictionary];
-
- // Since we can't persist every event right away, we write it to a simple C string.
- // This can then be written to disk by a signal handler in case of a crash.
- @synchronized (self) {
- bit_appendStringToEventBuffer(string, &BITTelemetryEventBuffer);
- self.dataItemCount += 1;
- }
-
- BITHockeyLogVerbose(@"VERBOSE: Appended data to buffer:\n%@", string);
- }
-}
-
-void bit_appendStringToEventBuffer(NSString *string, char **eventBuffer) {
- if (eventBuffer == NULL) {
- return;
- }
-
- if (!string) {
- return;
- }
-
- if (*eventBuffer == NULL || strlen(*eventBuffer) == 0) {
- bit_resetEventBuffer(eventBuffer);
- }
-
- if (string.length == 0) {
- return;
- }
-
- do {
- char *newBuffer = NULL;
- char *previousBuffer = *eventBuffer;
-
- // Concatenate old string with new JSON string and add a comma.
- asprintf(&newBuffer, "%s%.*s\n", previousBuffer, (int)MIN(string.length, (NSUInteger)INT_MAX), string.UTF8String);
-
- // Compare newBuffer and previousBuffer. If they point to the same address, we are safe to use them.
- if (atomic_compare_exchange_strong((atomic_charptr *)eventBuffer, &previousBuffer, newBuffer)) {
-
- // Free the intermediate pointer.
- free(previousBuffer);
- return;
- } else {
-
- // newBuffer has been changed by another thread.
- free(newBuffer);
- }
- } while (true);
-}
-
-void bit_resetEventBuffer(char **eventBuffer) {
- if (!eventBuffer) {
- return;
- }
-
- char *prevString = NULL;
- char *newEmptyString = strdup("");
- do {
- prevString = *eventBuffer;
-
- // Compare pointers to strings to make sure we are still threadsafe!
- if (atomic_compare_exchange_strong((atomic_charptr *)eventBuffer, &prevString, newEmptyString)) {
- free(prevString);
- return;
- }
- } while(true);
-}
-
-#pragma mark - Batching
-
-- (NSUInteger)maxBatchSize {
- if(_maxBatchSize <= 0){
- return BITDefaultMaxBatchSize;
- }
- return _maxBatchSize;
-}
-
-- (void)invalidateTimer {
- @synchronized(self) {
- if (self.timerSource != nil) {
- dispatch_source_cancel((dispatch_source_t)self.timerSource);
- self.timerSource = nil;
- }
- }
-}
-
--(BOOL)timerIsRunning {
- @synchronized(self) {
- return self.timerSource != nil;
- }
-}
-
-- (void)startTimer {
- @synchronized(self) {
-
- // Reset timer, if it is already running.
- [self invalidateTimer];
-
- dispatch_source_t timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.dataItemsOperations);
- dispatch_source_set_timer(timerSource, dispatch_walltime(NULL, NSEC_PER_SEC * self.batchInterval), 1ull * NSEC_PER_SEC, 1ull * NSEC_PER_SEC);
- __weak typeof(self) weakSelf = self;
- dispatch_source_set_event_handler(timerSource, ^{
- typeof(self) strongSelf = weakSelf;
- if (strongSelf) {
- if (strongSelf.dataItemCount > 0) {
- [strongSelf persistDataItemQueue:&BITTelemetryEventBuffer];
- } else {
- strongSelf.channelBlocked = NO;
- }
- [strongSelf invalidateTimer];
- }
- });
- dispatch_resume(timerSource);
- self.timerSource = timerSource;
- }
-}
-
-/**
- * Send a BITHockeyBlockingChannelNotification to the main thread to notify observers that channel can't enqueue new items.
- * This is typically used to trigger sending.
- */
-- (void)sendBlockingChannelNotification {
- dispatch_async(dispatch_get_main_queue(), ^{
- BITHockeyLogDebug(@"Sending notification: %@", BITChannelBlockedNotification);
- [[NSNotificationCenter defaultCenter] postNotificationName:BITChannelBlockedNotification
- object:nil
- userInfo:nil];
- });
-}
-
-@end
-
-NS_ASSUME_NONNULL_END
-
-#endif /* HOCKEYSDK_FEATURE_METRICS */
-
diff --git a/submodules/HockeySDK-iOS/Classes/BITChannelPrivate.h b/submodules/HockeySDK-iOS/Classes/BITChannelPrivate.h
deleted file mode 100644
index 97c836f709..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITChannelPrivate.h
+++ /dev/null
@@ -1,125 +0,0 @@
-#import
-#import
-#import "HockeySDKFeatureConfig.h"
-
-#if HOCKEYSDK_FEATURE_METRICS
-
-@class BITTelemetryData;
-@class BITTelemetryContext;
-@class BITPersistence;
-
-#import "BITChannel.h"
-
-#import "HockeySDKNullability.h"
-NS_ASSUME_NONNULL_BEGIN
-
-@interface BITChannel ()
-
-/**
- * Notification that will be send on the main thread to notifiy observers that channel can't enqueue new items.
- * This is typically used to trigger sending to the server.
- */
-FOUNDATION_EXPORT NSString *const BITChannelBlockedNotification;
-
-/**
- * Telemetry context used by the channel to create the payload (testing).
- */
-@property (nonatomic, strong) BITTelemetryContext *telemetryContext;
-
-/**
- * Persistence instance for storing files after the queue gets flushed (testing).
- */
-@property (nonatomic, strong) BITPersistence *persistence;
-
-/*
- * Threshold for sending data to the server. Default batch size for debugging is 150, for release
- * configuration, the batch size is 5.
- *
- * Default: 50
- *
- * @warning: We advice to not set the batch size below 5 events.
- */
-@property (nonatomic) NSUInteger maxBatchSize;
-
-/*
- * Interval for sending data to the server in seconds.
- *
- * Default: 15
- */
-@property (nonatomic, assign) NSInteger batchInterval;
-
-/**
- * A timer source which is used to flush the queue after a cretain time.
- */
-@property (nonatomic, strong, nullable) dispatch_source_t timerSource;
-
-/**
- * A queue which makes array operations thread safe.
- */
-@property (nonatomic, strong) dispatch_queue_t dataItemsOperations;
-
-/**
- * An integer value that keeps tracks of the number of data items added to the JSON Stream string.
- */
-@property (nonatomic, assign) NSUInteger dataItemCount;
-
-/**
- * Indicates that channel is currently in a blocked state.
- */
-@property BOOL channelBlocked;
-
-/**
- * Manually trigger the BITChannel to persist all items currently in its data item queue.
- */
-- (void)persistDataItemQueue:(char *_Nullable*_Nullable)eventBuffer;
-
-/**
- * Create background task for queues and group.
- */
-- (void)createBackgroundTaskWhileDataIsSending:(UIApplication *)application
- withWaitingGroup:(nullable dispatch_group_t)group;
-
-/**
- * Adds the specified dictionary to the JSON Stream string.
- *
- * @param dictionary the dictionary object which is to be added to the JSON Stream queue string.
- */
-- (void)appendDictionaryToEventBuffer:(NSDictionary *)dictionary;
-
-/**
- * A C function that serializes a given dictionary to JSON and appends it to a char string
- *
- * @param string The C string which the dictionary's JSON representation will be appended to.
- */
-void bit_appendStringToEventBuffer(NSString *string, char *__nonnull*__nonnull eventBuffer);
-
-/**
- * Reset the event buffer so we can start appending JSON dictionaries.
- *
- * @param eventBuffer The string that will be reset.
- */
-void bit_resetEventBuffer(char *__nonnull*__nonnull eventBuffer);
-
-/**
- * A method which indicates whether the telemetry pipeline is busy and no new data should be enqueued.
- * Currently, we drop telemetry data if this returns YES.
- * This depends on defaultMaxBatchCount and defaultBatchInterval.
- *
- * @return Returns yes if currently no new data should be enqueued on the channel.
- */
-- (BOOL)isQueueBusy;
-
-/**
- * Enqueue a telemetry item. This is for testing purposes where we actually use the completion handler.
- *
- * @param completionHandler The completion handler that will be called after enqueuing a BITTelemetryData object.
- *
- * @discussion intended for testing purposes.
- */
-- (void)enqueueTelemetryItem:(BITTelemetryData *)item completionHandler:(nullable void (^)(void))completionHandler;
-
-@end
-
-NS_ASSUME_NONNULL_END
-
-#endif /* HOCKEYSDK_FEATURE_METRICS */
diff --git a/submodules/HockeySDK-iOS/Classes/BITCrashAttachment.h b/submodules/HockeySDK-iOS/Classes/BITCrashAttachment.h
deleted file mode 100644
index 9f7d4273c0..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITCrashAttachment.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import "BITHockeyAttachment.h"
-
-/**
- Deprecated: Provides support to add binary attachments to crash reports
-
- This class is not needed any longer and exists for compatibility purposes with
- HockeySDK-iOS 3.5.5.
-
- It is a subclass of `BITHockeyAttachment` which only provides an initializer
- that is compatible with the one of HockeySDK-iOS 3.5.5.
-
- This is used by `[BITCrashManagerDelegate attachmentForCrashManager:]`
-
- @see BITHockeyAttachment
- */
-@interface BITCrashAttachment : BITHockeyAttachment
-
-/**
- Create an BITCrashAttachment instance with a given filename and NSData object
-
- @param filename The filename the attachment should get
- @param crashAttachmentData The attachment data as NSData
- @param contentType The content type of your data as MIME type
-
- @return An instance of BITCrashAttachment
- */
-- (instancetype)initWithFilename:(NSString *)filename
- crashAttachmentData:(NSData *)crashAttachmentData
- contentType:(NSString *)contentType;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITCrashAttachment.m b/submodules/HockeySDK-iOS/Classes/BITCrashAttachment.m
deleted file mode 100644
index f4f408d25d..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITCrashAttachment.m
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_CRASH_REPORTER
-
-#import "BITCrashAttachment.h"
-
-@implementation BITCrashAttachment
-
-- (instancetype)initWithFilename:(NSString *)filename
- crashAttachmentData:(NSData *)crashAttachmentData
- contentType:(NSString *)contentType
-{
- self = [super initWithFilename:filename hockeyAttachmentData:crashAttachmentData contentType:contentType];
-
- return self;
-}
-
-@end
-
-#endif
diff --git a/submodules/HockeySDK-iOS/Classes/BITCrashCXXExceptionHandler.h b/submodules/HockeySDK-iOS/Classes/BITCrashCXXExceptionHandler.h
deleted file mode 100644
index 9efc2d2292..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITCrashCXXExceptionHandler.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Author: Gwynne Raskind
- *
- * Copyright (c) 2015 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import
-#import "HockeySDKNullability.h"
-
-typedef struct {
- const void * __nullable exception;
- const char * __nullable exception_type_name;
- const char * __nullable exception_message;
- uint32_t exception_frames_count;
- const uintptr_t * __nonnull exception_frames;
-} BITCrashUncaughtCXXExceptionInfo;
-
-typedef void (*BITCrashUncaughtCXXExceptionHandler)(
- const BITCrashUncaughtCXXExceptionInfo * __nonnull info
-);
-
-@interface BITCrashUncaughtCXXExceptionHandlerManager : NSObject
-
-+ (void)addCXXExceptionHandler:(nonnull BITCrashUncaughtCXXExceptionHandler)handler;
-+ (void)removeCXXExceptionHandler:(nonnull BITCrashUncaughtCXXExceptionHandler)handler;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITCrashCXXExceptionHandler.mm b/submodules/HockeySDK-iOS/Classes/BITCrashCXXExceptionHandler.mm
deleted file mode 100644
index 233ab5ea27..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITCrashCXXExceptionHandler.mm
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Author: Gwynne Raskind
- *
- * Copyright (c) 2015 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_CRASH_REPORTER
-
-#import "BITCrashCXXExceptionHandler.h"
-#import
-#import
-#import
-#import
-#import
-#import
-#import
-#import
-#import
-#import
-
-typedef std::vector BITCrashUncaughtCXXExceptionHandlerList;
-typedef struct
-{
- void *exception_object;
- uintptr_t call_stack[128];
- uint32_t num_frames;
-} BITCrashCXXExceptionTSInfo;
-
-static bool _BITCrashIsOurTerminateHandlerInstalled = false;
-static std::terminate_handler _BITCrashOriginalTerminateHandler = nullptr;
-static BITCrashUncaughtCXXExceptionHandlerList _BITCrashUncaughtExceptionHandlerList;
-// We are ignoring warnings about OSSpinLock being deprecated because a replacement API
-// for this was introduced only in iOS 10.0.
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-static OSSpinLock _BITCrashCXXExceptionHandlingLock = OS_SPINLOCK_INIT;
-#pragma clang diagnostic pop
-static pthread_key_t _BITCrashCXXExceptionInfoTSDKey = 0;
-
-@implementation BITCrashUncaughtCXXExceptionHandlerManager
-
-extern "C" void __attribute__((noreturn)) __cxa_throw(void *exception_object, std::type_info *tinfo, void (*dest)(void *))
-{
- // Purposely do not take a lock in this function. The aim is to be as fast as
- // possible. While we could really use some of the info set up by the real
- // __cxa_throw, if we call through we never get control back - the function is
- // noreturn and jumps to landing pads. Most of the stuff in __cxxabiv1 also
- // won't work yet. We therefore have to do these checks by hand.
-
- // The technique for distinguishing Objective-C exceptions is based on the
- // implementation of objc_exception_throw(). It's weird, but it's fast. The
- // explicit symbol load and NULL checks should guard against the
- // implementation changing in a future version. (Or not existing in an earlier
- // version).
-
- typedef void (*cxa_throw_func)(void *, std::type_info *, void (*)(void *)) __attribute__((noreturn));
- static dispatch_once_t predicate = 0;
- static cxa_throw_func __original__cxa_throw = nullptr;
- static const void **__real_objc_ehtype_vtable = nullptr;
-
- dispatch_once(&predicate, ^ {
- __original__cxa_throw = reinterpret_cast(dlsym(RTLD_NEXT, "__cxa_throw"));
- __real_objc_ehtype_vtable = reinterpret_cast(dlsym(RTLD_DEFAULT, "objc_ehtype_vtable"));
- });
-
- // Actually check for Objective-C exceptions.
- if (tinfo && __real_objc_ehtype_vtable && // Guard from an ABI change
- *reinterpret_cast(tinfo) == __real_objc_ehtype_vtable + 2) {
- goto callthrough;
- }
-
- // Any other exception that came here has to be C++, since Objective-C is the
- // only (known) runtime that hijacks the C++ ABI this way. We need to save off
- // a backtrace.
- // Invariant: If the terminate handler is installed, the TSD key must also be
- // initialized.
- if (_BITCrashIsOurTerminateHandlerInstalled) {
- BITCrashCXXExceptionTSInfo *info = static_cast(pthread_getspecific(_BITCrashCXXExceptionInfoTSDKey));
-
- if (!info) {
- info = reinterpret_cast(calloc(1, sizeof(BITCrashCXXExceptionTSInfo)));
- pthread_setspecific(_BITCrashCXXExceptionInfoTSDKey, info);
- }
- info->exception_object = exception_object;
- // XXX: All significant time in this call is spent right here.
- info->num_frames = backtrace(reinterpret_cast(&info->call_stack[0]), sizeof(info->call_stack) / sizeof(info->call_stack[0]));
- }
-
-callthrough:
- if (__original__cxa_throw) {
- __original__cxa_throw(exception_object, tinfo, dest);
- } else {
- abort();
- }
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunreachable-code"
- __builtin_unreachable();
-#pragma clang diagnostic pop
-}
-
-__attribute__((always_inline))
-static inline void BITCrashIterateExceptionHandlers_unlocked(const BITCrashUncaughtCXXExceptionInfo &info)
-{
- for (const auto &handler : _BITCrashUncaughtExceptionHandlerList) {
- handler(&info);
- }
-}
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-static void BITCrashUncaughtCXXTerminateHandler(void)
-{
- BITCrashUncaughtCXXExceptionInfo info = {
- .exception = nullptr,
- .exception_type_name = nullptr,
- .exception_message = nullptr,
- .exception_frames_count = 0,
- .exception_frames = nullptr,
- };
- auto p = std::current_exception();
-
- OSSpinLockLock(&_BITCrashCXXExceptionHandlingLock); {
- if (p) { // explicit operator bool
- info.exception = reinterpret_cast(&p);
- info.exception_type_name = __cxxabiv1::__cxa_current_exception_type()->name();
-
- BITCrashCXXExceptionTSInfo *recorded_info = reinterpret_cast(pthread_getspecific(_BITCrashCXXExceptionInfoTSDKey));
-
- if (recorded_info) {
- info.exception_frames_count = recorded_info->num_frames - 1;
- info.exception_frames = &recorded_info->call_stack[1];
- } else {
- // There's no backtrace, grab this function's trace instead. Probably
- // means the exception came from a dynamically loaded library.
- void *frames[128] = { nullptr };
-
- info.exception_frames_count = backtrace(&frames[0], sizeof(frames) / sizeof(frames[0])) - 1;
- info.exception_frames = reinterpret_cast(&frames[1]);
- }
-
- try {
- std::rethrow_exception(p);
- } catch (const std::exception &e) { // C++ exception.
- info.exception_message = e.what();
- BITCrashIterateExceptionHandlers_unlocked(info);
- } catch (const std::exception *e) { // C++ exception by pointer.
- info.exception_message = e->what();
- BITCrashIterateExceptionHandlers_unlocked(info);
- } catch (const std::string &e) { // C++ string as exception.
- info.exception_message = e.c_str();
- BITCrashIterateExceptionHandlers_unlocked(info);
- } catch (const std::string *e) { // C++ string pointer as exception.
- info.exception_message = e->c_str();
- BITCrashIterateExceptionHandlers_unlocked(info);
- } catch (const char *e) { // Plain string as exception.
- info.exception_message = e;
- BITCrashIterateExceptionHandlers_unlocked(info);
- } catch (id __unused e) { // Objective-C exception. Pass it on to Foundation.
- OSSpinLockUnlock(&_BITCrashCXXExceptionHandlingLock);
- if (_BITCrashOriginalTerminateHandler != nullptr) {
- _BITCrashOriginalTerminateHandler();
- }
- return;
- } catch (...) { // Any other kind of exception. No message.
- BITCrashIterateExceptionHandlers_unlocked(info);
- }
- }
- } OSSpinLockUnlock(&_BITCrashCXXExceptionHandlingLock); // In case terminate is called reentrantly by pasing it on
-
- if (_BITCrashOriginalTerminateHandler != nullptr) {
- _BITCrashOriginalTerminateHandler();
- } else {
- abort();
- }
-}
-
-+ (void)addCXXExceptionHandler:(BITCrashUncaughtCXXExceptionHandler)handler
-{
- static dispatch_once_t key_predicate = 0;
-
- // This only EVER has to be done once, since we don't delete the TSD later
- // (there's no reason to delete it).
- dispatch_once(&key_predicate, ^ {
- pthread_key_create(&_BITCrashCXXExceptionInfoTSDKey, free);
- });
-
- OSSpinLockLock(&_BITCrashCXXExceptionHandlingLock); {
- if (!_BITCrashIsOurTerminateHandlerInstalled) {
- _BITCrashOriginalTerminateHandler = std::set_terminate(BITCrashUncaughtCXXTerminateHandler);
- _BITCrashIsOurTerminateHandlerInstalled = true;
- }
- _BITCrashUncaughtExceptionHandlerList.push_back(handler);
- } OSSpinLockUnlock(&_BITCrashCXXExceptionHandlingLock);
-}
-
-+ (void)removeCXXExceptionHandler:(BITCrashUncaughtCXXExceptionHandler)handler
-{
- OSSpinLockLock(&_BITCrashCXXExceptionHandlingLock); {
- auto i = std::find(_BITCrashUncaughtExceptionHandlerList.begin(), _BITCrashUncaughtExceptionHandlerList.end(), handler);
-
- if (i != _BITCrashUncaughtExceptionHandlerList.end()) {
- _BITCrashUncaughtExceptionHandlerList.erase(i);
- }
-
- if (_BITCrashIsOurTerminateHandlerInstalled) {
- if (_BITCrashUncaughtExceptionHandlerList.empty()) {
- std::terminate_handler previous_handler = std::set_terminate(_BITCrashOriginalTerminateHandler);
-
- if (previous_handler != BITCrashUncaughtCXXTerminateHandler) {
- std::set_terminate(previous_handler);
- } else {
- _BITCrashIsOurTerminateHandlerInstalled = false;
- _BITCrashOriginalTerminateHandler = nullptr;
- }
- }
- }
- } OSSpinLockUnlock(&_BITCrashCXXExceptionHandlingLock);
-}
-#pragma clang diagnostic pop
-
-@end
-
-#endif /* HOCKEYSDK_FEATURE_CRASH_REPORTER */
diff --git a/submodules/HockeySDK-iOS/Classes/BITCrashDetails.h b/submodules/HockeySDK-iOS/Classes/BITCrashDetails.h
deleted file mode 100644
index be2d62fa3a..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITCrashDetails.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import
-
-/**
- * Provides details about the crash that occurred in the previous app session
- */
-@interface BITCrashDetails : NSObject
-
-/**
- * UUID for the crash report
- */
-@property (nonatomic, readonly, copy) NSString *incidentIdentifier;
-
-/**
- * UUID for the app installation on the device
- */
-@property (nonatomic, readonly, copy) NSString *reporterKey;
-
-/**
- * Signal that caused the crash
- */
-@property (nonatomic, readonly, copy) NSString *signal;
-
-/**
- * Exception name that triggered the crash, nil if the crash was not caused by an exception
- */
-@property (nonatomic, readonly, copy) NSString *exceptionName;
-
-/**
- * Exception reason, nil if the crash was not caused by an exception
- */
-@property (nonatomic, readonly, copy) NSString *exceptionReason;
-
-/**
- * Date and time the app started, nil if unknown
- */
-@property (nonatomic, readonly, strong) NSDate *appStartTime;
-
-/**
- * Date and time the crash occurred, nil if unknown
- */
-@property (nonatomic, readonly, strong) NSDate *crashTime;
-
-/**
- * Operation System version string the app was running on when it crashed.
- */
-@property (nonatomic, readonly, copy) NSString *osVersion;
-
-/**
- * Operation System build string the app was running on when it crashed
- *
- * This may be unavailable.
- */
-@property (nonatomic, readonly, copy) NSString *osBuild;
-
-/**
- * CFBundleShortVersionString value of the app that crashed
- *
- * Can be `nil` if the crash was captured with an older version of the SDK
- * or if the app doesn't set the value.
- */
-@property (nonatomic, readonly, copy) NSString *appVersion;
-
-/**
- * CFBundleVersion value of the app that crashed
- */
-@property (nonatomic, readonly, copy) NSString *appBuild;
-
-/**
- * Identifier of the app process that crashed
- */
-@property (nonatomic, readonly, assign) NSUInteger appProcessIdentifier;
-
-/**
- Indicates if the app was killed while being in foreground from the iOS
-
- If `[BITCrashManager enableAppNotTerminatingCleanlyDetection]` is enabled, use this on startup
- to check if the app starts the first time after it was killed by iOS in the previous session.
-
- This can happen if it consumed too much memory or the watchdog killed the app because it
- took too long to startup or blocks the main thread for too long, or other reasons. See Apple
- documentation: https://developer.apple.com/library/ios/qa/qa1693/_index.html
-
- See `[BITCrashManager enableAppNotTerminatingCleanlyDetection]` for more details about which kind of kills can be detected.
-
- @warning This property only has a correct value, once `[BITHockeyManager startManager]` was
- invoked! In addition, it is automatically disabled while a debugger session is active!
-
- @see `[BITCrashManager enableAppNotTerminatingCleanlyDetection]`
- @see `[BITCrashManager didReceiveMemoryWarningInLastSession]`
-
- @return YES if the details represent an app kill instead of a crash
- */
-- (BOOL)isAppKill;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITCrashDetails.m b/submodules/HockeySDK-iOS/Classes/BITCrashDetails.m
deleted file mode 100644
index b9fa38f6bb..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITCrashDetails.m
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_CRASH_REPORTER
-
-#import "BITCrashDetails.h"
-#import "BITCrashDetailsPrivate.h"
-
-NSString *const kBITCrashKillSignal = @"SIGKILL";
-
-@implementation BITCrashDetails
-
-- (instancetype)initWithIncidentIdentifier:(NSString *)incidentIdentifier
- reporterKey:(NSString *)reporterKey
- signal:(NSString *)signal
- exceptionName:(NSString *)exceptionName
- exceptionReason:(NSString *)exceptionReason
- appStartTime:(NSDate *)appStartTime
- crashTime:(NSDate *)crashTime
- osVersion:(NSString *)osVersion
- osBuild:(NSString *)osBuild
- appVersion:(NSString *)appVersion
- appBuild:(NSString *)appBuild
- appProcessIdentifier:(NSUInteger)appProcessIdentifier
-{
- if ((self = [super init])) {
- _incidentIdentifier = incidentIdentifier;
- _reporterKey = reporterKey;
- _signal = signal;
- _exceptionName = exceptionName;
- _exceptionReason = exceptionReason;
- _appStartTime = appStartTime;
- _crashTime = crashTime;
- _osVersion = osVersion;
- _osBuild = osBuild;
- _appVersion = appVersion;
- _appBuild = appBuild;
- _appProcessIdentifier = appProcessIdentifier;
- }
- return self;
-}
-
-- (BOOL)isAppKill {
- BOOL result = NO;
-
- if (self.signal && [[self.signal uppercaseString] isEqualToString:kBITCrashKillSignal])
- result = YES;
-
- return result;
-}
-
-@end
-
-#endif /* HOCKEYSDK_FEATURE_CRASH_REPORTER */
diff --git a/submodules/HockeySDK-iOS/Classes/BITCrashDetailsPrivate.h b/submodules/HockeySDK-iOS/Classes/BITCrashDetailsPrivate.h
deleted file mode 100644
index 48b3061344..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITCrashDetailsPrivate.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-extern NSString *const kBITCrashKillSignal;
-
-@interface BITCrashDetails () {
-
-}
-
-- (instancetype)initWithIncidentIdentifier:(NSString *)incidentIdentifier
- reporterKey:(NSString *)reporterKey
- signal:(NSString *)signal
- exceptionName:(NSString *)exceptionName
- exceptionReason:(NSString *)exceptionReason
- appStartTime:(NSDate *)appStartTime
- crashTime:(NSDate *)crashTime
- osVersion:(NSString *)osVersion
- osBuild:(NSString *)osBuild
- appVersion:(NSString *)appVersion
- appBuild:(NSString *)appBuild
- appProcessIdentifier:(NSUInteger)appProcessIdentifier;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITCrashManager.h b/submodules/HockeySDK-iOS/Classes/BITCrashManager.h
deleted file mode 100644
index 69e7500f80..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITCrashManager.h
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * Author: Andreas Linde
- * Kent Sutherland
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * Copyright (c) 2011 Andreas Linde & Kent Sutherland.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import
-
-#import "BITHockeyBaseManager.h"
-
-@class BITCrashDetails;
-@class BITCrashMetaData;
-
-
-/**
- * Custom block that handles the alert that prompts the user whether they want to send crash reports
- */
-typedef void(^BITCustomAlertViewHandler)(void);
-
-
-/**
- * Crash Manager status
- */
-typedef NS_ENUM(NSUInteger, BITCrashManagerStatus) {
- /**
- * Crash reporting is disabled
- */
- BITCrashManagerStatusDisabled = 0,
- /**
- * User is asked each time before sending
- */
- BITCrashManagerStatusAlwaysAsk = 1,
- /**
- * Each crash report is send automatically
- */
- BITCrashManagerStatusAutoSend = 2
-};
-
-
-/**
- * Prototype of a callback function used to execute additional user code. Called upon completion of crash
- * handling, after the crash report has been written to disk.
- *
- * @param context The API client's supplied context value.
- *
- * @see `BITCrashManagerCallbacks`
- * @see `[BITCrashManager setCrashCallbacks:]`
- */
-typedef void (*BITCrashManagerPostCrashSignalCallback)(void *context);
-
-/**
- * This structure contains callbacks supported by `BITCrashManager` to allow the host application to perform
- * additional tasks prior to program termination after a crash has occurred.
- *
- * @see `BITCrashManagerPostCrashSignalCallback`
- * @see `[BITCrashManager setCrashCallbacks:]`
- */
-typedef struct BITCrashManagerCallbacks {
- /** An arbitrary user-supplied context value. This value may be NULL. */
- void *context;
-
- /**
- * The callback used to report caught signal information.
- */
- BITCrashManagerPostCrashSignalCallback handleSignal;
-} BITCrashManagerCallbacks;
-
-
-/**
- * Crash Manager alert user input
- */
-typedef NS_ENUM(NSUInteger, BITCrashManagerUserInput) {
- /**
- * User chose not to send the crash report
- */
- BITCrashManagerUserInputDontSend = 0,
- /**
- * User wants the crash report to be sent
- */
- BITCrashManagerUserInputSend = 1,
- /**
- * User chose to always send crash reports
- */
- BITCrashManagerUserInputAlwaysSend = 2
-
-};
-
-
-@protocol BITCrashManagerDelegate;
-
-/**
- The crash reporting module.
-
- This is the HockeySDK module for handling crash reports, including when distributed via the App Store.
- As a foundation it is using the open source, reliable and async-safe crash reporting framework
- [PLCrashReporter](https://code.google.com/p/plcrashreporter/).
-
- This module works as a wrapper around the underlying crash reporting framework and provides functionality to
- detect new crashes, queues them if networking is not available, present a user interface to approve sending
- the reports to the HockeyApp servers and more.
-
- It also provides options to add additional meta information to each crash report, like `userName`, `userEmail`
- via `BITHockeyManagerDelegate` protocol, and additional textual log information via `BITCrashManagerDelegate`
- protocol and a way to detect startup crashes so you can adjust your startup process to get these crash reports
- too and delay your app initialization.
-
- Crashes are send the next time the app starts. If `crashManagerStatus` is set to `BITCrashManagerStatusAutoSend`,
- crashes will be send without any user interaction, otherwise an alert will appear allowing the users to decide
- whether they want to send the report or not. This module is not sending the reports right when the crash happens
- deliberately, because if is not safe to implement such a mechanism while being async-safe (any Objective-C code
- is _NOT_ async-safe!) and not causing more danger like a deadlock of the device, than helping. We found that users
- do start the app again because most don't know what happened, and you will get by far most of the reports.
-
- Sending the reports on startup is done asynchronously (non-blocking). This is the only safe way to ensure
- that the app won't be possibly killed by the iOS watchdog process, because startup could take too long
- and the app could not react to any user input when network conditions are bad or connectivity might be
- very slow.
-
- It is possible to check upon startup if the app crashed before using `didCrashInLastSession` and also how much
- time passed between the app launch and the crash using `timeIntervalCrashInLastSessionOccurred`. This allows you
- to add additional code to your app delaying the app start until the crash has been successfully send if the crash
- occurred within a critical startup timeframe, e.g. after 10 seconds. The `BITCrashManagerDelegate` protocol provides
- various delegates to inform the app about it's current status so you can continue the remaining app startup setup
- after sending has been completed. The documentation contains a guide
- [How to handle Crashes on startup](HowTo-Handle-Crashes-On-Startup) with an example on how to do that.
-
- More background information on this topic can be found in the following blog post by Landon Fuller, the
- developer of [PLCrashReporter](https://www.plcrashreporter.org), about writing reliable and
- safe crash reporting: [Reliable Crash Reporting](http://goo.gl/WvTBR)
-
- @warning If you start the app with the Xcode debugger attached, detecting crashes will _NOT_ be enabled!
- */
-
-@interface BITCrashManager : BITHockeyBaseManager
-
-
-///-----------------------------------------------------------------------------
-/// @name Configuration
-///-----------------------------------------------------------------------------
-
-/** Set the default status of the Crash Manager
-
- Defines if the crash reporting feature should be disabled, ask the user before
- sending each crash report or send crash reports automatically without
- asking.
-
- The default value is `BITCrashManagerStatusAlwaysAsk`. The user can switch to
- `BITCrashManagerStatusAutoSend` by choosing "Always" in the dialog (since
- `showAlwaysButton` default is _YES_).
-
- The current value is always stored in User Defaults with the key
- `BITCrashManagerStatus`.
-
- If you intend to implement a user setting to let them enable or disable
- crash reporting, this delegate should be used to return that value. You also
- have to make sure the new value is stored in the UserDefaults with the key
- `BITCrashManagerStatus`.
-
- @see BITCrashManagerStatus
- @see showAlwaysButton
- */
-@property (nonatomic, assign) BITCrashManagerStatus crashManagerStatus;
-
-
-/**
- * Trap fatal signals via a Mach exception server.
- *
- * By default the SDK is using the safe and proven in-process BSD Signals for catching crashes.
- * This option provides an option to enable catching fatal signals via a Mach exception server
- * instead.
- *
- * We strongly advice _NOT_ to enable Mach exception handler in release versions of your apps!
- *
- * Default: _NO_
- *
- * @warning The Mach exception handler executes in-process, and will interfere with debuggers when
- * they attempt to suspend all active threads (which will include the Mach exception handler).
- * Mach-based handling should _NOT_ be used when a debugger is attached. The SDK will not
- * enabled catching exceptions if the app is started with the debugger running. If you attach
- * the debugger during runtime, this may cause issues the Mach exception handler is enabled!
- * @see isDebuggerAttached
- */
-@property (nonatomic, assign, getter=isMachExceptionHandlerEnabled) BOOL enableMachExceptionHandler;
-
-
-/**
- * Enable on device symbolication for system symbols
- *
- * By default, the SDK does not symbolicate on the device, since this can
- * take a few seconds at each crash. Also note that symbolication on the
- * device might not be able to retrieve all symbols.
- *
- * Enable if you want to analyze crashes on unreleased OS versions.
- *
- * Default: _NO_
- */
-@property (nonatomic, assign, getter=isOnDeviceSymbolicationEnabled) BOOL enableOnDeviceSymbolication;
-
-
-/**
- * EXPERIMENTAL: Enable heuristics to detect the app not terminating cleanly
- *
- * This allows it to get a crash report if the app got killed while being in the foreground
- * because of one of the following reasons:
- *
- * - The main thread was blocked for too long
- * - The app took too long to start up
- * - The app tried to allocate too much memory. If iOS did send a memory warning before killing the app because of this reason, `didReceiveMemoryWarningInLastSession` returns `YES`.
- * - Permitted background duration if main thread is running in an endless loop
- * - App failed to resume in time if main thread is running in an endless loop
- * - If `enableMachExceptionHandler` is not activated, crashed due to stack overflow will also be reported
- *
- * The following kills can _NOT_ be detected:
- *
- * - Terminating the app takes too long
- * - Permitted background duration too long for all other cases
- * - App failed to resume in time for all other cases
- * - possibly more cases
- *
- * Crash reports triggered by this mechanisms do _NOT_ contain any stack traces since the time of the kill
- * cannot be intercepted and hence no stack trace of the time of the kill event can't be gathered.
- *
- * The heuristic is implemented as follows:
- * If the app never gets a `UIApplicationDidEnterBackgroundNotification` or `UIApplicationWillTerminateNotification`
- * notification, PLCrashReporter doesn't detect a crash itself, and the app starts up again, it is assumed that
- * the app got either killed by iOS while being in foreground or a crash occurred that couldn't be detected.
- *
- * Default: _NO_
- *
- * @warning This is a heuristic and it _MAY_ report false positives! It has been tested with iOS 6.1 and iOS 7.
- * Depending on Apple changing notification events, new iOS version may cause more false positives!
- *
- * @see lastSessionCrashDetails
- * @see didReceiveMemoryWarningInLastSession
- * @see `BITCrashManagerDelegate considerAppNotTerminatedCleanlyReportForCrashManager:`
- * @see [Apple Technical Note TN2151](https://developer.apple.com/library/ios/technotes/tn2151/_index.html)
- * @see [Apple Technical Q&A QA1693](https://developer.apple.com/library/ios/qa/qa1693/_index.html)
- */
-@property (nonatomic, assign, getter = isAppNotTerminatingCleanlyDetectionEnabled) BOOL enableAppNotTerminatingCleanlyDetection;
-
-
-/**
- * Set the callbacks that will be executed prior to program termination after a crash has occurred
- *
- * PLCrashReporter provides support for executing an application specified function in the context
- * of the crash reporter's signal handler, after the crash report has been written to disk.
- *
- * Writing code intended for execution inside of a signal handler is exceptionally difficult, and is _NOT_ recommended!
- *
- * _Program Flow and Signal Handlers_
- *
- * When the signal handler is called the normal flow of the program is interrupted, and your program is an unknown state. Locks may be held, the heap may be corrupt (or in the process of being updated), and your signal handler may invoke a function that was being executed at the time of the signal. This may result in deadlocks, data corruption, and program termination.
- *
- * _Async-Safe Functions_
- *
- * A subset of functions are defined to be async-safe by the OS, and are safely callable from within a signal handler. If you do implement a custom post-crash handler, it must be async-safe. A table of POSIX-defined async-safe functions and additional information is available from the [CERT programming guide - SIG30-C](https://www.securecoding.cert.org/confluence/display/seccode/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers).
- *
- * Most notably, the Objective-C runtime itself is not async-safe, and Objective-C may not be used within a signal handler.
- *
- * Documentation taken from PLCrashReporter: https://www.plcrashreporter.org/documentation/api/v1.2-rc2/async_safety.html
- *
- * @see BITCrashManagerPostCrashSignalCallback
- * @see BITCrashManagerCallbacks
- *
- * @param callbacks A pointer to an initialized PLCrashReporterCallback structure, see https://www.plcrashreporter.org/documentation/api/v1.2-rc2/struct_p_l_crash_reporter_callbacks.html
- */
-- (void)setCrashCallbacks: (BITCrashManagerCallbacks *) callbacks;
-
-
-/**
- Flag that determines if an "Always" option should be shown
-
- If enabled the crash reporting alert will also present an "Always" option, so
- the user doesn't have to approve every single crash over and over again.
-
- If If `crashManagerStatus` is set to `BITCrashManagerStatusAutoSend`, this property
- has no effect, since no alert will be presented.
-
- Default: _YES_
-
- @see crashManagerStatus
- */
-@property (nonatomic, assign, getter=shouldShowAlwaysButton) BOOL showAlwaysButton;
-
-
-///-----------------------------------------------------------------------------
-/// @name Crash Meta Information
-///-----------------------------------------------------------------------------
-
-/**
- Indicates if the app crash in the previous session
-
- Use this on startup, to check if the app starts the first time after it crashed
- previously. You can use this also to disable specific events, like asking
- the user to rate your app.
-
- @warning This property only has a correct value, once `[BITHockeyManager startManager]` was
- invoked!
-
- @see lastSessionCrashDetails
- */
-@property (nonatomic, readonly) BOOL didCrashInLastSession;
-
-/**
- Provides an interface to pass user input from a custom alert to a crash report
-
- @param userInput Defines the users action wether to send, always send, or not to send the crash report.
- @param userProvidedMetaData The content of this optional BITCrashMetaData instance will be attached to the crash report and allows to ask the user for e.g. additional comments or info.
-
- @return Returns YES if the input is a valid option and successfully triggered further processing of the crash report
-
- @see BITCrashManagerUserInput
- @see BITCrashMetaData
- */
-- (BOOL)handleUserInput:(BITCrashManagerUserInput)userInput withUserProvidedMetaData:(BITCrashMetaData *)userProvidedMetaData;
-
-/**
- Lets you set a custom block which handles showing a custom UI and asking the user
- whether they want to send the crash report.
-
- This replaces the default alert the SDK would show!
-
- You can use this to present any kind of user interface which asks the user for additional information,
- e.g. what they did in the app before the app crashed.
-
- In addition to this you should always ask your users if they agree to send crash reports, send them
- always or not and return the result when calling `handleUserInput:withUserProvidedCrashDescription`.
-
- @param alertViewHandler A block that is responsible for loading, presenting and and dismissing your custom user interface which prompts the user if they want to send crash reports. The block is also responsible for triggering further processing of the crash reports.
-
- @warning This is not available when compiled for Watch OS!
-
- @warning Block needs to call the `[BITCrashManager handleUserInput:withUserProvidedMetaData:]` method!
-
- @warning This needs to be set before calling `[BITHockeyManager startManager]`!
- */
-- (void)setAlertViewHandler:(BITCustomAlertViewHandler)alertViewHandler;
-
-/**
- * Provides details about the crash that occurred in the last app session
- */
-@property (nonatomic, readonly) BITCrashDetails *lastSessionCrashDetails;
-
-
-/**
- Indicates if the app did receive a low memory warning in the last session
-
- It may happen that low memory warning where send but couldn't be logged, since iOS
- killed the app before updating the flag in the filesystem did complete.
-
- This property may be true in case of low memory kills, but it doesn't have to be! Apps
- can also be killed without the app ever receiving a low memory warning.
-
- Also the app could have received a low memory warning, but the reason for being killed was
- actually different.
-
- @warning This property only has a correct value, once `[BITHockeyManager startManager]` was
- invoked!
-
- @see enableAppNotTerminatingCleanlyDetection
- @see lastSessionCrashDetails
- */
-@property (nonatomic, readonly) BOOL didReceiveMemoryWarningInLastSession;
-
-
-/**
- Provides the time between startup and crash in seconds
-
- Use this in together with `didCrashInLastSession` to detect if the app crashed very
- early after startup. This can be used to delay app initialization until the crash
- report has been sent to the server or if you want to do any other actions like
- cleaning up some cache data etc.
-
- Note that sending a crash reports starts as early as 1.5 seconds after the application
- did finish launching!
-
- The `BITCrashManagerDelegate` protocol provides some delegates to inform if sending
- a crash report was finished successfully, ended in error or was cancelled by the user.
-
- *Default*: _-1_
- @see didCrashInLastSession
- @see BITCrashManagerDelegate
- */
-@property (nonatomic, readonly) NSTimeInterval timeIntervalCrashInLastSessionOccurred;
-
-
-///-----------------------------------------------------------------------------
-/// @name Helper
-///-----------------------------------------------------------------------------
-
-/**
- * Detect if a debugger is attached to the app process
- *
- * This is only invoked once on app startup and can not detect if the debugger is being
- * attached during runtime!
- *
- * @return BOOL if the debugger is attached on app startup
- */
-- (BOOL)isDebuggerAttached;
-
-
-/**
- * Lets the app crash for easy testing of the SDK
- *
- * The best way to use this is to trigger the crash with a button action.
- *
- * Make sure not to let the app crash in `applicationDidFinishLaunching` or any other
- * startup method! Since otherwise the app would crash before the SDK could process it.
- *
- * Note that our SDK provides support for handling crashes that happen early on startup.
- * Check the documentation for more information on how to use this.
- *
- * If the SDK detects an App Store environment, it will _NOT_ cause the app to crash!
- */
-- (void)generateTestCrash;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITCrashManager.m b/submodules/HockeySDK-iOS/Classes/BITCrashManager.m
deleted file mode 100644
index 6b60dcc00a..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITCrashManager.m
+++ /dev/null
@@ -1,1713 +0,0 @@
-/*
- * Author: Andreas Linde
- * Kent Sutherland
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * Copyright (c) 2011 Andreas Linde & Kent Sutherland.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import "HockeySDKFeatureConfig.h"
-
-#if HOCKEYSDK_FEATURE_CRASH_REPORTER
-
-#import
-#import
-
-#import "HockeySDKPrivate.h"
-#import "BITHockeyHelper.h"
-#import "BITHockeyHelper+Application.h"
-#import "BITHockeyAppClient.h"
-
-#import "BITCrashManager.h"
-#import "BITCrashManagerPrivate.h"
-#import "BITCrashAttachment.h"
-#import "BITHockeyBaseManagerPrivate.h"
-#import "BITCrashReportTextFormatter.h"
-#import "BITCrashDetailsPrivate.h"
-#import "BITCrashCXXExceptionHandler.h"
-
-#if HOCKEYSDK_FEATURE_METRICS
-#import "BITMetricsManagerPrivate.h"
-#import "BITChannel.h"
-#import "BITPersistencePrivate.h"
-#endif
-
-#include
-
-// stores the set of crashreports that have been approved but aren't sent yet
-#define kBITCrashApprovedReports @"HockeySDKCrashApprovedReports"
-
-// keys for meta information associated to each crash
-#define kBITCrashMetaUserName @"BITCrashMetaUserName"
-#define kBITCrashMetaUserEmail @"BITCrashMetaUserEmail"
-#define kBITCrashMetaUserID @"BITCrashMetaUserID"
-#define kBITCrashMetaApplicationLog @"BITCrashMetaApplicationLog"
-#define kBITCrashMetaAttachment @"BITCrashMetaAttachment"
-
-// internal keys
-static NSString *const KBITAttachmentDictIndex = @"index";
-static NSString *const KBITAttachmentDictAttachment = @"attachment";
-
-static NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus";
-
-static NSString *const kBITAppWentIntoBackgroundSafely = @"BITAppWentIntoBackgroundSafely";
-static NSString *const kBITAppDidReceiveLowMemoryNotification = @"BITAppDidReceiveLowMemoryNotification";
-static NSString *const kBITAppMarketingVersion = @"BITAppMarketingVersion";
-static NSString *const kBITAppVersion = @"BITAppVersion";
-static NSString *const kBITAppOSVersion = @"BITAppOSVersion";
-static NSString *const kBITAppOSBuild = @"BITAppOSBuild";
-static NSString *const kBITAppUUIDs = @"BITAppUUIDs";
-
-static NSString *const kBITFakeCrashUUID = @"BITFakeCrashUUID";
-static NSString *const kBITFakeCrashAppMarketingVersion = @"BITFakeCrashAppMarketingVersion";
-static NSString *const kBITFakeCrashAppVersion = @"BITFakeCrashAppVersion";
-static NSString *const kBITFakeCrashAppBundleIdentifier = @"BITFakeCrashAppBundleIdentifier";
-static NSString *const kBITFakeCrashOSVersion = @"BITFakeCrashOSVersion";
-static NSString *const kBITFakeCrashDeviceModel = @"BITFakeCrashDeviceModel";
-static NSString *const kBITFakeCrashAppBinaryUUID = @"BITFakeCrashAppBinaryUUID";
-static NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
-
-// We need BIT_UNUSED macro to make sure there aren't any warnings when building
-// HockeySDK Distribution scheme. Since several configurations are build in this scheme
-// and different features can be turned on and off we can't just use __unused attribute.
-#if HOCKEYSDK_FEATURE_METRICS
-static char const *BITSaveEventsFilePath;
-#define BIT_UNUSED
-#else
-#define BIT_UNUSED __unused
-#endif
-
-static BITCrashManagerCallbacks bitCrashCallbacks = {
- .context = NULL,
- .handleSignal = NULL
-};
-
-#if HOCKEYSDK_FEATURE_METRICS
-static void bit_save_events_callback(siginfo_t __unused *info, ucontext_t __unused *uap, void __unused *context) {
-
- // Do not flush metrics queue if queue is empty (metrics module disabled) to not freeze the app
- if (!BITTelemetryEventBuffer) {
- return;
- }
-
- // Try to get a file descriptor with our pre-filled path
- int fd = open(BITSaveEventsFilePath, O_WRONLY | O_CREAT | O_TRUNC, 0644);
- if (fd < 0) {
- return;
- }
-
- size_t len = strlen(BITTelemetryEventBuffer);
- if (len > 0) {
- // Simply write the whole string to disk
- write(fd, BITTelemetryEventBuffer, len);
- }
- close(fd);
-}
-#endif
-
-// Proxy implementation for PLCrashReporter to keep our interface stable while this can change
-static void plcr_post_crash_callback (BIT_UNUSED siginfo_t *info, BIT_UNUSED ucontext_t *uap, void *context) {
-#if HOCKEYSDK_FEATURE_METRICS
- bit_save_events_callback(info, uap, context);
-#endif
- if (bitCrashCallbacks.handleSignal != NULL) {
- bitCrashCallbacks.handleSignal(context);
- }
-}
-
-static PLCrashReporterCallbacks plCrashCallbacks = {
- .version = 0,
- .context = NULL,
- .handleSignal = plcr_post_crash_callback
-};
-
-// Temporary class until PLCR catches up
-// We trick PLCR with an Objective-C exception.
-//
-// This code provides us access to the C++ exception message, including a correct stack trace.
-//
-@interface BITCrashCXXExceptionWrapperException : NSException
-
-- (instancetype)initWithCXXExceptionInfo:(const BITCrashUncaughtCXXExceptionInfo *)info;
-
-@property (nonatomic, readonly) const BITCrashUncaughtCXXExceptionInfo *info;
-
-@end
-
-@implementation BITCrashCXXExceptionWrapperException
-
-- (instancetype)initWithCXXExceptionInfo:(const BITCrashUncaughtCXXExceptionInfo *)info {
- extern char* __cxa_demangle(const char* mangled_name, char* output_buffer, size_t* length, int* status);
- char *demangled_name = &__cxa_demangle ? __cxa_demangle(info->exception_type_name ?: "", NULL, NULL, NULL) : NULL;
-
- if ((self = [super
- initWithName:(NSString *)[NSString stringWithUTF8String:demangled_name ?: info->exception_type_name ?: ""]
- reason:[NSString stringWithUTF8String:info->exception_message ?: ""]
- userInfo:nil])) {
- _info = info;
- }
- return self;
-}
-
-- (NSArray *)callStackReturnAddresses {
- NSMutableArray *cxxFrames = [NSMutableArray arrayWithCapacity:self.info->exception_frames_count];
-
- for (uint32_t i = 0; i < self.info->exception_frames_count; ++i) {
- [cxxFrames addObject:[NSNumber numberWithUnsignedLongLong:self.info->exception_frames[i]]];
- }
- return cxxFrames;
-}
-
-@end
-
-
-// C++ Exception Handler
-__attribute__((noreturn)) static void uncaught_cxx_exception_handler(const BITCrashUncaughtCXXExceptionInfo *info) {
- // This relies on a LOT of sneaky internal knowledge of how PLCR works and should not be considered a long-term solution.
- NSGetUncaughtExceptionHandler()([[BITCrashCXXExceptionWrapperException alloc] initWithCXXExceptionInfo:info]);
- abort();
-}
-
-@interface BITCrashManager ()
-
-@property (nonatomic, strong) NSMutableDictionary *approvedCrashReports;
-@property (nonatomic, strong) NSMutableArray *crashFiles;
-@property (nonatomic, copy) NSString *settingsFile;
-@property (nonatomic, copy) NSString *analyzerInProgressFile;
-@property (nonatomic) BOOL crashIdenticalCurrentVersion;
-@property (nonatomic) BOOL sendingInProgress;
-@property (nonatomic) BOOL isSetup;
-@property (nonatomic) BOOL didLogLowMemoryWarning;
-@property (nonatomic, weak) id appDidBecomeActiveObserver;
-@property (nonatomic, weak) id appWillTerminateObserver;
-@property (nonatomic, weak) id appDidEnterBackgroundObserver;
-@property (nonatomic, weak) id appWillEnterForegroundObserver;
-@property (nonatomic, weak) id appDidReceiveLowMemoryWarningObserver;
-@property (nonatomic, weak) id networkDidBecomeReachableObserver;
-
-// Redeclare BITCrashManager properties with readwrite attribute
-@property (nonatomic, readwrite) NSTimeInterval timeIntervalCrashInLastSessionOccurred;
-@property (nonatomic, readwrite) BITCrashDetails *lastSessionCrashDetails;
-@property (nonatomic, readwrite) BOOL didCrashInLastSession;
-@property (nonatomic, readwrite) BOOL didReceiveMemoryWarningInLastSession;
-
-@end
-
-@implementation BITCrashManager
-
-- (instancetype)initWithAppIdentifier:(NSString *)appIdentifier appEnvironment:(BITEnvironment)environment hockeyAppClient:(BITHockeyAppClient *)hockeyAppClient {
- if ((self = [super initWithAppIdentifier:appIdentifier appEnvironment:environment])) {
- _delegate = nil;
- _isSetup = NO;
-
- _hockeyAppClient = hockeyAppClient;
-
- _showAlwaysButton = YES;
- _alertViewHandler = nil;
-
- _plCrashReporter = nil;
- _exceptionHandler = nil;
-
- _crashIdenticalCurrentVersion = YES;
-
- _didCrashInLastSession = NO;
- _timeIntervalCrashInLastSessionOccurred = -1;
- _didLogLowMemoryWarning = NO;
-
- _approvedCrashReports = [[NSMutableDictionary alloc] init];
-
- _fileManager = [[NSFileManager alloc] init];
- _crashFiles = [[NSMutableArray alloc] init];
-
- _crashManagerStatus = BITCrashManagerStatusAlwaysAsk;
-
- if ([[NSUserDefaults standardUserDefaults] stringForKey:kBITCrashManagerStatus]) {
- _crashManagerStatus = (BITCrashManagerStatus)[[NSUserDefaults standardUserDefaults] integerForKey:kBITCrashManagerStatus];
- } else {
- // migrate previous setting if available
- if ([[NSUserDefaults standardUserDefaults] boolForKey:@"BITCrashAutomaticallySendReports"]) {
- _crashManagerStatus = BITCrashManagerStatusAutoSend;
- [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"BITCrashAutomaticallySendReports"];
- }
- [[NSUserDefaults standardUserDefaults] setInteger:_crashManagerStatus forKey:kBITCrashManagerStatus];
- }
-
- _crashesDir = bit_settingsDir();
- _settingsFile = [_crashesDir stringByAppendingPathComponent:BITHOCKEY_CRASH_SETTINGS];
- _analyzerInProgressFile = [_crashesDir stringByAppendingPathComponent:BITHOCKEY_CRASH_ANALYZER];
-
-
- if (!BITHockeyBundle() && !bit_isRunningInAppExtension()) {
- BITHockeyLogWarning(@"[HockeySDK] WARNING: %@ is missing, will send reports automatically!", BITHOCKEYSDK_BUNDLE);
- }
- }
- return self;
-}
-
-
-- (void) dealloc {
- [self unregisterObservers];
-}
-
-
-- (void)setCrashManagerStatus:(BITCrashManagerStatus)crashManagerStatus {
- _crashManagerStatus = crashManagerStatus;
-
- [[NSUserDefaults standardUserDefaults] setInteger:crashManagerStatus forKey:kBITCrashManagerStatus];
-}
-
-- (void)setServerURL:(NSString *)serverURL {
- if ([serverURL isEqualToString:super.serverURL]) { return; }
-
- super.serverURL = serverURL;
- self.hockeyAppClient = [[BITHockeyAppClient alloc] initWithBaseURL:[NSURL URLWithString:serverURL]];
-}
-
-#pragma mark - Private
-
-/**
- * Save all settings
- *
- * This saves the list of approved crash reports
- */
-- (void)saveSettings {
- NSError *error = nil;
-
- NSMutableDictionary *rootObj = [NSMutableDictionary dictionaryWithCapacity:2];
- if (self.approvedCrashReports && [self.approvedCrashReports count] > 0) {
- [rootObj setObject:self.approvedCrashReports forKey:kBITCrashApprovedReports];
- }
-
- NSData *plist = [NSPropertyListSerialization dataWithPropertyList:(id)rootObj format:NSPropertyListBinaryFormat_v1_0 options:0 error:&error];
-
- if (plist) {
- [plist writeToFile:self.settingsFile atomically:YES];
- } else {
- BITHockeyLogError(@"ERROR: Writing settings. %@", [error description]);
- }
-}
-
-/**
- * Load all settings
- *
- * This contains the list of approved crash reports
- */
-- (void)loadSettings {
- NSError *error = nil;
- NSPropertyListFormat format;
-
- if (![self.fileManager fileExistsAtPath:self.settingsFile])
- return;
-
- NSData *plist = [NSData dataWithContentsOfFile:self.settingsFile];
- if (plist) {
- NSDictionary *rootObj = (NSDictionary *)[NSPropertyListSerialization
- propertyListWithData:plist
- options:NSPropertyListMutableContainersAndLeaves
- format:&format
- error:&error];
-
- if ([rootObj objectForKey:kBITCrashApprovedReports])
- [self.approvedCrashReports setDictionary:(NSDictionary *)[rootObj objectForKey:kBITCrashApprovedReports]];
- } else {
- BITHockeyLogError(@"ERROR: Reading crash manager settings.");
- }
-}
-
-
-/**
- * Remove a cached crash report
- *
- * @param filename The base filename of the crash report
- */
-- (void)cleanCrashReportWithFilename:(NSString *)filename {
- if (!filename) return;
-
- NSError *error = NULL;
-
- [self.fileManager removeItemAtPath:filename error:&error];
- [self.fileManager removeItemAtPath:[filename stringByAppendingString:@".data"] error:&error];
- [self.fileManager removeItemAtPath:[filename stringByAppendingString:@".meta"] error:&error];
- [self.fileManager removeItemAtPath:[filename stringByAppendingString:@".desc"] error:&error];
-
- NSString *cacheFilename = [filename lastPathComponent];
- [self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserName]];
- [self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserEmail]];
- [self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserID]];
-
- [self.crashFiles removeObject:filename];
- [self.approvedCrashReports removeObjectForKey:filename];
-
- [self saveSettings];
-}
-
-/**
- * Remove all crash reports and stored meta data for each from the file system and keychain
- *
- * This is currently only used as a helper method for tests
- */
-- (void)cleanCrashReports {
- for (NSUInteger i=0; i < [self.crashFiles count]; i++) {
- [self cleanCrashReportWithFilename:[self.crashFiles objectAtIndex:i]];
- }
-}
-
-- (BOOL)persistAttachment:(BITHockeyAttachment *)attachment withFilename:(NSString *)filename {
- NSString *attachmentFilename = [filename stringByAppendingString:@".data"];
- NSMutableData *data = [[NSMutableData alloc] init];
- NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
-
- [archiver encodeObject:attachment forKey:kBITCrashMetaAttachment];
-
- [archiver finishEncoding];
-
- return [data writeToFile:attachmentFilename atomically:YES];
-}
-
-- (void)persistUserProvidedMetaData:(BITCrashMetaData *)userProvidedMetaData {
- if (!userProvidedMetaData) return;
-
- if (userProvidedMetaData.userProvidedDescription && [userProvidedMetaData.userProvidedDescription length] > 0) {
- NSError *error;
- [userProvidedMetaData.userProvidedDescription writeToFile:[NSString stringWithFormat:@"%@.desc", [self.crashesDir stringByAppendingPathComponent: self.lastCrashFilename]] atomically:YES encoding:NSUTF8StringEncoding error:&error];
- }
-
- if (userProvidedMetaData.userName && [userProvidedMetaData.userName length] > 0) {
- [self addStringValueToKeychain:userProvidedMetaData.userName forKey:[NSString stringWithFormat:@"%@.%@", self.lastCrashFilename, kBITCrashMetaUserName]];
-
- }
-
- if (userProvidedMetaData.userEmail && [userProvidedMetaData.userEmail length] > 0) {
- [self addStringValueToKeychain:userProvidedMetaData.userEmail forKey:[NSString stringWithFormat:@"%@.%@", self.lastCrashFilename, kBITCrashMetaUserEmail]];
- }
-
- if (userProvidedMetaData.userID && [userProvidedMetaData.userID length] > 0) {
- [self addStringValueToKeychain:userProvidedMetaData.userID forKey:[NSString stringWithFormat:@"%@.%@", self.lastCrashFilename, kBITCrashMetaUserID]];
-
- }
-}
-
-/**
- * Read the attachment data from the stored file
- *
- * @param filename The crash report file path
- *
- * @return an BITHockeyAttachment instance or nil
- */
-- (BITHockeyAttachment *)attachmentForCrashReport:(NSString *)filename {
- NSString *attachmentFilename = [filename stringByAppendingString:@".data"];
-
- if (![self.fileManager fileExistsAtPath:attachmentFilename])
- return nil;
-
-
- NSData *codedData = [[NSData alloc] initWithContentsOfFile:attachmentFilename];
- if (!codedData)
- return nil;
-
- NSKeyedUnarchiver *unarchiver = nil;
-
- @try {
- unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:codedData];
- }
- @catch (NSException __unused *exception) {
- return nil;
- }
-
- if ([unarchiver containsValueForKey:kBITCrashMetaAttachment]) {
- BITHockeyAttachment *attachment = [unarchiver decodeObjectForKey:kBITCrashMetaAttachment];
- return attachment;
- }
-
- return nil;
-}
-
-/**
- * Extract all app specific UUIDs from the crash reports
- *
- * This allows us to send the UUIDs in the XML construct to the server, so the server does not need to parse the crash report for this data.
- * The app specific UUIDs help to identify which dSYMs are needed to symbolicate this crash report.
- *
- * @param report The crash report from PLCrashReporter
- *
- * @return XML structure with the app specific UUIDs
- */
-- (NSString *) extractAppUUIDs:(BITPLCrashReport *)report {
- NSMutableString *uuidString = [NSMutableString string];
- NSArray *uuidArray = [BITCrashReportTextFormatter arrayOfAppUUIDsForCrashReport:report];
-
- for (NSDictionary *element in uuidArray) {
- if ([element objectForKey:kBITBinaryImageKeyType] && [element objectForKey:kBITBinaryImageKeyArch] && [element objectForKey:kBITBinaryImageKeyUUID]) {
- [uuidString appendFormat:@"%@",
- [element objectForKey:kBITBinaryImageKeyType],
- [element objectForKey:kBITBinaryImageKeyArch],
- [element objectForKey:kBITBinaryImageKeyUUID]
- ];
- }
- }
-
- return uuidString;
-}
-
-- (void) registerObservers {
- __weak typeof(self) weakSelf = self;
-
- if(nil == self.appDidBecomeActiveObserver) {
- NSNotificationName name = UIApplicationDidBecomeActiveNotification;
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wpartial-availability"
- if (bit_isRunningInAppExtension() && &NSExtensionHostDidBecomeActiveNotification != NULL) {
- name = NSExtensionHostDidBecomeActiveNotification;
- }
-#pragma clang diagnostic pop
- self.appDidBecomeActiveObserver = [[NSNotificationCenter defaultCenter] addObserverForName:name
- object:nil
- queue:NSOperationQueue.mainQueue
- usingBlock:^(NSNotification __unused *note) {
- typeof(self) strongSelf = weakSelf;
- [strongSelf triggerDelayedProcessing];
- }];
- }
-
- if(nil == self.networkDidBecomeReachableObserver) {
- self.networkDidBecomeReachableObserver = [[NSNotificationCenter defaultCenter] addObserverForName:BITHockeyNetworkDidBecomeReachableNotification
- object:nil
- queue:NSOperationQueue.mainQueue
- usingBlock:^(NSNotification __unused *note) {
- typeof(self) strongSelf = weakSelf;
- [strongSelf triggerDelayedProcessing];
- }];
- }
-
- if (nil == self.appWillTerminateObserver) {
- self.appWillTerminateObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillTerminateNotification
- object:nil
- queue:NSOperationQueue.mainQueue
- usingBlock:^(NSNotification __unused *note) {
- typeof(self) strongSelf = weakSelf;
- [strongSelf leavingAppSafely];
- }];
- }
-
- if (nil == self.appDidEnterBackgroundObserver) {
- NSNotificationName name = UIApplicationDidEnterBackgroundNotification;
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wpartial-availability"
- if (bit_isRunningInAppExtension() && &NSExtensionHostDidEnterBackgroundNotification != NULL) {
- name = NSExtensionHostDidEnterBackgroundNotification;
- }
-#pragma clang diagnostic pop
- self.appDidEnterBackgroundObserver = [[NSNotificationCenter defaultCenter] addObserverForName:name
- object:nil
- queue:NSOperationQueue.mainQueue
- usingBlock:^(NSNotification __unused *note) {
- typeof(self) strongSelf = weakSelf;
- [strongSelf leavingAppSafely];
- }];
- }
-
- if (nil == self.appWillEnterForegroundObserver) {
- NSNotificationName name = UIApplicationWillEnterForegroundNotification;
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wpartial-availability"
- if (bit_isRunningInAppExtension() && &NSExtensionHostWillEnterForegroundNotification != NULL) {
- name = NSExtensionHostWillEnterForegroundNotification;
- }
-#pragma clang diagnostic pop
- self.appWillEnterForegroundObserver = [[NSNotificationCenter defaultCenter] addObserverForName:name
- object:nil
- queue:NSOperationQueue.mainQueue
- usingBlock:^(NSNotification __unused *note) {
- typeof(self) strongSelf = weakSelf;
- [strongSelf appEnteredForeground];
- }];
- }
-
- if (nil == self.appDidReceiveLowMemoryWarningObserver) {
- if (bit_isRunningInAppExtension()) {
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_MEMORYPRESSURE, 0, DISPATCH_MEMORYPRESSURE_WARN|DISPATCH_MEMORYPRESSURE_CRITICAL, dispatch_get_main_queue());
- dispatch_source_set_event_handler(source, ^{
- if (!self.didLogLowMemoryWarning) {
- [[NSUserDefaults standardUserDefaults] setBool:YES forKey:kBITAppDidReceiveLowMemoryNotification];
- self.didLogLowMemoryWarning = YES;
- }
- });
- dispatch_resume(source);
- });
- } else {
- self.appDidReceiveLowMemoryWarningObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidReceiveMemoryWarningNotification
- object:nil
- queue:NSOperationQueue.mainQueue
- usingBlock:^(NSNotification __unused *note) {
- // we only need to log this once
- if (!self.didLogLowMemoryWarning) {
- [[NSUserDefaults standardUserDefaults] setBool:YES forKey:kBITAppDidReceiveLowMemoryNotification];
- self.didLogLowMemoryWarning = YES;
-
- }
- }];
- }
- }
-}
-
-- (void) unregisterObservers {
- [self unregisterObserver:self.appDidBecomeActiveObserver];
- [self unregisterObserver:self.appWillTerminateObserver];
- [self unregisterObserver:self.appDidEnterBackgroundObserver];
- [self unregisterObserver:self.appWillEnterForegroundObserver];
- [self unregisterObserver:self.appDidReceiveLowMemoryWarningObserver];
-
- [self unregisterObserver:self.networkDidBecomeReachableObserver];
-}
-
-- (void) unregisterObserver:(id)observer {
- if (observer) {
- [[NSNotificationCenter defaultCenter] removeObserver:observer];
- observer = nil;
- }
-}
-
-- (void)leavingAppSafely {
- if (self.isAppNotTerminatingCleanlyDetectionEnabled) {
- [[NSUserDefaults standardUserDefaults] setBool:YES forKey:kBITAppWentIntoBackgroundSafely];
- }
-}
-
-- (void)appEnteredForeground {
- // we disable kill detection while the debugger is running, since we'd get only false positives if the app is terminated by the user using the debugger
- if (self.isDebuggerAttached) {
- [[NSUserDefaults standardUserDefaults] setBool:YES forKey:kBITAppWentIntoBackgroundSafely];
- } else if (self.isAppNotTerminatingCleanlyDetectionEnabled) {
- [[NSUserDefaults standardUserDefaults] setBool:NO forKey:kBITAppWentIntoBackgroundSafely];
-
- static dispatch_once_t predAppData;
-
- dispatch_once(&predAppData, ^{
- id marketingVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
- if (marketingVersion && [marketingVersion isKindOfClass:[NSString class]])
- [[NSUserDefaults standardUserDefaults] setObject:marketingVersion forKey:kBITAppMarketingVersion];
-
- id bundleVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
- if (bundleVersion && [bundleVersion isKindOfClass:[NSString class]])
- [[NSUserDefaults standardUserDefaults] setObject:bundleVersion forKey:kBITAppVersion];
-
- [[NSUserDefaults standardUserDefaults] setObject:[[UIDevice currentDevice] systemVersion] forKey:kBITAppOSVersion];
- [[NSUserDefaults standardUserDefaults] setObject:[self osBuild] forKey:kBITAppOSBuild];
-
- NSString *uuidString =[NSString stringWithFormat:@"%@",
- [self deviceArchitecture],
- [self executableUUID]
- ];
-
- [[NSUserDefaults standardUserDefaults] setObject:uuidString forKey:kBITAppUUIDs];
- });
- }
-}
-
-- (NSString *)deviceArchitecture {
- NSString *archName = @"???";
-
- size_t size;
- cpu_type_t type;
- cpu_subtype_t subtype;
- size = sizeof(type);
- if (sysctlbyname("hw.cputype", &type, &size, NULL, 0))
- return archName;
-
- size = sizeof(subtype);
- if (sysctlbyname("hw.cpusubtype", &subtype, &size, NULL, 0))
- return archName;
-
- archName = [BITCrashReportTextFormatter bit_archNameFromCPUType:type subType:subtype] ?: @"???";
-
- return archName;
-}
-
-- (NSString *)osBuild {
- size_t size;
- sysctlbyname("kern.osversion", NULL, &size, NULL, 0);
- char *answer = (char*)malloc(size);
- if (answer == NULL)
- return nil;
- sysctlbyname("kern.osversion", answer, &size, NULL, 0);
- NSString *osBuild = [NSString stringWithCString:answer encoding: NSUTF8StringEncoding];
- free(answer);
- return osBuild;
-}
-
-/**
- * Get the userID from the delegate which should be stored with the crash report
- *
- * @return The userID value
- */
-- (NSString *)userIDForCrashReport {
- NSString *userID;
-#if HOCKEYSDK_FEATURE_AUTHENTICATOR
- // if we have an identification from BITAuthenticator, use this as a default.
- if ((
- self.installationIdentificationType == BITAuthenticatorIdentificationTypeAnonymous ||
- self.installationIdentificationType == BITAuthenticatorIdentificationTypeDevice
- ) &&
- self.installationIdentification) {
- userID = self.installationIdentification;
- }
-#endif
-
- // first check the global keychain storage
- NSString *userIdFromKeychain = [self stringValueFromKeychainForKey:kBITHockeyMetaUserID];
- if (userIdFromKeychain) {
- userID = userIdFromKeychain;
- }
- id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate;
- if ([strongDelegate respondsToSelector:@selector(userIDForHockeyManager:componentManager:)]) {
- userID = [strongDelegate userIDForHockeyManager:[BITHockeyManager sharedHockeyManager] componentManager:self];
- }
- return userID ?: @"";
-}
-
-/**
- * Get the userName from the delegate which should be stored with the crash report
- *
- * @return The userName value
- */
-- (NSString *)userNameForCrashReport {
- // first check the global keychain storage
- NSString *username = [self stringValueFromKeychainForKey:kBITHockeyMetaUserName] ?: @"";
- id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate;
- if ([strongDelegate respondsToSelector:@selector(userNameForHockeyManager:componentManager:)]) {
- username = [strongDelegate userNameForHockeyManager:[BITHockeyManager sharedHockeyManager] componentManager:self] ?: @"";
- }
- return username;
-}
-
-/**
- * Get the userEmail from the delegate which should be stored with the crash report
- *
- * @return The userEmail value
- */
-- (NSString *)userEmailForCrashReport {
- // first check the global keychain storage
- NSString *useremail = [self stringValueFromKeychainForKey:kBITHockeyMetaUserEmail] ?: @"";
-
-#if HOCKEYSDK_FEATURE_AUTHENTICATOR
- // if we have an identification from BITAuthenticator, use this as a default.
- if ((
- self.installationIdentificationType == BITAuthenticatorIdentificationTypeHockeyAppEmail ||
- self.installationIdentificationType == BITAuthenticatorIdentificationTypeHockeyAppUser ||
- self.installationIdentificationType == BITAuthenticatorIdentificationTypeWebAuth
- ) &&
- self.installationIdentification) {
- useremail = self.installationIdentification;
- }
-#endif
- id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate;
- if ([strongDelegate respondsToSelector:@selector(userEmailForHockeyManager:componentManager:)]) {
- useremail = [strongDelegate userEmailForHockeyManager:[BITHockeyManager sharedHockeyManager] componentManager:self] ?: @"";
- }
- return useremail;
-}
-
-#pragma mark - CrashCallbacks
-
-/**
- * Set the callback for PLCrashReporter
- *
- * @param callbacks BITCrashManagerCallbacks instance
- */
-- (void)setCrashCallbacks:(BITCrashManagerCallbacks *)callbacks {
- if (!callbacks) return;
- if (self.isSetup) {
- BITHockeyLogWarning(@"WARNING: CrashCallbacks need to be configured before calling startManager!");
- }
-
- // set our proxy callback struct
- bitCrashCallbacks.context = callbacks->context;
- bitCrashCallbacks.handleSignal = callbacks->handleSignal;
-
- // set the PLCrashReporterCallbacks struct
- plCrashCallbacks.context = callbacks->context;
-}
-
-#if HOCKEYSDK_FEATURE_METRICS
-- (void)configDefaultCrashCallback {
- BITMetricsManager *metricsManager = [BITHockeyManager sharedHockeyManager].metricsManager;
- BITPersistence *persistence = metricsManager.persistence;
- BITSaveEventsFilePath = strdup([persistence fileURLForType:BITPersistenceTypeTelemetry].UTF8String);
-}
-#endif
-
-#pragma mark - Public
-
-- (void)setAlertViewHandler:(BITCustomAlertViewHandler)alertViewHandler{
- _alertViewHandler = alertViewHandler;
-}
-
-
-- (BOOL)isDebuggerAttached {
- return bit_isDebuggerAttached();
-}
-
-
-- (void)generateTestCrash {
- if (self.appEnvironment != BITEnvironmentAppStore) {
-
- if ([self isDebuggerAttached]) {
- BITHockeyLogWarning(@"[HockeySDK] WARNING: The debugger is attached. The following crash cannot be detected by the SDK!");
- }
-
- __builtin_trap();
- }
-}
-
-/**
- * Write a meta file for a new crash report
- *
- * @param filename the crash reports temp filename
- */
-- (void)storeMetaDataForCrashReportFilename:(NSString *)filename {
- BITHockeyLogVerbose(@"VERBOSE: Storing meta data for crash report with filename %@", filename);
- NSError *error = NULL;
- NSMutableDictionary *metaDict = [NSMutableDictionary dictionaryWithCapacity:4];
- NSString *applicationLog = @"";
-
- [self addStringValueToKeychain:[self userNameForCrashReport] forKey:[NSString stringWithFormat:@"%@.%@", filename, kBITCrashMetaUserName]];
- [self addStringValueToKeychain:[self userEmailForCrashReport] forKey:[NSString stringWithFormat:@"%@.%@", filename, kBITCrashMetaUserEmail]];
- [self addStringValueToKeychain:[self userIDForCrashReport] forKey:[NSString stringWithFormat:@"%@.%@", filename, kBITCrashMetaUserID]];
- id strongDelegate = self.delegate;
- if ([strongDelegate respondsToSelector:@selector(applicationLogForCrashManager:)]) {
- applicationLog = [strongDelegate applicationLogForCrashManager:self] ?: @"";
- }
- [metaDict setObject:applicationLog forKey:kBITCrashMetaApplicationLog];
-
- if ([strongDelegate respondsToSelector:@selector(attachmentForCrashManager:)]) {
- BITHockeyLogVerbose(@"VERBOSE: Processing attachment for crash report with filename %@", filename);
- BITHockeyAttachment *attachment = [strongDelegate attachmentForCrashManager:self];
-
- if (attachment && attachment.hockeyAttachmentData) {
- BOOL success = [self persistAttachment:attachment withFilename:[self.crashesDir stringByAppendingPathComponent: filename]];
- if (!success) {
- BITHockeyLogError(@"ERROR: Persisting the crash attachment failed");
- } else {
- BITHockeyLogVerbose(@"VERBOSE: Crash attachment successfully persisted.");
- }
- } else {
- BITHockeyLogDebug(@"INFO: Crash attachment was nil");
- }
- }
-
- NSData *plist = [NSPropertyListSerialization dataWithPropertyList:(id)metaDict
- format:NSPropertyListBinaryFormat_v1_0
- options:0
- error:&error];
- if (plist) {
- BOOL success = [plist writeToFile:[self.crashesDir stringByAppendingPathComponent:(NSString *)[filename stringByAppendingPathExtension:@"meta"]] atomically:YES];
- if (!success) {
- BITHockeyLogError(@"ERROR: Writing crash meta data failed.");
- }
- } else {
- BITHockeyLogError(@"ERROR: Writing crash meta data failed. %@", error);
- }
- BITHockeyLogVerbose(@"VERBOSE: Storing crash meta data finished.");
-}
-
-- (BOOL)handleUserInput:(BITCrashManagerUserInput)userInput withUserProvidedMetaData:(BITCrashMetaData *)userProvidedMetaData {
- id strongDelegate = self.delegate;
- switch (userInput) {
- case BITCrashManagerUserInputDontSend:
- if ([strongDelegate respondsToSelector:@selector(crashManagerWillCancelSendingCrashReport:)]) {
- [strongDelegate crashManagerWillCancelSendingCrashReport:self];
- }
-
- if (self.lastCrashFilename)
- [self cleanCrashReportWithFilename:[self.crashesDir stringByAppendingPathComponent: self.lastCrashFilename]];
-
- return YES;
-
- case BITCrashManagerUserInputSend:
- if (userProvidedMetaData)
- [self persistUserProvidedMetaData:userProvidedMetaData];
-
- [self approveLatestCrashReport];
- [self sendNextCrashReport];
- return YES;
-
- case BITCrashManagerUserInputAlwaysSend:
- self.crashManagerStatus = BITCrashManagerStatusAutoSend;
- [[NSUserDefaults standardUserDefaults] setInteger:self.crashManagerStatus forKey:kBITCrashManagerStatus];
-
- if ([strongDelegate respondsToSelector:@selector(crashManagerWillSendCrashReportsAlways:)]) {
- [strongDelegate crashManagerWillSendCrashReportsAlways:self];
- }
-
- if (userProvidedMetaData)
- [self persistUserProvidedMetaData:userProvidedMetaData];
-
- [self approveLatestCrashReport];
- [self sendNextCrashReport];
- return YES;
-
- default:
- return NO;
- }
-
-}
-
-#pragma mark - PLCrashReporter
-
-/**
- * Process new crash reports provided by PLCrashReporter
- *
- * Parse the new crash report and gather additional meta data from the app which will be stored along the crash report
- */
-- (void) handleCrashReport {
- BITHockeyLogVerbose(@"VERBOSE: Handling crash report");
- NSError *error = NULL;
-
- if (!self.plCrashReporter) return;
-
- // check if the next call ran successfully the last time
- if (![self.fileManager fileExistsAtPath:self.analyzerInProgressFile]) {
- // mark the start of the routine
- [self.fileManager createFileAtPath:self.analyzerInProgressFile contents:nil attributes:nil];
- BITHockeyLogVerbose(@"VERBOSE: AnalyzerInProgress file created");
-
- [self saveSettings];
-
- // Try loading the crash report
- NSData *crashData = [[NSData alloc] initWithData:[self.plCrashReporter loadPendingCrashReportDataAndReturnError: &error]];
-
- NSString *cacheFilename = [NSString stringWithFormat: @"%.0f", [NSDate timeIntervalSinceReferenceDate]];
- self.lastCrashFilename = cacheFilename;
-
- if (crashData == nil) {
- BITHockeyLogError(@"ERROR: Could not load crash report: %@", error);
- } else {
- // get the startup timestamp from the crash report, and the file timestamp to calculate the timeinterval when the crash happened after startup
- BITPLCrashReport *report = [[BITPLCrashReport alloc] initWithData:crashData error:&error];
-
- if (report == nil) {
- BITHockeyLogWarning(@"WARNING: Could not parse crash report");
- } else {
- NSDate *appStartTime = nil;
- NSDate *appCrashTime = nil;
- if ([report.processInfo respondsToSelector:@selector(processStartTime)]) {
- if (report.systemInfo.timestamp && report.processInfo.processStartTime) {
- appStartTime = report.processInfo.processStartTime;
- appCrashTime =report.systemInfo.timestamp;
- self.timeIntervalCrashInLastSessionOccurred = [report.systemInfo.timestamp timeIntervalSinceDate:report.processInfo.processStartTime];
- }
- }
-
- [crashData writeToFile:[self.crashesDir stringByAppendingPathComponent: cacheFilename] atomically:YES];
-
- NSString *incidentIdentifier = @"???";
- if (report.uuidRef != NULL) {
- incidentIdentifier = (NSString *) CFBridgingRelease(CFUUIDCreateString(NULL, report.uuidRef));
- }
-
- NSString *reporterKey = bit_appAnonID(NO) ?: @"";
-
- self.lastSessionCrashDetails = [[BITCrashDetails alloc] initWithIncidentIdentifier:incidentIdentifier
- reporterKey:reporterKey
- signal:report.signalInfo.name
- exceptionName:report.exceptionInfo.exceptionName
- exceptionReason:report.exceptionInfo.exceptionReason
- appStartTime:appStartTime
- crashTime:appCrashTime
- osVersion:report.systemInfo.operatingSystemVersion
- osBuild:report.systemInfo.operatingSystemBuild
- appVersion:report.applicationInfo.applicationMarketingVersion
- appBuild:report.applicationInfo.applicationVersion
- appProcessIdentifier:report.processInfo.processID
- ];
-
- // fetch and store the meta data after setting _lastSessionCrashDetails, so the property can be used in the protocol methods
- [self storeMetaDataForCrashReportFilename:cacheFilename];
- }
- }
- } else {
- BITHockeyLogWarning(@"WARNING: AnalyzerInProgress file found, handling crash report skipped");
- }
-
- // Purge the report
- // mark the end of the routine
- if ([self.fileManager fileExistsAtPath:self.analyzerInProgressFile]) {
- [self.fileManager removeItemAtPath:self.analyzerInProgressFile error:&error];
- }
-
- [self saveSettings];
-
- [self.plCrashReporter purgePendingCrashReport];
-}
-
-/**
- Get the filename of the first not approved crash report
-
- @return NSString Filename of the first found not approved crash report
- */
-- (NSString *)firstNotApprovedCrashReport {
- if ((!self.approvedCrashReports || [self.approvedCrashReports count] == 0) && [self.crashFiles count] > 0) {
- return [self.crashFiles objectAtIndex:0];
- }
-
- for (NSUInteger i=0; i < [self.crashFiles count]; i++) {
- NSString *filename = [self.crashFiles objectAtIndex:i];
-
- if (![self.approvedCrashReports objectForKey:filename]) return filename;
- }
-
- return nil;
-}
-
-/**
- * Check if there are any new crash reports that are not yet processed
- *
- * @return `YES` if there is at least one new crash report found, `NO` otherwise
- */
-- (BOOL)hasPendingCrashReport {
- if (self.crashManagerStatus == BITCrashManagerStatusDisabled) return NO;
-
- if ([self.fileManager fileExistsAtPath:self.crashesDir]) {
- NSError *error = NULL;
-
- NSArray *dirArray = [self.fileManager contentsOfDirectoryAtPath:self.crashesDir error:&error];
-
- for (NSString *file in dirArray) {
- NSString *filePath = [self.crashesDir stringByAppendingPathComponent:file];
-
- NSDictionary *fileAttributes = [self.fileManager attributesOfItemAtPath:filePath error:&error];
- if ([[fileAttributes objectForKey:NSFileType] isEqualToString:NSFileTypeRegular] &&
- [[fileAttributes objectForKey:NSFileSize] intValue] > 0 &&
- ![file hasSuffix:@".DS_Store"] &&
- ![file hasSuffix:@".analyzer"] &&
- ![file hasSuffix:@".plist"] &&
- ![file hasSuffix:@".data"] &&
- ![file hasSuffix:@".meta"] &&
- ![file hasSuffix:@".desc"]) {
- [self.crashFiles addObject:filePath];
- }
- }
- }
-
- if ([self.crashFiles count] > 0) {
- BITHockeyLogDebug(@"INFO: %lu pending crash reports found.", (unsigned long)[self.crashFiles count]);
- return YES;
- } else {
- if (self.didCrashInLastSession) {
- id strongDelegate = self.delegate;
- if ([strongDelegate respondsToSelector:@selector(crashManagerWillCancelSendingCrashReport:)]) {
- [strongDelegate crashManagerWillCancelSendingCrashReport:self];
- }
-
- self.didCrashInLastSession = NO;
- }
-
- return NO;
- }
-}
-
-
-#pragma mark - Crash Report Processing
-
-// store the latest crash report as user approved, so if it fails it will retry automatically
-- (void)approveLatestCrashReport {
- [self.approvedCrashReports setObject:[NSNumber numberWithBool:YES] forKey:[self.crashesDir stringByAppendingPathComponent: self.lastCrashFilename]];
- [self saveSettings];
-}
-
-- (void)triggerDelayedProcessing {
- BITHockeyLogVerbose(@"VERBOSE: Triggering delayed crash processing.");
- [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(invokeDelayedProcessing) object:nil];
- [self performSelector:@selector(invokeDelayedProcessing) withObject:nil afterDelay:0.5];
-}
-
-/**
- * Delayed startup processing for everything that does not to be done in the app startup runloop
- *
- * - Checks if there is another exception handler installed that may block ours
- * - Present UI if the user has to approve new crash reports
- * - Send pending approved crash reports
- */
-- (void)invokeDelayedProcessing {
-#if !defined (HOCKEYSDK_CONFIGURATION_ReleaseCrashOnlyExtensions)
- if (!bit_isRunningInAppExtension() && [BITHockeyHelper applicationState] != BITApplicationStateActive) {
- return;
- }
-#endif
-
- BITHockeyLogDebug(@"INFO: Start delayed CrashManager processing");
-
- // was our own exception handler successfully added?
- if (self.exceptionHandler) {
- // get the current top level error handler
- NSUncaughtExceptionHandler *currentHandler = NSGetUncaughtExceptionHandler();
-
- // If the top level error handler differs from our own, then at least another one was added.
- // This could cause exception crashes not to be reported to HockeyApp. See log message for details.
- if (self.exceptionHandler != currentHandler) {
- BITHockeyLogWarning(@"[HockeySDK] WARNING: Another exception handler was added. If this invokes any kind of exit() after processing the exception, which causes any subsequent error handler not to be invoked, these crashes will NOT be reported to HockeyApp!");
- }
- }
-
- if (!self.sendingInProgress && [self hasPendingCrashReport]) {
- self.sendingInProgress = YES;
-
- NSString *notApprovedReportFilename = [self firstNotApprovedCrashReport];
-
- // this can happen in case there is a non approved crash report but it didn't happen in the previous app session
- if (notApprovedReportFilename && !self.lastCrashFilename) {
- self.lastCrashFilename = [notApprovedReportFilename lastPathComponent];
- }
-
- if (!BITHockeyBundle() || bit_isRunningInAppExtension()) {
- [self approveLatestCrashReport];
- [self sendNextCrashReport];
-
-#if !defined (HOCKEYSDK_CONFIGURATION_ReleaseCrashOnlyExtensions)
-
- } else if (self.crashManagerStatus != BITCrashManagerStatusAutoSend && notApprovedReportFilename) {
- id strongDelegate = self.delegate;
- if ([strongDelegate respondsToSelector:@selector(crashManagerWillShowSubmitCrashReportAlert:)]) {
- [strongDelegate crashManagerWillShowSubmitCrashReportAlert:self];
- }
-
- NSString *appName = bit_appName(BITHockeyLocalizedString(@"HockeyAppNamePlaceholder"));
- NSString *alertDescription = [NSString stringWithFormat:BITHockeyLocalizedString(@"CrashDataFoundAnonymousDescription"), appName];
-
- // the crash report is not anonymous any more if username or useremail are not nil
- NSString *userid = [self userIDForCrashReport];
- NSString *username = [self userNameForCrashReport];
- NSString *useremail = [self userEmailForCrashReport];
-
- if ((userid && [userid length] > 0) ||
- (username && [username length] > 0) ||
- (useremail && [useremail length] > 0)) {
- alertDescription = [NSString stringWithFormat:BITHockeyLocalizedString(@"CrashDataFoundDescription"), appName];
- }
-
- if (self.alertViewHandler) {
- self.alertViewHandler();
- } else {
- __weak typeof(self) weakSelf = self;
- UIAlertController *alertController = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:BITHockeyLocalizedString(@"CrashDataFoundTitle"), appName]
- message:alertDescription
- preferredStyle:UIAlertControllerStyleAlert];
- UIAlertAction *cancelAction = [BITAlertAction actionWithTitle:BITHockeyLocalizedString(@"CrashDontSendReport")
- style:UIAlertActionStyleCancel
- handler:^(UIAlertAction __unused *action) {
- typeof(self) strongSelf = weakSelf;
- [strongSelf handleUserInput:BITCrashManagerUserInputDontSend withUserProvidedMetaData:nil];
- }];
- [alertController addAction:cancelAction];
- UIAlertAction *sendAction = [BITAlertAction actionWithTitle:BITHockeyLocalizedString(@"CrashSendReport")
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction __unused *action) {
- typeof(self) strongSelf = weakSelf;
- [strongSelf handleUserInput:BITCrashManagerUserInputSend withUserProvidedMetaData:nil];
- }];
- [alertController addAction:sendAction];
- if (self.shouldShowAlwaysButton) {
- UIAlertAction *alwaysSendAction = [BITAlertAction actionWithTitle:BITHockeyLocalizedString(@"CrashSendReportAlways")
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction __unused *action) {
- typeof(self) strongSelf = weakSelf;
- [strongSelf handleUserInput:BITCrashManagerUserInputAlwaysSend withUserProvidedMetaData:nil];
- }];
-
- [alertController addAction:alwaysSendAction];
- }
-
- [self showAlertController:alertController];
- }
-#endif /* !defined (HOCKEYSDK_CONFIGURATION_ReleaseCrashOnlyExtensions) */
-
- } else {
- [self approveLatestCrashReport];
- [self sendNextCrashReport];
- }
- }
-}
-
-/**
- * Main startup sequence initializing PLCrashReporter if it wasn't disabled
- */
-- (void)startManager {
- if (self.crashManagerStatus == BITCrashManagerStatusDisabled) return;
-
- [self registerObservers];
-
- [self loadSettings];
-
- if (!self.isSetup) {
- static dispatch_once_t plcrPredicate;
- dispatch_once(&plcrPredicate, ^{
- /* Configure our reporter */
-
- PLCrashReporterSignalHandlerType signalHandlerType = PLCrashReporterSignalHandlerTypeBSD;
- if (self.isMachExceptionHandlerEnabled) {
- signalHandlerType = PLCrashReporterSignalHandlerTypeMach;
- }
-
- PLCrashReporterSymbolicationStrategy symbolicationStrategy = PLCrashReporterSymbolicationStrategyNone;
- if (self.isOnDeviceSymbolicationEnabled) {
- symbolicationStrategy = PLCrashReporterSymbolicationStrategyAll;
- }
-
- BITPLCrashReporterConfig *config = [[BITPLCrashReporterConfig alloc] initWithSignalHandlerType: signalHandlerType
- symbolicationStrategy: symbolicationStrategy];
- self.plCrashReporter = [[BITPLCrashReporter alloc] initWithConfiguration: config];
-
- // Check if we previously crashed
- if ([self.plCrashReporter hasPendingCrashReport]) {
- self.didCrashInLastSession = YES;
- [self handleCrashReport];
- }
-
- // The actual signal and mach handlers are only registered when invoking `enableCrashReporterAndReturnError`
- // So it is safe enough to only disable the following part when a debugger is attached no matter which
- // signal handler type is set
- // We only check for this if we are not in the App Store environment
-
- BOOL debuggerIsAttached = NO;
- if (self.appEnvironment != BITEnvironmentAppStore) {
- if ([self isDebuggerAttached]) {
- debuggerIsAttached = YES;
- BITHockeyLogWarning(@"[HockeySDK] WARNING: Detecting crashes is NOT enabled due to running the app with a debugger attached.");
- }
- }
-
- if (!debuggerIsAttached) {
- // Multiple exception handlers can be set, but we can only query the top level error handler (uncaught exception handler).
- //
- // To check if PLCrashReporter's error handler is successfully added, we compare the top
- // level one that is set before and the one after PLCrashReporter sets up its own.
- //
- // With delayed processing we can then check if another error handler was set up afterwards
- // and can show a debug warning log message, that the dev has to make sure the "newer" error handler
- // doesn't exit the process itself, because then all subsequent handlers would never be invoked.
- //
- // Note: ANY error handler setup BEFORE HockeySDK initialization will not be processed!
-
- // get the current top level error handler
- NSUncaughtExceptionHandler *initialHandler = NSGetUncaughtExceptionHandler();
-
- // PLCrashReporter may only be initialized once. So make sure the developer
- // can't break this
- NSError *error = NULL;
-
-#if HOCKEYSDK_FEATURE_METRICS
- [self configDefaultCrashCallback];
-#endif
- // Set plCrashReporter callback which contains our default callback and potentially user defined callbacks
- [self.plCrashReporter setCrashCallbacks:&plCrashCallbacks];
-
- // Enable the Crash Reporter
- if (![self.plCrashReporter enableCrashReporterAndReturnError: &error])
- BITHockeyLogError(@"[HockeySDK] ERROR: Could not enable crash reporter: %@", [error localizedDescription]);
-
- // get the new current top level error handler, which should now be the one from PLCrashReporter
- NSUncaughtExceptionHandler *currentHandler = NSGetUncaughtExceptionHandler();
-
- // do we have a new top level error handler? then we were successful
- if (currentHandler && currentHandler != initialHandler) {
- self.exceptionHandler = currentHandler;
-
- BITHockeyLogDebug(@"INFO: Exception handler successfully initialized.");
- } else {
-
- // If we're running in a Xamarin Environment, the exception handler will be the one by the xamarin runtime, not ours.
- // In other cases, this should never happen, theoretically only if NSSetUncaugtExceptionHandler() has some internal issues
- BITHockeyLogError(@"[HockeySDK] ERROR: Exception handler could not be set. Make sure there is no other exception handler set up!");
- BITHockeyLogError(@"[HockeySDK] ERROR: If you are using the HockeySDK-Xamarin, this is expected behavior and you can ignore this message");
- }
-
- // Add the C++ uncaught exception handler, which is currently not handled by PLCrashReporter internally
- [BITCrashUncaughtCXXExceptionHandlerManager addCXXExceptionHandler:uncaught_cxx_exception_handler];
- }
- self.isSetup = YES;
- });
- }
-
- if ([[NSUserDefaults standardUserDefaults] valueForKey:kBITAppDidReceiveLowMemoryNotification])
- self.didReceiveMemoryWarningInLastSession = [[NSUserDefaults standardUserDefaults] boolForKey:kBITAppDidReceiveLowMemoryNotification];
-
- if (!self.didCrashInLastSession && self.isAppNotTerminatingCleanlyDetectionEnabled) {
- BOOL didAppSwitchToBackgroundSafely = YES;
-
- if ([[NSUserDefaults standardUserDefaults] valueForKey:kBITAppWentIntoBackgroundSafely])
- didAppSwitchToBackgroundSafely = [[NSUserDefaults standardUserDefaults] boolForKey:kBITAppWentIntoBackgroundSafely];
-
- if (!didAppSwitchToBackgroundSafely) {
- BOOL considerReport = YES;
- id strongDelegate = self.delegate;
- if ([strongDelegate respondsToSelector:@selector(considerAppNotTerminatedCleanlyReportForCrashManager:)]) {
- considerReport = [strongDelegate considerAppNotTerminatedCleanlyReportForCrashManager:self];
- }
-
- if (considerReport) {
- BITHockeyLogVerbose(@"INFO: App kill detected, creating crash report.");
- [self createCrashReportForAppKill];
-
- self.didCrashInLastSession = YES;
- }
- }
- }
-
-#if !defined (HOCKEYSDK_CONFIGURATION_ReleaseCrashOnlyExtensions)
- if ([BITHockeyHelper applicationState] != BITApplicationStateActive) {
- [self appEnteredForeground];
- }
-#else
- [self appEnteredForeground];
-#endif
-
- [[NSUserDefaults standardUserDefaults] setBool:NO forKey:kBITAppDidReceiveLowMemoryNotification];
-
- [self triggerDelayedProcessing];
- BITHockeyLogVerbose(@"VERBOSE: CrashManager startManager has finished.");
-}
-
-/**
- * Creates a fake crash report because the app was killed while being in foreground
- */
-- (void)createCrashReportForAppKill {
- NSString *fakeReportUUID = bit_UUID();
- NSString *fakeReporterKey = bit_appAnonID(NO) ?: @"???";
-
- NSString *fakeReportAppMarketingVersion = [[NSUserDefaults standardUserDefaults] objectForKey:kBITAppMarketingVersion];
-
- NSString *fakeReportAppVersion = [[NSUserDefaults standardUserDefaults] objectForKey:kBITAppVersion];
- if (!fakeReportAppVersion)
- return;
-
- NSString *fakeReportOSVersion = [[NSUserDefaults standardUserDefaults] objectForKey:kBITAppOSVersion] ?: [[UIDevice currentDevice] systemVersion];
-
- NSString *fakeReportOSVersionString = fakeReportOSVersion;
- NSString *fakeReportOSBuild = [[NSUserDefaults standardUserDefaults] objectForKey:kBITAppOSBuild] ?: [self osBuild];
- if (fakeReportOSBuild) {
- fakeReportOSVersionString = [NSString stringWithFormat:@"%@ (%@)", fakeReportOSVersion, fakeReportOSBuild];
- }
-
- NSString *fakeReportAppBundleIdentifier = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"];
- NSString *fakeReportDeviceModel = [self getDevicePlatform] ?: @"Unknown";
- NSString *fakeReportAppUUIDs = [[NSUserDefaults standardUserDefaults] objectForKey:kBITAppUUIDs] ?: @"";
-
- NSString *fakeSignalName = kBITCrashKillSignal;
-
- NSMutableString *fakeReportString = [NSMutableString string];
-
- [fakeReportString appendFormat:@"Incident Identifier: %@\n", fakeReportUUID];
- [fakeReportString appendFormat:@"CrashReporter Key: %@\n", fakeReporterKey];
- [fakeReportString appendFormat:@"Hardware Model: %@\n", fakeReportDeviceModel];
- [fakeReportString appendFormat:@"Identifier: %@\n", fakeReportAppBundleIdentifier];
-
- NSString *fakeReportAppVersionString = fakeReportAppMarketingVersion ? [NSString stringWithFormat:@"%@ (%@)", fakeReportAppMarketingVersion, fakeReportAppVersion] : fakeReportAppVersion;
-
- [fakeReportString appendFormat:@"Version: %@\n", fakeReportAppVersionString];
- [fakeReportString appendString:@"Code Type: ARM\n"];
- [fakeReportString appendString:@"\n"];
-
- NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
- NSDateFormatter *rfc3339Formatter = [[NSDateFormatter alloc] init];
- [rfc3339Formatter setLocale:enUSPOSIXLocale];
- [rfc3339Formatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"];
- [rfc3339Formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
- NSString *fakeCrashTimestamp = [rfc3339Formatter stringFromDate:[NSDate date]];
-
- // we use the current date, since we don't know when the kill actually happened
- [fakeReportString appendFormat:@"Date/Time: %@\n", fakeCrashTimestamp];
- [fakeReportString appendFormat:@"OS Version: %@\n", fakeReportOSVersionString];
- [fakeReportString appendString:@"Report Version: 104\n"];
- [fakeReportString appendString:@"\n"];
- [fakeReportString appendFormat:@"Exception Type: %@\n", fakeSignalName];
- [fakeReportString appendString:@"Exception Codes: 00000020 at 0x8badf00d\n"];
- [fakeReportString appendString:@"\n"];
- [fakeReportString appendString:@"Application Specific Information:\n"];
- [fakeReportString appendString:@"The application did not terminate cleanly but no crash occured."];
- if (self.didReceiveMemoryWarningInLastSession) {
- [fakeReportString appendString:@" The app received at least one Low Memory Warning."];
- }
- [fakeReportString appendString:@"\n\n"];
-
- NSString *fakeReportFilename = [NSString stringWithFormat: @"%.0f", [NSDate timeIntervalSinceReferenceDate]];
-
- NSError *error = nil;
-
- NSMutableDictionary *rootObj = [NSMutableDictionary dictionaryWithCapacity:2];
- [rootObj setObject:fakeReportUUID forKey:kBITFakeCrashUUID];
- if (fakeReportAppMarketingVersion)
- [rootObj setObject:fakeReportAppMarketingVersion forKey:kBITFakeCrashAppMarketingVersion];
- [rootObj setObject:fakeReportAppVersion forKey:kBITFakeCrashAppVersion];
- [rootObj setObject:fakeReportAppBundleIdentifier forKey:kBITFakeCrashAppBundleIdentifier];
- [rootObj setObject:fakeReportOSVersion forKey:kBITFakeCrashOSVersion];
- [rootObj setObject:fakeReportDeviceModel forKey:kBITFakeCrashDeviceModel];
- [rootObj setObject:fakeReportAppUUIDs forKey:kBITFakeCrashAppBinaryUUID];
- [rootObj setObject:fakeReportString forKey:kBITFakeCrashReport];
-
- self.lastSessionCrashDetails = [[BITCrashDetails alloc] initWithIncidentIdentifier:fakeReportUUID
- reporterKey:fakeReporterKey
- signal:fakeSignalName
- exceptionName:nil
- exceptionReason:nil
- appStartTime:nil
- crashTime:nil
- osVersion:fakeReportOSVersion
- osBuild:fakeReportOSBuild
- appVersion:fakeReportAppMarketingVersion
- appBuild:fakeReportAppVersion
- appProcessIdentifier:[[NSProcessInfo processInfo] processIdentifier]
- ];
-
- NSData *plist = [NSPropertyListSerialization dataWithPropertyList:(id)rootObj
- format:NSPropertyListBinaryFormat_v1_0
- options:0
- error:&error];
- if (plist) {
- if ([plist writeToFile:[self.crashesDir stringByAppendingPathComponent:(NSString *)[fakeReportFilename stringByAppendingPathExtension:@"fake"]] atomically:YES]) {
- [self storeMetaDataForCrashReportFilename:fakeReportFilename];
- }
- } else {
- BITHockeyLogError(@"ERROR: Writing fake crash report. %@", [error description]);
- }
-}
-
-/**
- * Send all approved crash reports
- *
- * Gathers all collected data and constructs the XML structure and starts the sending process
- */
-- (void)sendNextCrashReport {
- NSError *error = NULL;
-
- self.crashIdenticalCurrentVersion = NO;
-
- if ([self.crashFiles count] == 0)
- return;
-
- NSString *crashXML = nil;
- BITHockeyAttachment *attachment = nil;
-
- // we start sending always with the oldest pending one
- NSString *filename = [self.crashFiles objectAtIndex:0];
- NSString *attachmentFilename = filename;
- NSString *cacheFilename = [filename lastPathComponent];
- NSData *crashData = [NSData dataWithContentsOfFile:filename];
-
- if ([crashData length] > 0) {
- BITPLCrashReport *report = nil;
- NSString *crashUUID = @"";
- NSString *installString = nil;
- NSString *crashLogString = nil;
- NSString *appBundleIdentifier = nil;
- NSString *appBundleMarketingVersion = nil;
- NSString *appBundleVersion = nil;
- NSString *osVersion = nil;
- NSString *deviceModel = nil;
- NSString *appBinaryUUIDs = nil;
- NSString *metaFilename = nil;
-
- NSPropertyListFormat format;
-
- if ([[cacheFilename pathExtension] isEqualToString:@"fake"]) {
- NSDictionary *fakeReportDict = (NSDictionary *)[NSPropertyListSerialization
- propertyListWithData:crashData
- options:NSPropertyListMutableContainersAndLeaves
- format:&format
- error:&error];
-
- crashLogString = [fakeReportDict objectForKey:kBITFakeCrashReport];
- crashUUID = [fakeReportDict objectForKey:kBITFakeCrashUUID];
- appBundleIdentifier = [fakeReportDict objectForKey:kBITFakeCrashAppBundleIdentifier];
- appBundleMarketingVersion = [fakeReportDict objectForKey:kBITFakeCrashAppMarketingVersion] ?: @"";
- appBundleVersion = [fakeReportDict objectForKey:kBITFakeCrashAppVersion];
- appBinaryUUIDs = [fakeReportDict objectForKey:kBITFakeCrashAppBinaryUUID];
- deviceModel = [fakeReportDict objectForKey:kBITFakeCrashDeviceModel];
- osVersion = [fakeReportDict objectForKey:kBITFakeCrashOSVersion];
-
- metaFilename = [cacheFilename stringByReplacingOccurrencesOfString:@".fake" withString:@".meta"];
- attachmentFilename = [attachmentFilename stringByReplacingOccurrencesOfString:@".fake" withString:@""];
-
- if ([appBundleVersion compare:(NSString *)[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]] == NSOrderedSame) {
- self.crashIdenticalCurrentVersion = YES;
- }
-
- } else {
- report = [[BITPLCrashReport alloc] initWithData:crashData error:&error];
- }
-
- if (report == nil && crashLogString == nil) {
- BITHockeyLogWarning(@"WARNING: Could not parse crash report");
- // we cannot do anything with this report, so delete it
- [self cleanCrashReportWithFilename:filename];
- // we don't continue with the next report here, even if there are to prevent calling sendCrashReports from itself again
- // the next crash will be automatically send on the next app start/becoming active event
- return;
- }
-
- installString = bit_appAnonID(NO) ?: @"";
-
- if (report) {
- if (report.uuidRef != NULL) {
- crashUUID = (NSString *) CFBridgingRelease(CFUUIDCreateString(NULL, report.uuidRef));
- }
- metaFilename = [cacheFilename stringByAppendingPathExtension:@"meta"];
- crashLogString = [BITCrashReportTextFormatter stringValueForCrashReport:report crashReporterKey:installString];
- appBundleIdentifier = report.applicationInfo.applicationIdentifier;
- appBundleMarketingVersion = report.applicationInfo.applicationMarketingVersion ?: @"";
- appBundleVersion = report.applicationInfo.applicationVersion;
- osVersion = report.systemInfo.operatingSystemVersion;
- deviceModel = [self getDevicePlatform];
- appBinaryUUIDs = [self extractAppUUIDs:report];
- if ([report.applicationInfo.applicationVersion compare:(NSString *)[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]] == NSOrderedSame) {
- self.crashIdenticalCurrentVersion = YES;
- }
- }
-
- if ([report.applicationInfo.applicationVersion compare:(NSString *)[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]] == NSOrderedSame) {
- self.crashIdenticalCurrentVersion = YES;
- }
-
- NSString *username = @"";
- NSString *useremail = @"";
- NSString *userid = @"";
- NSString *applicationLog = @"";
- NSString *description = @"";
-
- NSData *plist = [NSData dataWithContentsOfFile:[self.crashesDir stringByAppendingPathComponent:metaFilename]];
- if (plist) {
- NSDictionary *metaDict = (NSDictionary *)[NSPropertyListSerialization
- propertyListWithData:plist
- options:NSPropertyListMutableContainersAndLeaves
- format:&format
- error:&error];
-
- username = [self stringValueFromKeychainForKey:[NSString stringWithFormat:@"%@.%@", attachmentFilename.lastPathComponent, kBITCrashMetaUserName]] ?: @"";
- useremail = [self stringValueFromKeychainForKey:[NSString stringWithFormat:@"%@.%@", attachmentFilename.lastPathComponent, kBITCrashMetaUserEmail]] ?: @"";
- userid = [self stringValueFromKeychainForKey:[NSString stringWithFormat:@"%@.%@", attachmentFilename.lastPathComponent, kBITCrashMetaUserID]] ?: @"";
- applicationLog = [metaDict objectForKey:kBITCrashMetaApplicationLog] ?: @"";
- description = [NSString stringWithContentsOfFile:[NSString stringWithFormat:@"%@.desc", [self.crashesDir stringByAppendingPathComponent: cacheFilename]] encoding:NSUTF8StringEncoding error:&error];
- attachment = [self attachmentForCrashReport:attachmentFilename];
- } else {
- BITHockeyLogError(@"ERROR: Reading crash meta data. %@", error);
- }
-
- if ([applicationLog length] > 0) {
- if ([description length] > 0) {
- description = [NSString stringWithFormat:@"%@\n\nLog:\n%@", description, applicationLog];
- } else {
- description = [NSString stringWithFormat:@"Log:\n%@", applicationLog];
- }
- }
-
- crashXML = [NSString stringWithFormat:@"%@%@%@%@%@%@%@%@%@%@%@%@",
- [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleExecutable"],
- appBinaryUUIDs,
- appBundleIdentifier,
- osVersion,
- deviceModel,
- [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"],
- appBundleMarketingVersion,
- appBundleVersion,
- crashUUID,
- [crashLogString stringByReplacingOccurrencesOfString:@"]]>" withString:@"]]" @"]]>" options:NSLiteralSearch range:NSMakeRange(0,crashLogString.length)],
- userid,
- username,
- useremail,
- installString,
- [description stringByReplacingOccurrencesOfString:@"]]>" withString:@"]]" @"]]>" options:NSLiteralSearch range:NSMakeRange(0,description.length)]];
-
- BITHockeyLogDebug(@"INFO: Sending crash reports:\n%@", crashXML);
- [self sendCrashReportWithFilename:filename xml:crashXML attachment:attachment];
- } else {
- // we cannot do anything with this report, so delete it
- [self cleanCrashReportWithFilename:filename];
- }
-}
-
-#pragma mark - Networking
-
-- (NSData *)postBodyWithXML:(NSString *)xml attachment:(BITHockeyAttachment *)attachment boundary:(NSString *)boundary {
- NSMutableData *postBody = [NSMutableData data];
-
- // [postBody appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
- [postBody appendData:[BITHockeyAppClient dataWithPostValue:BITHOCKEY_NAME
- forKey:@"sdk"
- boundary:boundary]];
-
- [postBody appendData:[BITHockeyAppClient dataWithPostValue:BITHOCKEY_VERSION
- forKey:@"sdk_version"
- boundary:boundary]];
-
- [postBody appendData:[BITHockeyAppClient dataWithPostValue:@"no"
- forKey:@"feedbackEnabled"
- boundary:boundary]];
-
- [postBody appendData:[BITHockeyAppClient dataWithPostValue:[xml dataUsingEncoding:NSUTF8StringEncoding]
- forKey:@"xml"
- contentType:@"text/xml"
- boundary:boundary
- filename:@"crash.xml"]];
-
- if (attachment && attachment.hockeyAttachmentData) {
- NSString *attachmentFilename = attachment.filename;
- if (!attachmentFilename) {
- attachmentFilename = @"Attachment_0";
- }
- [postBody appendData:[BITHockeyAppClient dataWithPostValue:attachment.hockeyAttachmentData
- forKey:@"attachment0"
- contentType:attachment.contentType
- boundary:boundary
- filename:attachmentFilename]];
- }
-
- [postBody appendData:(NSData *)[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
-
- return postBody;
-}
-
-- (NSMutableURLRequest *)requestWithBoundary:(NSString *)boundary {
- NSString *postCrashPath = [NSString stringWithFormat:@"api/2/apps/%@/crashes", self.encodedAppIdentifier];
-
- NSMutableURLRequest *request = [self.hockeyAppClient requestWithMethod:@"POST"
- path:postCrashPath
- parameters:nil];
-
- [request setCachePolicy: NSURLRequestReloadIgnoringLocalCacheData];
- [request setValue:@"HockeySDK/iOS" forHTTPHeaderField:@"User-Agent"];
- [request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];
-
- NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
- [request setValue:contentType forHTTPHeaderField:@"Content-type"];
-
- return request;
-}
-
-// process upload response
-- (void)processUploadResultWithFilename:(NSString *)filename responseData:(NSData *)responseData statusCode:(NSInteger)statusCode error:(NSError *)error {
- __block NSError *theError = error;
-
- dispatch_async(dispatch_get_main_queue(), ^{
- self.sendingInProgress = NO;
- id strongDelegate = self.delegate;
- if (nil == theError) {
- if (nil == responseData || [responseData length] == 0) {
- theError = [NSError errorWithDomain:kBITCrashErrorDomain
- code:BITCrashAPIReceivedEmptyResponse
- userInfo:@{
- NSLocalizedDescriptionKey: @"Sending failed with an empty response!"
- }
- ];
- } else if (statusCode >= 200 && statusCode < 400) {
- [self cleanCrashReportWithFilename:filename];
-
- // HockeyApp uses PList XML format
- NSMutableDictionary *response = [NSPropertyListSerialization propertyListWithData:responseData
- options:NSPropertyListMutableContainersAndLeaves
- format:nil
- error:&theError];
- BITHockeyLogDebug(@"INFO: Received API response: %@", response);
- if ([strongDelegate respondsToSelector:@selector(crashManagerDidFinishSendingCrashReport:)]) {
- [strongDelegate crashManagerDidFinishSendingCrashReport:self];
- }
-
- // only if sending the crash report went successfully, continue with the next one (if there are more)
- [self sendNextCrashReport];
- } else if (statusCode == 400) {
- [self cleanCrashReportWithFilename:filename];
-
- theError = [NSError errorWithDomain:kBITCrashErrorDomain
- code:BITCrashAPIAppVersionRejected
- userInfo:@{
- NSLocalizedDescriptionKey: @"The server rejected receiving crash reports for this app version!"
- }
- ];
- } else {
- theError = [NSError errorWithDomain:kBITCrashErrorDomain
- code:BITCrashAPIErrorWithStatusCode
- userInfo:@{
- NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Sending failed with status code: %li", (long)statusCode]
- }
- ];
- }
- }
-
- if (theError) {
- if ([strongDelegate respondsToSelector:@selector(crashManager:didFailWithError:)]) {
- [strongDelegate crashManager:self didFailWithError:theError];
- }
-
- BITHockeyLogError(@"ERROR: %@", [theError localizedDescription]);
- }
- });
-}
-
-/**
- * Send the XML data to the server
- *
- * Wraps the XML structure into a POST body and starts sending the data asynchronously
- *
- * @param xml The XML data that needs to be send to the server
- */
-- (void)sendCrashReportWithFilename:(NSString *)filename xml:(NSString*)xml attachment:(BITHockeyAttachment *)attachment {
- NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
- __block NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
-
- NSURLRequest *request = [self requestWithBoundary:kBITHockeyAppClientBoundary];
- NSData *data = [self postBodyWithXML:xml attachment:attachment boundary:kBITHockeyAppClientBoundary];
-
- if (request && data) {
- __weak typeof (self) weakSelf = self;
- NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request
- fromData:data
- completionHandler:^(NSData *responseData, NSURLResponse *response, NSError *error) {
- typeof (self) strongSelf = weakSelf;
-
- [session finishTasksAndInvalidate];
-
- NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*) response;
- NSInteger statusCode = [httpResponse statusCode];
- [strongSelf processUploadResultWithFilename:filename responseData:responseData statusCode:statusCode error:error];
- }];
-
- [uploadTask resume];
- }
- id strongDelegate = self.delegate;
- if ([strongDelegate respondsToSelector:@selector(crashManagerWillSendCrashReport:)]) {
- [strongDelegate crashManagerWillSendCrashReport:self];
- }
-
- BITHockeyLogDebug(@"INFO: Sending crash reports started.");
-}
-
-- (NSTimeInterval)timeintervalCrashInLastSessionOccured {
- return self.timeIntervalCrashInLastSessionOccurred;
-}
-
-@end
-
-#endif /* HOCKEYSDK_FEATURE_CRASH_REPORTER */
-
diff --git a/submodules/HockeySDK-iOS/Classes/BITCrashManagerDelegate.h b/submodules/HockeySDK-iOS/Classes/BITCrashManagerDelegate.h
deleted file mode 100644
index 786ead9d22..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITCrashManagerDelegate.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import
-
-@class BITCrashManager;
-@class BITHockeyAttachment;
-
-/**
- The `BITCrashManagerDelegate` formal protocol defines methods further configuring
- the behaviour of `BITCrashManager`.
- */
-
-@protocol BITCrashManagerDelegate
-
-@optional
-
-
-///-----------------------------------------------------------------------------
-/// @name Additional meta data
-///-----------------------------------------------------------------------------
-
-/** Return any log string based data the crash report being processed should contain
-
- @param crashManager The `BITCrashManager` instance invoking this delegate
- @see attachmentForCrashManager:
- @see BITHockeyManagerDelegate userNameForHockeyManager:componentManager:
- @see BITHockeyManagerDelegate userEmailForHockeyManager:componentManager:
- */
--(NSString *)applicationLogForCrashManager:(BITCrashManager *)crashManager;
-
-
-/** Return a BITHockeyAttachment object providing an NSData object the crash report
- being processed should contain
-
- Please limit your attachments to reasonable files to avoid high traffic costs for your users.
-
- Example implementation:
-
- - (BITHockeyAttachment *)attachmentForCrashManager:(BITCrashManager *)crashManager {
- NSData *data = [NSData dataWithContentsOfURL:@"mydatafile"];
-
- BITHockeyAttachment *attachment = [[BITHockeyAttachment alloc] initWithFilename:@"myfile.data"
- hockeyAttachmentData:data
- contentType:@"'application/octet-stream"];
- return attachment;
- }
-
- @param crashManager The `BITCrashManager` instance invoking this delegate
- @see BITHockeyAttachment
- @see applicationLogForCrashManager:
- @see BITHockeyManagerDelegate userNameForHockeyManager:componentManager:
- @see BITHockeyManagerDelegate userEmailForHockeyManager:componentManager:
- */
--(BITHockeyAttachment *)attachmentForCrashManager:(BITCrashManager *)crashManager;
-
-
-
-///-----------------------------------------------------------------------------
-/// @name Alert
-///-----------------------------------------------------------------------------
-
-/** Invoked before the user is asked to send a crash report, so you can do additional actions.
- E.g. to make sure not to ask the user for an app rating :)
-
- @param crashManager The `BITCrashManager` instance invoking this delegate
- */
--(void)crashManagerWillShowSubmitCrashReportAlert:(BITCrashManager *)crashManager;
-
-
-/** Invoked after the user did choose _NOT_ to send a crash in the alert
-
- @param crashManager The `BITCrashManager` instance invoking this delegate
- */
--(void)crashManagerWillCancelSendingCrashReport:(BITCrashManager *)crashManager;
-
-
-/** Invoked after the user did choose to send crashes always in the alert
-
- @param crashManager The `BITCrashManager` instance invoking this delegate
- */
--(void)crashManagerWillSendCrashReportsAlways:(BITCrashManager *)crashManager;
-
-
-///-----------------------------------------------------------------------------
-/// @name Networking
-///-----------------------------------------------------------------------------
-
-/** Invoked right before sending crash reports will start
-
- @param crashManager The `BITCrashManager` instance invoking this delegate
- */
-- (void)crashManagerWillSendCrashReport:(BITCrashManager *)crashManager;
-
-/** Invoked after sending crash reports failed
-
- @param crashManager The `BITCrashManager` instance invoking this delegate
- @param error The error returned from the NSURLSession call or `kBITCrashErrorDomain`
- with reason of type `BITCrashErrorReason`.
- */
-- (void)crashManager:(BITCrashManager *)crashManager didFailWithError:(NSError *)error;
-
-/** Invoked after sending crash reports succeeded
-
- @param crashManager The `BITCrashManager` instance invoking this delegate
- */
-- (void)crashManagerDidFinishSendingCrashReport:(BITCrashManager *)crashManager;
-
-///-----------------------------------------------------------------------------
-/// @name Experimental
-///-----------------------------------------------------------------------------
-
-/** Define if a report should be considered as a crash report
-
- Due to the risk, that these reports may be false positives, this delegates allows the
- developer to influence which reports detected by the heuristic should actually be reported.
-
- The developer can use the following property to get more information about the crash scenario:
- - `[BITCrashManager didReceiveMemoryWarningInLastSession]`: Did the app receive a low memory warning
-
- This allows only reports to be considered where at least one low memory warning notification was
- received by the app to reduce to possibility of having false positives.
-
- @param crashManager The `BITCrashManager` instance invoking this delegate
- @return `YES` if the heuristic based detected report should be reported, otherwise `NO`
- @see `[BITCrashManager didReceiveMemoryWarningInLastSession]`
- */
--(BOOL)considerAppNotTerminatedCleanlyReportForCrashManager:(BITCrashManager *)crashManager;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITCrashManagerPrivate.h b/submodules/HockeySDK-iOS/Classes/BITCrashManagerPrivate.h
deleted file mode 100644
index 0add0c801d..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITCrashManagerPrivate.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2013-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_CRASH_REPORTER
-
-#import
-
-@class BITHockeyAppClient;
-
-@interface BITCrashManager () {
-}
-
-
-///-----------------------------------------------------------------------------
-/// @name Delegate
-///-----------------------------------------------------------------------------
-
-/**
- Sets the optional `BITCrashManagerDelegate` delegate.
-
- The delegate is automatically set by using `[BITHockeyManager setDelegate:]`. You
- should not need to set this delegate individually.
-
- @see `[BITHockeyManager setDelegate:]`
- */
-@property (nonatomic, weak) id delegate;
-
-/**
- * must be set
- */
-@property (nonatomic, strong) BITHockeyAppClient *hockeyAppClient;
-
-@property (nonatomic) NSUncaughtExceptionHandler *exceptionHandler;
-
-@property (nonatomic, strong) NSFileManager *fileManager;
-
-@property (nonatomic, strong) BITPLCrashReporter *plCrashReporter;
-
-@property (nonatomic) NSString *lastCrashFilename;
-
-@property (nonatomic, copy, setter = setAlertViewHandler:) BITCustomAlertViewHandler alertViewHandler;
-
-@property (nonatomic, copy) NSString *crashesDir;
-
-#if HOCKEYSDK_FEATURE_AUTHENTICATOR
-
-// Only set via BITAuthenticator
-@property (nonatomic, copy) NSString *installationIdentification;
-
-// Only set via BITAuthenticator
-@property (nonatomic) BITAuthenticatorIdentificationType installationIdentificationType;
-
-// Only set via BITAuthenticator
-@property (nonatomic) BOOL installationIdentified;
-
-#endif /* HOCKEYSDK_FEATURE_AUTHENTICATOR */
-
-- (instancetype)initWithAppIdentifier:(NSString *)appIdentifier appEnvironment:(BITEnvironment)environment hockeyAppClient:(BITHockeyAppClient *)hockeyAppClient NS_DESIGNATED_INITIALIZER;
-
-- (void)cleanCrashReports;
-
-- (NSString *)userIDForCrashReport;
-- (NSString *)userEmailForCrashReport;
-- (NSString *)userNameForCrashReport;
-
-- (void)handleCrashReport;
-- (BOOL)hasPendingCrashReport;
-- (NSString *)firstNotApprovedCrashReport;
-
-- (void)persistUserProvidedMetaData:(BITCrashMetaData *)userProvidedMetaData;
-- (BOOL)persistAttachment:(BITHockeyAttachment *)attachment withFilename:(NSString *)filename;
-
-- (BITHockeyAttachment *)attachmentForCrashReport:(NSString *)filename;
-
-- (void)invokeDelayedProcessing;
-- (void)sendNextCrashReport;
-
-- (void)setLastCrashFilename:(NSString *)lastCrashFilename;
-
-- (void)leavingAppSafely;
-
-@end
-
-
-#endif /* HOCKEYSDK_FEATURE_CRASH_REPORTER */
diff --git a/submodules/HockeySDK-iOS/Classes/BITCrashMetaData.h b/submodules/HockeySDK-iOS/Classes/BITCrashMetaData.h
deleted file mode 100644
index 10508b5794..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITCrashMetaData.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import
-
-
-/**
- * This class provides properties that can be attached to a crash report via a custom alert view flow
- */
-@interface BITCrashMetaData : NSObject
-
-/**
- * User provided description that should be attached to the crash report as plain text
- */
-@property (nonatomic, copy) NSString *userProvidedDescription;
-
-/**
- * User name that should be attached to the crash report
- */
-@property (nonatomic, copy) NSString *userName;
-
-/**
- * User email that should be attached to the crash report
- */
-@property (nonatomic, copy) NSString *userEmail;
-
-/**
- * User ID that should be attached to the crash report
- */
-@property (nonatomic, copy) NSString *userID;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITCrashMetaData.m b/submodules/HockeySDK-iOS/Classes/BITCrashMetaData.m
deleted file mode 100644
index 2ec133dd65..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITCrashMetaData.m
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_CRASH_REPORTER
-
-#import "BITCrashMetaData.h"
-
-@implementation BITCrashMetaData
-
-@end
-
-#endif
diff --git a/submodules/HockeySDK-iOS/Classes/BITCrashReportTextFormatter.h b/submodules/HockeySDK-iOS/Classes/BITCrashReportTextFormatter.h
deleted file mode 100644
index c75d93c67f..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITCrashReportTextFormatter.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Authors:
- * Landon Fuller
- * Damian Morris
- * Andreas Linde
- *
- * Copyright (c) 2008-2013 Plausible Labs Cooperative, Inc.
- * Copyright (c) 2010 MOSO Corporation, Pty Ltd.
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#import
-
-@class PLCrashReport;
-
-
-// Dictionary keys for array elements returned by arrayOfAppUUIDsForCrashReport:
-#ifndef kBITBinaryImageKeyUUID
-#define kBITBinaryImageKeyUUID @"uuid"
-#define kBITBinaryImageKeyArch @"arch"
-#define kBITBinaryImageKeyType @"type"
-#endif
-
-
-/**
- * HockeySDK Crash Reporter error domain
- */
-typedef NS_ENUM (NSInteger, BITBinaryImageType) {
- /**
- * App binary
- */
- BITBinaryImageTypeAppBinary,
- /**
- * App provided framework
- */
- BITBinaryImageTypeAppFramework,
- /**
- * Image not related to the app
- */
- BITBinaryImageTypeOther
-};
-
-
-@interface BITCrashReportTextFormatter : NSObject {
-}
-
-+ (NSString *)stringValueForCrashReport:(PLCrashReport *)report crashReporterKey:(NSString *)crashReporterKey;
-+ (NSArray *)arrayOfAppUUIDsForCrashReport:(PLCrashReport *)report;
-+ (NSString *)bit_archNameFromCPUType:(uint64_t)cpuType subType:(uint64_t)subType;
-+ (BITBinaryImageType)bit_imageTypeForImagePath:(NSString *)imagePath processPath:(NSString *)processPath;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITCrashReportTextFormatter.m b/submodules/HockeySDK-iOS/Classes/BITCrashReportTextFormatter.m
deleted file mode 100644
index 4c896802e6..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITCrashReportTextFormatter.m
+++ /dev/null
@@ -1,928 +0,0 @@
-/*
- * Authors:
- * Landon Fuller
- * Damian Morris
- * Andreas Linde
- *
- * Copyright (c) 2008-2013 Plausible Labs Cooperative, Inc.
- * Copyright (c) 2010 MOSO Corporation, Pty Ltd.
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import "HockeySDK.h"
-#import "HockeySDKPrivate.h"
-
-#if HOCKEYSDK_FEATURE_CRASH_REPORTER
-
-#import
-
-#import
-#import
-#import
-#import
-#import
-
-#if defined(__OBJC2__)
-#define SEL_NAME_SECT "__objc_methname"
-#else
-#define SEL_NAME_SECT "__cstring"
-#endif
-
-#import "BITCrashReportTextFormatter.h"
-
-/*
- * XXX: The ARM64 CPU type, and ARM_V7S and ARM_V8 Mach-O CPU subtypes are not
- * defined in the Mac OS X 10.8 headers.
- */
-#ifndef CPU_SUBTYPE_ARM_V7S
-# define CPU_SUBTYPE_ARM_V7S 11
-#endif
-
-#ifndef CPU_TYPE_ARM64
-#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
-#endif
-
-#ifndef CPU_SUBTYPE_ARM_V8
-# define CPU_SUBTYPE_ARM_V8 13
-#endif
-
-/**
- * Sort PLCrashReportBinaryImageInfo instances by their starting address.
- */
-static NSInteger bit_binaryImageSort(id binary1, id binary2, void *__unused context) {
- uint64_t addr1 = [binary1 imageBaseAddress];
- uint64_t addr2 = [binary2 imageBaseAddress];
-
- if (addr1 < addr2)
- return NSOrderedAscending;
- else if (addr1 > addr2)
- return NSOrderedDescending;
- else
- return NSOrderedSame;
-}
-
-/**
- * Validates that the given @a string terminates prior to @a limit.
- */
-static const char *safer_string_read (const char *string, const char *limit) {
- const char *p = string;
- do {
- if (p >= limit || p+1 >= limit) {
- return NULL;
- }
- p++;
- } while (*p != '\0');
-
- return string;
-}
-
-/*
- * The relativeAddress should be ` - `, extracted from the crash report's thread
- * and binary image list.
- *
- * For the (architecture-specific) registers to attempt, see:
- * http://sealiesoftware.com/blog/archive/2008/09/22/objc_explain_So_you_crashed_in_objc_msgSend.html
- */
-static const char *findSEL (const char *imageName, NSString *imageUUID, uint64_t relativeAddress) {
- unsigned int images_count = _dyld_image_count();
- for (unsigned int i = 0; i < images_count; ++i) {
- intptr_t slide = _dyld_get_image_vmaddr_slide(i);
- const struct mach_header *header = _dyld_get_image_header(i);
- const struct mach_header_64 *header64 = (const struct mach_header_64 *) header;
- const char *name = _dyld_get_image_name(i);
-
- /* Image disappeared? */
- if (name == NULL || header == NULL)
- continue;
-
- /* Check if this is the correct image. If we were being even more careful, we'd check the LC_UUID */
- if (strcmp(name, imageName) != 0)
- continue;
-
- /* Determine whether this is a 64-bit or 32-bit Mach-O file */
- BOOL m64 = NO;
- if (header->magic == MH_MAGIC_64)
- m64 = YES;
-
- NSString *uuidString = nil;
- const uint8_t *command;
- uint32_t ncmds;
-
- if (m64) {
- command = (const uint8_t *)(header64 + 1);
- ncmds = header64->ncmds;
- } else {
- command = (const uint8_t *)(header + 1);
- ncmds = header->ncmds;
- }
- for (uint32_t idx = 0; idx < ncmds; ++idx) {
- const struct load_command *load_command = (const struct load_command *)command;
- if (load_command->cmd == LC_UUID) {
- const struct uuid_command *uuid_command = (const struct uuid_command *)command;
- const uint8_t *uuid = uuid_command->uuid;
- uuidString = [[NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
- uuid[0], uuid[1], uuid[2], uuid[3],
- uuid[4], uuid[5], uuid[6], uuid[7],
- uuid[8], uuid[9], uuid[10], uuid[11],
- uuid[12], uuid[13], uuid[14], uuid[15]]
- lowercaseString];
- break;
- } else {
- command += load_command->cmdsize;
- }
- }
-
- // Check if this is the correct image by comparing the UUIDs
- if (!uuidString || ![uuidString isEqualToString:imageUUID])
- continue;
-
- /* Fetch the __objc_methname section */
- const char *methname_sect;
- uint64_t methname_sect_size;
- if (m64) {
- methname_sect = getsectdatafromheader_64(header64, SEG_TEXT, SEL_NAME_SECT, &methname_sect_size);
- } else {
- uint32_t meth_size_32;
- methname_sect = getsectdatafromheader(header, SEG_TEXT, SEL_NAME_SECT, &meth_size_32);
- methname_sect_size = meth_size_32;
- }
-
- /* Apply the slide, as per getsectdatafromheader(3) */
- methname_sect += slide;
-
- if (methname_sect == NULL) {
- return NULL;
- }
-
- /* Calculate the target address within this image, and verify that it is within __objc_methname */
- const char *target = ((const char *)header) + relativeAddress;
- const char *limit = methname_sect + methname_sect_size;
- if (target < methname_sect || target >= limit) {
- return NULL;
- }
-
- /* Read the actual method name */
- return safer_string_read(target, limit);
- }
-
- return NULL;
-}
-
-/**
- * Formats PLCrashReport data as human-readable text.
- */
-@implementation BITCrashReportTextFormatter
-
-static NSString *const BITXamarinStackTraceDelimiter = @"Xamarin Exception Stack:";
-
-/**
- * Formats the provided @a report as human-readable text in the given @a textFormat, and return
- * the formatted result as a string.
- *
- * @param report The report to format.
- * @param crashReporterKey The crash reporter key.
- *
- * @return Returns the formatted result on success, or nil if an error occurs.
- */
-+ (NSString *)stringValueForCrashReport:(BITPLCrashReport *)report crashReporterKey:(NSString *)crashReporterKey {
- NSMutableString* text = [NSMutableString string];
- boolean_t lp64 = true; // quiesce GCC uninitialized value warning
-
- /* Header */
-
- /* Map to apple style OS name */
- NSString *osName;
- switch (report.systemInfo.operatingSystem) {
- case PLCrashReportOperatingSystemMacOSX:
- osName = @"Mac OS X";
- break;
- case PLCrashReportOperatingSystemiPhoneOS:
- osName = @"iPhone OS";
- break;
- case PLCrashReportOperatingSystemiPhoneSimulator:
- osName = @"Mac OS X";
- break;
- default:
- osName = [NSString stringWithFormat: @"Unknown (%d)", report.systemInfo.operatingSystem];
- break;
- }
-
- /* Map to Apple-style code type, and mark whether architecture is LP64 (64-bit) */
- NSString *codeType = nil;
- {
- /* Attempt to derive the code type from the binary images */
- for (BITPLCrashReportBinaryImageInfo *image in report.images) {
- /* Skip images with no specified type */
- if (image.codeType == nil)
- continue;
-
- /* Skip unknown encodings */
- if (image.codeType.typeEncoding != PLCrashReportProcessorTypeEncodingMach)
- continue;
-
- switch (image.codeType.type) {
- case CPU_TYPE_ARM:
- codeType = @"ARM";
- lp64 = false;
- break;
-
- case CPU_TYPE_ARM64:
- codeType = @"ARM-64";
- lp64 = true;
- break;
-
- case CPU_TYPE_X86:
- codeType = @"X86";
- lp64 = false;
- break;
-
- case CPU_TYPE_X86_64:
- codeType = @"X86-64";
- lp64 = true;
- break;
-
- case CPU_TYPE_POWERPC:
- codeType = @"PPC";
- lp64 = false;
- break;
-
- default:
- // Do nothing, handled below.
- break;
- }
-
- /* Stop immediately if code type was discovered */
- if (codeType != nil)
- break;
- }
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
- /* If we were unable to determine the code type, fall back on the legacy architecture value. */
- if (codeType == nil) {
- switch (report.systemInfo.architecture) {
- case PLCrashReportArchitectureARMv6:
- case PLCrashReportArchitectureARMv7:
- codeType = @"ARM";
- lp64 = false;
- break;
- case PLCrashReportArchitectureX86_32:
- codeType = @"X86";
- lp64 = false;
- break;
- case PLCrashReportArchitectureX86_64:
- codeType = @"X86-64";
- lp64 = true;
- break;
- case PLCrashReportArchitecturePPC:
- codeType = @"PPC";
- lp64 = false;
- break;
- default:
- codeType = [NSString stringWithFormat: @"Unknown (%d)", report.systemInfo.architecture];
- lp64 = true;
- break;
- }
- }
-#pragma GCC diagnostic pop
- }
-
- {
- NSString *reporterKey = @"???";
- if (crashReporterKey && [crashReporterKey length] > 0)
- reporterKey = crashReporterKey;
-
- NSString *hardwareModel = @"???";
- if (report.hasMachineInfo && report.machineInfo.modelName != nil)
- hardwareModel = report.machineInfo.modelName;
-
- NSString *incidentIdentifier = @"???";
- if (report.uuidRef != NULL) {
- incidentIdentifier = (NSString *) CFBridgingRelease(CFUUIDCreateString(NULL, report.uuidRef));
- }
-
- [text appendFormat: @"Incident Identifier: %@\n", incidentIdentifier];
- [text appendFormat: @"CrashReporter Key: %@\n", reporterKey];
- [text appendFormat: @"Hardware Model: %@\n", hardwareModel];
- }
-
- /* Application and process info */
- {
- NSString *unknownString = @"???";
-
- NSString *processName = unknownString;
- NSString *processId = unknownString;
- NSString *processPath = unknownString;
- NSString *parentProcessName = unknownString;
- NSString *parentProcessId = unknownString;
-
- /* Process information was not available in earlier crash report versions */
- if (report.hasProcessInfo) {
- /* Process Name */
- if (report.processInfo.processName != nil)
- processName = report.processInfo.processName;
-
- /* PID */
- processId = [@(report.processInfo.processID) stringValue];
-
- /* Process Path */
- if (report.processInfo.processPath != nil) {
- processPath = report.processInfo.processPath;
-
- /* Remove username from the path */
-#if TARGET_OS_SIMULATOR
- processPath = [self anonymizedPathFromPath:processPath];
-#endif
- }
-
- /* Parent Process Name */
- if (report.processInfo.parentProcessName != nil)
- parentProcessName = report.processInfo.parentProcessName;
-
- /* Parent Process ID */
- parentProcessId = [@(report.processInfo.parentProcessID) stringValue];
- }
-
- [text appendFormat: @"Process: %@ [%@]\n", processName, processId];
- [text appendFormat: @"Path: %@\n", processPath];
- [text appendFormat: @"Identifier: %@\n", report.applicationInfo.applicationIdentifier];
-
- NSString *marketingVersion = report.applicationInfo.applicationMarketingVersion;
- NSString *appVersion = report.applicationInfo.applicationVersion;
- NSString *versionString = marketingVersion ? [NSString stringWithFormat:@"%@ (%@)", marketingVersion, appVersion] : appVersion;
-
- [text appendFormat: @"Version: %@\n", versionString];
- [text appendFormat: @"Code Type: %@\n", codeType];
- [text appendFormat: @"Parent Process: %@ [%@]\n", parentProcessName, parentProcessId];
- }
-
- [text appendString: @"\n"];
-
- NSString *xamarinTrace;
- NSString *exceptionReason;
-
- /* System info */
- {
- NSString *osBuild = @"???";
- if (report.systemInfo.operatingSystemBuild != nil)
- osBuild = report.systemInfo.operatingSystemBuild;
-
- NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
- NSDateFormatter *rfc3339Formatter = [[NSDateFormatter alloc] init];
- [rfc3339Formatter setLocale:enUSPOSIXLocale];
- [rfc3339Formatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"];
- [rfc3339Formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
-
- [text appendFormat: @"Date/Time: %@\n", [rfc3339Formatter stringFromDate:report.systemInfo.timestamp]];
- if ([report.processInfo respondsToSelector:@selector(processStartTime)]) {
- if (report.systemInfo.timestamp && report.processInfo.processStartTime) {
- [text appendFormat: @"Launch Time: %@\n", [rfc3339Formatter stringFromDate:report.processInfo.processStartTime]];
- }
- }
- [text appendFormat: @"OS Version: %@ %@ (%@)\n", osName, report.systemInfo.operatingSystemVersion, osBuild];
-
- // Check if exception data contains xamarin stacktrace in order to determine report version
- if (report.hasExceptionInfo) {
- exceptionReason = report.exceptionInfo.exceptionReason;
- NSInteger xamarinTracePosition = [exceptionReason rangeOfString:BITXamarinStackTraceDelimiter].location;
- if (xamarinTracePosition != NSNotFound) {
- xamarinTrace = [exceptionReason substringFromIndex:xamarinTracePosition];
- xamarinTrace = [xamarinTrace stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
- xamarinTrace = [xamarinTrace stringByReplacingOccurrencesOfString:@"<---\n\n--->" withString:@"<---\n--->"];
- exceptionReason = [exceptionReason substringToIndex:xamarinTracePosition];
- exceptionReason = [exceptionReason stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
- }
- }
- NSString *reportVersion = (xamarinTrace) ? @"104-Xamarin" : @"104";
- [text appendFormat: @"Report Version: %@\n", reportVersion];
- }
-
- [text appendString: @"\n"];
-
- /* Exception code */
- [text appendFormat: @"Exception Type: %@\n", report.signalInfo.name];
- [text appendFormat: @"Exception Codes: %@ at 0x%" PRIx64 "\n", report.signalInfo.code, report.signalInfo.address];
-
- for (BITPLCrashReportThreadInfo *thread in report.threads) {
- if (thread.crashed) {
- [text appendFormat: @"Crashed Thread: %ld\n", (long) thread.threadNumber];
- break;
- }
- }
-
- [text appendString: @"\n"];
-
- BITPLCrashReportThreadInfo *crashed_thread = nil;
- for (BITPLCrashReportThreadInfo *thread in report.threads) {
- if (thread.crashed) {
- crashed_thread = thread;
- break;
- }
- }
-
- /* Uncaught Exception */
- if (report.hasExceptionInfo) {
- [text appendFormat: @"Application Specific Information:\n"];
- [text appendFormat: @"*** Terminating app due to uncaught exception '%@', reason: '%@'\n",
- report.exceptionInfo.exceptionName, exceptionReason];
- [text appendString: @"\n"];
-
- /* Xamarin Exception */
- if (xamarinTrace) {
- [text appendFormat:@"%@\n", xamarinTrace];
- [text appendString: @"\n"];
- }
-
- } else if (crashed_thread != nil) {
- // try to find the selector in case this was a crash in obj_msgSend
- // we search this whether the crash happened in obj_msgSend or not since we don't have the symbol!
-
- NSString *foundSelector = nil;
-
- // search the registers value for the current arch
-#if TARGET_OS_SIMULATOR
- if (lp64) {
- foundSelector = [[self class] selectorForRegisterWithName:@"rsi" ofThread:crashed_thread report:report];
- if (foundSelector == NULL)
- foundSelector = [[self class] selectorForRegisterWithName:@"rdx" ofThread:crashed_thread report:report];
- } else {
- foundSelector = [[self class] selectorForRegisterWithName:@"ecx" ofThread:crashed_thread report:report];
- }
-#else
- if (lp64) {
- foundSelector = [[self class] selectorForRegisterWithName:@"x1" ofThread:crashed_thread report:report];
- } else {
- foundSelector = [[self class] selectorForRegisterWithName:@"r1" ofThread:crashed_thread report:report];
- if (foundSelector == NULL)
- foundSelector = [[self class] selectorForRegisterWithName:@"r2" ofThread:crashed_thread report:report];
- }
-#endif
-
- if (foundSelector) {
- [text appendFormat: @"Application Specific Information:\n"];
- [text appendFormat: @"Selector name found in current argument registers: %@\n", foundSelector];
- [text appendString: @"\n"];
- }
- }
-
- /* If an exception stack trace is available, output an Apple-compatible backtrace. */
- if (report.exceptionInfo != nil && report.exceptionInfo.stackFrames != nil && [report.exceptionInfo.stackFrames count] > 0) {
- BITPLCrashReportExceptionInfo *exception = report.exceptionInfo;
-
- /* Create the header. */
- [text appendString: @"Last Exception Backtrace:\n"];
-
- /* Write out the frames. In raw reports, Apple writes this out as a simple list of PCs. In the minimally
- * post-processed report, Apple writes this out as full frame entries. We use the latter format. */
- for (NSUInteger frame_idx = 0; frame_idx < [exception.stackFrames count]; frame_idx++) {
- BITPLCrashReportStackFrameInfo *frameInfo = exception.stackFrames[frame_idx];
- [text appendString: [[self class] bit_formatStackFrame: frameInfo frameIndex: frame_idx report: report lp64: lp64]];
- }
- [text appendString: @"\n"];
- }
-
- /* Threads */
- NSInteger maxThreadNum = 0;
- for (BITPLCrashReportThreadInfo *thread in report.threads) {
- if (thread.crashed) {
- [text appendFormat: @"Thread %ld Crashed:\n", (long) thread.threadNumber];
- } else {
- [text appendFormat: @"Thread %ld:\n", (long) thread.threadNumber];
- }
- for (NSUInteger frame_idx = 0; frame_idx < [thread.stackFrames count]; frame_idx++) {
- BITPLCrashReportStackFrameInfo *frameInfo = thread.stackFrames[frame_idx];
- [text appendString:[[self class] bit_formatStackFrame:frameInfo frameIndex:frame_idx report:report lp64:lp64]];
- }
- [text appendString: @"\n"];
-
- /* Track the highest thread number */
- maxThreadNum = MAX(maxThreadNum, thread.threadNumber);
- }
-
- /* Registers */
- if (crashed_thread != nil) {
- [text appendFormat: @"Thread %ld crashed with %@ Thread State:\n", (long) crashed_thread.threadNumber, codeType];
-
- int regColumn = 0;
- for (BITPLCrashReportRegisterInfo *reg in crashed_thread.registers) {
- NSString *reg_fmt;
-
- /* Use 32-bit or 64-bit fixed width format for the register values */
- if (lp64)
- reg_fmt = @"%6s: 0x%016" PRIx64 " ";
- else
- reg_fmt = @"%6s: 0x%08" PRIx64 " ";
-
- /* Remap register names to match Apple's crash reports */
- NSString *regName = reg.registerName;
- if (report.machineInfo != nil && report.machineInfo.processorInfo.typeEncoding == PLCrashReportProcessorTypeEncodingMach) {
- BITPLCrashReportProcessorInfo *pinfo = report.machineInfo.processorInfo;
- cpu_type_t arch_type = (cpu_type_t)(pinfo.type & ~CPU_ARCH_MASK);
-
- /* Apple uses 'ip' rather than 'r12' on ARM */
- if (arch_type == CPU_TYPE_ARM && [regName isEqual: @"r12"]) {
- regName = @"ip";
- }
- }
- [text appendFormat: reg_fmt, [regName UTF8String], reg.registerValue];
-
- regColumn++;
- if (regColumn == 4) {
- [text appendString: @"\n"];
- regColumn = 0;
- }
- }
-
- if (regColumn != 0)
- [text appendString: @"\n"];
-
- [text appendString: @"\n"];
- }
-
- /* Images. The iPhone crash report format sorts these in ascending order, by the base address */
- [text appendString: @"Binary Images:\n"];
- NSMutableArray *addedImagesBaseAddresses = @[].mutableCopy;
- for (BITPLCrashReportBinaryImageInfo *imageInfo in [report.images sortedArrayUsingFunction: bit_binaryImageSort context: nil]) {
- // Make sure we don't add duplicates
- if ([addedImagesBaseAddresses containsObject:@(imageInfo.imageBaseAddress)]) {
- continue;
- } else {
- [addedImagesBaseAddresses addObject:@(imageInfo.imageBaseAddress)];
- }
-
- NSString *uuid;
- /* Fetch the UUID if it exists */
- if (imageInfo.hasImageUUID)
- uuid = imageInfo.imageUUID;
- else
- uuid = @"???";
-
- /* Determine the architecture string */
- NSString *archName = [[self class] bit_archNameFromImageInfo:imageInfo];
-
- /* Determine if this is the main executable or an app specific framework*/
- NSString *binaryDesignator = @" ";
- BITBinaryImageType imageType = [[self class] bit_imageTypeForImagePath:imageInfo.imageName
- processPath:report.processInfo.processPath];
- if (imageType != BITBinaryImageTypeOther) {
- binaryDesignator = @"+";
- }
-
- /* base_address - terminating_address [designator]file_name arch file_path */
- NSString *fmt = nil;
- if (lp64) {
- fmt = @"%18#" PRIx64 " - %18#" PRIx64 " %@%@ %@ <%@> %@\n";
- } else {
- fmt = @"%10#" PRIx64 " - %10#" PRIx64 " %@%@ %@ <%@> %@\n";
- }
-
- /* Remove username from the image path */
- NSString *imageName = @"";
- if (imageInfo.imageName && [imageInfo.imageName length] > 0) {
-#if TARGET_OS_SIMULATOR
- imageName = [imageInfo.imageName stringByAbbreviatingWithTildeInPath];
-#else
- imageName = imageInfo.imageName;
-#endif
- }
-#if TARGET_OS_SIMULATOR
- imageName = [self anonymizedPathFromPath:imageName];
-#endif
- [text appendFormat: fmt,
- imageInfo.imageBaseAddress,
- imageInfo.imageBaseAddress + (MAX(1U, imageInfo.imageSize) - 1), // The Apple format uses an inclusive range
- binaryDesignator,
- [imageInfo.imageName lastPathComponent],
- archName,
- uuid,
- imageName];
- }
-
-
- return text;
-}
-
-/**
- * Return the selector string of a given register name
- *
- * @param regName The name of the register to use for getting the address
- * @param thread The crashed thread
- * @param report The crash report.
- *
- * @return The selector as a C string or NULL if no selector was found
- */
-+ (NSString *)selectorForRegisterWithName:(NSString *)regName ofThread:(BITPLCrashReportThreadInfo *)thread report:(BITPLCrashReport *)report {
- // get the address for the register
- uint64_t regAddress = 0;
-
- for (BITPLCrashReportRegisterInfo *reg in thread.registers) {
- if ([reg.registerName isEqualToString:regName]) {
- regAddress = reg.registerValue;
- break;
- }
- }
-
- if (regAddress == 0)
- return nil;
-
- BITPLCrashReportBinaryImageInfo *imageForRegAddress = [report imageForAddress:regAddress];
- if (imageForRegAddress) {
- // get the SEL
- const char *foundSelector = findSEL([imageForRegAddress.imageName UTF8String], imageForRegAddress.imageUUID, regAddress - (uint64_t)imageForRegAddress.imageBaseAddress);
-
- if (foundSelector != NULL) {
- return [NSString stringWithUTF8String:foundSelector];
- }
- }
-
- return nil;
-}
-
-
-/**
- * Returns an array of app UUIDs and their architecture
- * As a dictionary for each element
- *
- * @param report The report to format.
- *
- * @return Returns the formatted result on success, or nil if an error occurs.
- */
-+ (NSArray *)arrayOfAppUUIDsForCrashReport:(BITPLCrashReport *)report {
- NSMutableArray* appUUIDs = [NSMutableArray array];
-
- /* Images. The iPhone crash report format sorts these in ascending order, by the base address */
- for (BITPLCrashReportBinaryImageInfo *imageInfo in [report.images sortedArrayUsingFunction: bit_binaryImageSort context: nil]) {
- NSString *uuid;
- /* Fetch the UUID if it exists */
- uuid = imageInfo.hasImageUUID ? imageInfo.imageUUID : @"???";
-
- /* Determine the architecture string */
- NSString *archName = [[self class] bit_archNameFromImageInfo:imageInfo];
-
- /* Determine if this is the app executable or app specific framework */
- BITBinaryImageType imageType = [[self class] bit_imageTypeForImagePath:imageInfo.imageName
- processPath:report.processInfo.processPath];
- if (imageType != BITBinaryImageTypeOther) {
- NSString *imageTypeString;
-
- if (imageType == BITBinaryImageTypeAppBinary) {
- imageTypeString = @"app";
- } else {
- imageTypeString = @"framework";
- }
-
- [appUUIDs addObject:@{kBITBinaryImageKeyUUID: uuid,
- kBITBinaryImageKeyArch: archName,
- kBITBinaryImageKeyType: imageTypeString}
- ];
- }
- }
-
- return appUUIDs;
-}
-
-/* Determine if in binary image is the app executable or app specific framework */
-+ (BITBinaryImageType)bit_imageTypeForImagePath:(NSString *)imagePath processPath:(NSString *)processPath {
- if (!imagePath || !processPath) {
- return BITBinaryImageTypeOther;
- }
- BITBinaryImageType imageType = BITBinaryImageTypeOther;
-
- NSString *standardizedImagePath = [[imagePath stringByStandardizingPath] lowercaseString];
- NSString *lowercaseImagePath = [imagePath lowercaseString];
- NSString *lowercaseProcessPath = [processPath lowercaseString];
-
- NSRange appRange = [standardizedImagePath rangeOfString: @".app/"];
-
- // Exclude iOS swift dylibs. These are provided as part of the app binary by Xcode for now, but we never get a dSYM for those.
- NSRange swiftLibRange = [standardizedImagePath rangeOfString:@"frameworks/libswift"];
- BOOL dylibSuffix = [standardizedImagePath hasSuffix:@".dylib"];
-
- if (appRange.location != NSNotFound && !(swiftLibRange.location != NSNotFound && dylibSuffix)) {
- NSString *appBundleContentsPath = [standardizedImagePath substringToIndex:appRange.location + 5];
-
- if ([standardizedImagePath isEqual: lowercaseProcessPath] ||
- // Fix issue with iOS 8 `stringByStandardizingPath` removing leading `/private` path (when not running in the debugger or simulator only)
- [lowercaseImagePath hasPrefix:lowercaseProcessPath]) {
- imageType = BITBinaryImageTypeAppBinary;
- } else if ([standardizedImagePath hasPrefix:appBundleContentsPath] ||
- // Fix issue with iOS 8 `stringByStandardizingPath` removing leading `/private` path (when not running in the debugger or simulator only)
- [lowercaseImagePath hasPrefix:appBundleContentsPath]) {
- imageType = BITBinaryImageTypeAppFramework;
- }
- }
-
- return imageType;
-}
-
-+ (NSString *)bit_archNameFromImageInfo:(BITPLCrashReportBinaryImageInfo *)imageInfo
-{
- NSString *archName = @"???";
- if (imageInfo.codeType != nil && imageInfo.codeType.typeEncoding == PLCrashReportProcessorTypeEncodingMach) {
- archName = [BITCrashReportTextFormatter bit_archNameFromCPUType:imageInfo.codeType.type subType:imageInfo.codeType.subtype];
- }
-
- return archName;
-}
-
-+ (NSString *)bit_archNameFromCPUType:(uint64_t)cpuType subType:(uint64_t)subType {
- NSString *archName = @"???";
- switch (cpuType) {
- case CPU_TYPE_ARM:
- /* Apple includes subtype for ARM binaries. */
- switch (subType) {
- case CPU_SUBTYPE_ARM_V6:
- archName = @"armv6";
- break;
-
- case CPU_SUBTYPE_ARM_V7:
- archName = @"armv7";
- break;
-
- case CPU_SUBTYPE_ARM_V7S:
- archName = @"armv7s";
- break;
-
- default:
- archName = @"arm-unknown";
- break;
- }
- break;
-
- case CPU_TYPE_ARM64:
- /* Apple includes subtype for ARM64 binaries. */
- switch (subType) {
- case CPU_SUBTYPE_ARM_ALL:
- archName = @"arm64";
- break;
-
- case CPU_SUBTYPE_ARM_V8:
- archName = @"arm64";
- break;
-
- default:
- archName = @"arm64-unknown";
- break;
- }
- break;
-
- case CPU_TYPE_X86:
- archName = @"i386";
- break;
-
- case CPU_TYPE_X86_64:
- archName = @"x86_64";
- break;
-
- case CPU_TYPE_POWERPC:
- archName = @"powerpc";
- break;
-
- default:
- // Use the default archName value (initialized above).
- break;
- }
-
- return archName;
-}
-
-
-/**
- * Format a stack frame for display in a thread backtrace.
- *
- * @param frameInfo The stack frame to format
- * @param frameIndex The frame's index
- * @param report The report from which this frame was acquired.
- * @param lp64 If YES, the report was generated by an LP64 system.
- *
- * @return Returns a formatted frame line.
- */
-+ (NSString *)bit_formatStackFrame: (BITPLCrashReportStackFrameInfo *) frameInfo
- frameIndex: (NSUInteger) frameIndex
- report: (BITPLCrashReport *) report
- lp64: (boolean_t) lp64
-{
- /* Base image address containing instrumentation pointer, offset of the IP from that base
- * address, and the associated image name */
- uint64_t baseAddress = 0x0;
- uint64_t pcOffset = 0x0;
- NSString *imageName = @"\?\?\?";
- NSString *symbolString = nil;
-
- BITPLCrashReportBinaryImageInfo *imageInfo = [report imageForAddress: frameInfo.instructionPointer];
- if (imageInfo != nil) {
- imageName = [imageInfo.imageName lastPathComponent];
- baseAddress = imageInfo.imageBaseAddress;
- pcOffset = frameInfo.instructionPointer - imageInfo.imageBaseAddress;
- }
-
- /* Make sure UTF8/16 characters are handled correctly */
- NSInteger offset = 0;
- NSUInteger index = 0;
- for (index = 0; index < [imageName length]; index++) {
- NSRange range = [imageName rangeOfComposedCharacterSequenceAtIndex:index];
- if (range.length > 1) {
- offset += range.length - 1;
- index += range.length - 1;
- }
- if (index > 32) {
- imageName = [NSString stringWithFormat:@"%@... ", [imageName substringToIndex:index - 1]];
- index += 3;
- break;
- }
- }
- if (index-offset < 36) {
- imageName = [imageName stringByPaddingToLength:(NSUInteger)(36 + offset) withString:@" " startingAtIndex:0];
- }
-
- /* If symbol info is available, the format used in Apple's reports is Sym + OffsetFromSym. Otherwise,
- * the format used is imageBaseAddress + offsetToIP */
- BITBinaryImageType imageType = [[self class] bit_imageTypeForImagePath:imageInfo.imageName
- processPath:report.processInfo.processPath];
- if (frameInfo.symbolInfo != nil && imageType == BITBinaryImageTypeOther) {
- NSString *symbolName = frameInfo.symbolInfo.symbolName;
-
- /* Apple strips the _ symbol prefix in their reports. Only OS X makes use of an
- * underscore symbol prefix by default. */
- if ([symbolName rangeOfString: @"_"].location == 0 && [symbolName length] > 1) {
- switch (report.systemInfo.operatingSystem) {
- case PLCrashReportOperatingSystemMacOSX:
- case PLCrashReportOperatingSystemiPhoneOS:
- case PLCrashReportOperatingSystemiPhoneSimulator:
- symbolName = [symbolName substringFromIndex: 1];
- break;
-
- default:
- BITHockeyLogDebug(@"Symbol prefix rules are unknown for this OS!");
- break;
- }
- }
-
-
- uint64_t symOffset = frameInfo.instructionPointer - frameInfo.symbolInfo.startAddress;
- symbolString = [NSString stringWithFormat: @"%@ + %" PRId64, symbolName, symOffset];
- } else {
- symbolString = [NSString stringWithFormat: @"0x%" PRIx64 " + %" PRId64, baseAddress, pcOffset];
- }
-
- /* Note that width specifiers are ignored for %@, but work for C strings.
- * UTF-8 is not correctly handled with %s (it depends on the system encoding), but
- * UTF-16 is supported via %S, so we use it here */
- return [NSString stringWithFormat: @"%-4ld%-35S 0x%0*" PRIx64 " %@\n",
- (long) frameIndex,
- (const uint16_t *)[imageName cStringUsingEncoding: NSUTF16StringEncoding],
- lp64 ? 16 : 8, frameInfo.instructionPointer,
- symbolString];
-}
-
-/**
- * Remove the user's name from a crash's process path.
- * This is only necessary when sending crashes from the simulator as the path
- * then contains the username of the Mac the simulator is running on.
- *
- * @param path A string containing the username.
- *
- * @return An anonymized string where the real username is replaced by "USER"
- */
-+ (NSString *)anonymizedPathFromPath:(NSString *)path {
-
- NSString *anonymizedProcessPath = [NSString string];
-
- if (([path length] > 0) && [path hasPrefix:@"/Users/"]) {
- NSError *error = nil;
- NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(/Users/[^/]+/)" options:0 error:&error];
- anonymizedProcessPath = [regex stringByReplacingMatchesInString:path options:0 range:NSMakeRange(0, [path length]) withTemplate:@"/Users/USER/"];
- if (error) {
- BITHockeyLogError(@"ERROR: String replacing failed - %@", error.localizedDescription);
- }
- }
- else if(([path length] > 0) && (![path containsString:@"Users"])) {
- return path;
- }
- return anonymizedProcessPath;
-}
-
-@end
-
-#endif /* HOCKEYSDK_FEATURE_CRASH_REPORTER */
diff --git a/submodules/HockeySDK-iOS/Classes/BITCrashReportTextFormatterPrivate.h b/submodules/HockeySDK-iOS/Classes/BITCrashReportTextFormatterPrivate.h
deleted file mode 100644
index 5b53c4f231..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITCrashReportTextFormatterPrivate.h
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// BITCrashReportTextFormatterPrivate.h
-// HockeySDK
-//
-// Created by Lukas Spieß on 27/01/16.
-//
-//
-
-#import "BITCrashReportTextFormatter.h"
-
-#ifndef BITCrashReportTextFormatterPrivate_h
-#define BITCrashReportTextFormatterPrivate_h
-
-@interface BITCrashReportTextFormatter ()
-
-+ (NSString *)anonymizedPathFromPath:(NSString *)path;
-
-@end
-
-#endif /* BITCrashReportTextFormatterPrivate_h */
diff --git a/submodules/HockeySDK-iOS/Classes/BITData.h b/submodules/HockeySDK-iOS/Classes/BITData.h
deleted file mode 100644
index 05147d6b95..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITData.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#import "BITBase.h"
-@class BITTelemetryData;
-
-@interface BITData : BITBase
-
-@property (nonatomic, strong) BITTelemetryData *baseData;
-
-- (instancetype)initWithCoder:(NSCoder *)coder;
-
-- (void)encodeWithCoder:(NSCoder *)coder;
-
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITData.m b/submodules/HockeySDK-iOS/Classes/BITData.m
deleted file mode 100644
index 958e6ac9aa..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITData.m
+++ /dev/null
@@ -1,39 +0,0 @@
-#import "BITData.h"
-#import "BITHockeyLogger.h"
-
-/// Data contract class for type Data.
-@implementation BITData
-
-///
-/// Adds all members of this class to a dictionary
-/// @returns dictionary to which the members of this class will be added.
-///
-- (NSDictionary *)serializeToDictionary {
- NSMutableDictionary *dict = [super serializeToDictionary].mutableCopy;
- NSDictionary *baseDataDict = [self.baseData serializeToDictionary];
- if ([NSJSONSerialization isValidJSONObject:baseDataDict]) {
- [dict setObject:baseDataDict forKey:@"baseData"];
- } else {
- BITHockeyLogError(@"[HockeySDK] Some of the telemetry data was not NSJSONSerialization compatible and could not be serialized!");
- }
- return dict;
-}
-
-#pragma mark - NSCoding
-
-- (instancetype)initWithCoder:(NSCoder *)coder {
- self = [super initWithCoder:coder];
- if(self) {
- _baseData = [coder decodeObjectForKey:@"self.baseData"];
- }
-
- return self;
-}
-
-- (void)encodeWithCoder:(NSCoder *)coder {
- [super encodeWithCoder:coder];
- [coder encodeObject:self.baseData forKey:@"self.baseData"];
-}
-
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITDevice.h b/submodules/HockeySDK-iOS/Classes/BITDevice.h
deleted file mode 100755
index 95fa4d52af..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITDevice.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#import "BITTelemetryObject.h"
-
-@interface BITDevice : BITTelemetryObject
-
-@property (nonatomic, copy) NSString *deviceId;
-@property (nonatomic, copy) NSString *ip;
-@property (nonatomic, copy) NSString *language;
-@property (nonatomic, copy) NSString *locale;
-@property (nonatomic, copy) NSString *machineName;
-@property (nonatomic, copy) NSString *model;
-@property (nonatomic, copy) NSString *network;
-@property (nonatomic, copy) NSString *networkName;
-@property (nonatomic, copy) NSString *oemName;
-@property (nonatomic, copy) NSString *os;
-@property (nonatomic, copy) NSString *osVersion;
-@property (nonatomic, copy) NSString *roleInstance;
-@property (nonatomic, copy) NSString *roleName;
-@property (nonatomic, copy) NSString *screenResolution;
-@property (nonatomic, copy) NSString *type;
-@property (nonatomic, copy) NSString *vmName;
-
-- (instancetype)initWithCoder:(NSCoder *)coder;
-
-- (void)encodeWithCoder:(NSCoder *)coder;
-
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITDevice.m b/submodules/HockeySDK-iOS/Classes/BITDevice.m
deleted file mode 100755
index 54eb987a74..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITDevice.m
+++ /dev/null
@@ -1,110 +0,0 @@
-#import "BITDevice.h"
-
-/// Data contract class for type Device.
-@implementation BITDevice
-
-///
-/// Adds all members of this class to a dictionary
-/// @returns dictionary to which the members of this class will be added.
-///
-- (NSDictionary *)serializeToDictionary {
- NSMutableDictionary *dict = [super serializeToDictionary].mutableCopy;
- if (self.deviceId != nil) {
- [dict setObject:self.deviceId forKey:@"ai.device.id"];
- }
- if (self.ip != nil) {
- [dict setObject:self.ip forKey:@"ai.device.ip"];
- }
- if (self.language != nil) {
- [dict setObject:self.language forKey:@"ai.device.language"];
- }
- if (self.locale != nil) {
- [dict setObject:self.locale forKey:@"ai.device.locale"];
- }
- if (self.model != nil) {
- [dict setObject:self.model forKey:@"ai.device.model"];
- }
- if (self.network != nil) {
- [dict setObject:self.network forKey:@"ai.device.network"];
- }
- if(self.networkName != nil) {
- [dict setObject:self.networkName forKey:@"ai.device.networkName"];
- }
- if (self.oemName != nil) {
- [dict setObject:self.oemName forKey:@"ai.device.oemName"];
- }
- if (self.os != nil) {
- [dict setObject:self.os forKey:@"ai.device.os"];
- }
- if (self.osVersion != nil) {
- [dict setObject:self.osVersion forKey:@"ai.device.osVersion"];
- }
- if (self.roleInstance != nil) {
- [dict setObject:self.roleInstance forKey:@"ai.device.roleInstance"];
- }
- if (self.roleName != nil) {
- [dict setObject:self.roleName forKey:@"ai.device.roleName"];
- }
- if (self.screenResolution != nil) {
- [dict setObject:self.screenResolution forKey:@"ai.device.screenResolution"];
- }
- if (self.type != nil) {
- [dict setObject:self.type forKey:@"ai.device.type"];
- }
- if (self.machineName != nil) {
- [dict setObject:self.machineName forKey:@"ai.device.machineName"];
- }
- if(self.vmName != nil) {
- [dict setObject:self.vmName forKey:@"ai.device.vmName"];
- }
- return dict;
-}
-
-#pragma mark - NSCoding
-
-- (instancetype)initWithCoder:(NSCoder *)coder {
- self = [super init];
- if(self) {
- _deviceId = [coder decodeObjectForKey:@"self.deviceId"];
- _ip = [coder decodeObjectForKey:@"self.ip"];
- _language = [coder decodeObjectForKey:@"self.language"];
- _locale = [coder decodeObjectForKey:@"self.locale"];
- _model = [coder decodeObjectForKey:@"self.model"];
- _network = [coder decodeObjectForKey:@"self.network"];
- _oemName = [coder decodeObjectForKey:@"self.oemName"];
- _os = [coder decodeObjectForKey:@"self.os"];
- _osVersion = [coder decodeObjectForKey:@"self.osVersion"];
- _roleInstance = [coder decodeObjectForKey:@"self.roleInstance"];
- _roleName = [coder decodeObjectForKey:@"self.roleName"];
- _screenResolution = [coder decodeObjectForKey:@"self.screenResolution"];
- _type = [coder decodeObjectForKey:@"self.type"];
- _machineName = [coder decodeObjectForKey:@"self.machineName"];
- _networkName = [coder decodeObjectForKey:@"self.networkName"];
- _vmName = [coder decodeObjectForKey:@"self.vmName"];
- }
-
- return self;
-}
-
-- (void)encodeWithCoder:(NSCoder *)coder {
- [super encodeWithCoder:coder];
- [coder encodeObject:self.deviceId forKey:@"self.deviceId"];
- [coder encodeObject:self.ip forKey:@"self.ip"];
- [coder encodeObject:self.language forKey:@"self.language"];
- [coder encodeObject:self.locale forKey:@"self.locale"];
- [coder encodeObject:self.model forKey:@"self.model"];
- [coder encodeObject:self.network forKey:@"self.network"];
- [coder encodeObject:self.networkName forKey:@"self.networkName"];
- [coder encodeObject:self.oemName forKey:@"self.oemName"];
- [coder encodeObject:self.os forKey:@"self.os"];
- [coder encodeObject:self.osVersion forKey:@"self.osVersion"];
- [coder encodeObject:self.roleInstance forKey:@"self.roleInstance"];
- [coder encodeObject:self.roleName forKey:@"self.roleName"];
- [coder encodeObject:self.screenResolution forKey:@"self.screenResolution"];
- [coder encodeObject:self.type forKey:@"self.type"];
- [coder encodeObject:self.machineName forKey:@"self.machineName"];
- [coder encodeObject:self.vmName forKey:@"self.vmName"];
-}
-
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITDomain.h b/submodules/HockeySDK-iOS/Classes/BITDomain.h
deleted file mode 100644
index c20cd5a71f..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITDomain.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#import "BITTelemetryData.h"
-
-@interface BITDomain : BITTelemetryData
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITDomain.m b/submodules/HockeySDK-iOS/Classes/BITDomain.m
deleted file mode 100644
index d1d743af04..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITDomain.m
+++ /dev/null
@@ -1,45 +0,0 @@
-#import "BITDomain.h"
-/// Data contract class for type Domain.
-@implementation BITDomain
-@synthesize envelopeTypeName = _envelopeTypeName;
-@synthesize dataTypeName = _dataTypeName;
-@synthesize properties = _properties;
-
-/// Initializes a new instance of the class.
-- (instancetype)init {
- if ((self = [super init])) {
- _envelopeTypeName = @"Microsoft.ApplicationInsights.Domain";
- _dataTypeName = @"Domain";
- }
- return self;
-}
-
-///
-/// Adds all members of this class to a dictionary
-/// @returns dictionary to which the members of this class will be added.
-///
-- (NSDictionary *)serializeToDictionary {
- NSMutableDictionary *dict = [super serializeToDictionary].mutableCopy;
- return dict;
-}
-
-#pragma mark - NSCoding
-
-- (instancetype)initWithCoder:(NSCoder *)coder {
- self = [super initWithCoder:coder];
- if(self) {
- _envelopeTypeName = (NSString *)[coder decodeObjectForKey:@"_envelopeTypeName"];
- _dataTypeName = (NSString *)[coder decodeObjectForKey:@"_dataTypeName"];
- }
-
- return self;
-}
-
-- (void)encodeWithCoder:(NSCoder *)coder {
- [super encodeWithCoder:coder];
- [coder encodeObject:self.envelopeTypeName forKey:@"_envelopeTypeName"];
- [coder encodeObject:self.dataTypeName forKey:@"_dataTypeName"];
-}
-
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITEnvelope.h b/submodules/HockeySDK-iOS/Classes/BITEnvelope.h
deleted file mode 100644
index 5237132215..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITEnvelope.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#import "BITTelemetryObject.h"
-@class BITBase;
-
-@interface BITEnvelope : BITTelemetryObject
-
-@property (nonatomic, copy) NSNumber *version;
-@property (nonatomic, copy) NSString *name;
-@property (nonatomic, copy) NSString *time;
-@property (nonatomic, copy) NSNumber *sampleRate;
-@property (nonatomic, copy) NSString *seq;
-@property (nonatomic, copy) NSString *iKey;
-@property (nonatomic, copy) NSNumber *flags;
-@property (nonatomic, copy) NSString *deviceId;
-@property (nonatomic, copy) NSString *os;
-@property (nonatomic, copy) NSString *osVer;
-@property (nonatomic, copy) NSString *appId;
-@property (nonatomic, copy) NSString *appVer;
-@property (nonatomic, copy) NSString *userId;
-@property (nonatomic, strong) NSDictionary *tags;
-@property (nonatomic, strong) BITBase *data;
-
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITEnvelope.m b/submodules/HockeySDK-iOS/Classes/BITEnvelope.m
deleted file mode 100644
index b833f58f89..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITEnvelope.m
+++ /dev/null
@@ -1,120 +0,0 @@
-#import "BITEnvelope.h"
-#import "BITData.h"
-#import "BITHockeyLogger.h"
-
-/// Data contract class for type Envelope.
-@implementation BITEnvelope
-
-/// Initializes a new instance of the class.
-- (instancetype)init {
- if((self = [super init])) {
- _version = @1;
- _sampleRate = @100.0;
- _tags = [NSDictionary dictionary];
- }
- return self;
-}
-
-///
-/// Adds all members of this class to a dictionary
-/// @returns dictionary to which the members of this class will be added.
-///
-- (NSDictionary *)serializeToDictionary {
- NSMutableDictionary *dict = [super serializeToDictionary].mutableCopy;
- if(self.version != nil) {
- [dict setObject:self.version forKey:@"ver"];
- }
- if(self.name != nil) {
- [dict setObject:self.name forKey:@"name"];
- }
- if(self.time != nil) {
- [dict setObject:self.time forKey:@"time"];
- }
- if(self.sampleRate != nil) {
- [dict setObject:self.sampleRate forKey:@"sampleRate"];
- }
- if(self.seq != nil) {
- [dict setObject:self.seq forKey:@"seq"];
- }
- if(self.iKey != nil) {
- [dict setObject:self.iKey forKey:@"iKey"];
- }
- if(self.flags != nil) {
- [dict setObject:self.flags forKey:@"flags"];
- }
- if(self.deviceId != nil) {
- [dict setObject:self.deviceId forKey:@"deviceId"];
- }
- if(self.os != nil) {
- [dict setObject:self.os forKey:@"os"];
- }
- if(self.osVer != nil) {
- [dict setObject:self.osVer forKey:@"osVer"];
- }
- if(self.appId != nil) {
- [dict setObject:self.appId forKey:@"appId"];
- }
- if(self.appVer != nil) {
- [dict setObject:self.appVer forKey:@"appVer"];
- }
- if(self.userId != nil) {
- [dict setObject:self.userId forKey:@"userId"];
- }
- if(self.tags != nil) {
- [dict setObject:self.tags forKey:@"tags"];
- }
-
- NSDictionary *dataDict = [self.data serializeToDictionary];
- if ([NSJSONSerialization isValidJSONObject:dataDict]) {
- [dict setObject:dataDict forKey:@"data"];
- } else {
- BITHockeyLogError(@"[HockeySDK] Some of the telemetry data was not NSJSONSerialization compatible and could not be serialized!");
- }
- return dict;
-}
-
-#pragma mark - NSCoding
-
-- (instancetype)initWithCoder:(NSCoder *)coder {
- self = [super init];
- if(self) {
- _version = [coder decodeObjectForKey:@"self.version"];
- _name = [coder decodeObjectForKey:@"self.name"];
- _time = [coder decodeObjectForKey:@"self.time"];
- _sampleRate = [coder decodeObjectForKey:@"self.sampleRate"];
- _seq = [coder decodeObjectForKey:@"self.seq"];
- _iKey = [coder decodeObjectForKey:@"self.iKey"];
- _flags = [coder decodeObjectForKey:@"self.flags"];
- _deviceId = [coder decodeObjectForKey:@"self.deviceId"];
- _os = [coder decodeObjectForKey:@"self.os"];
- _osVer = [coder decodeObjectForKey:@"self.osVer"];
- _appId = [coder decodeObjectForKey:@"self.appId"];
- _appVer = [coder decodeObjectForKey:@"self.appVer"];
- _userId = [coder decodeObjectForKey:@"self.userId"];
- _tags = [coder decodeObjectForKey:@"self.tags"];
- _data = [coder decodeObjectForKey:@"self.data"];
- }
-
- return self;
-}
-
-- (void)encodeWithCoder:(NSCoder *)coder {
- [coder encodeObject:self.version forKey:@"self.version"];
- [coder encodeObject:self.name forKey:@"self.name"];
- [coder encodeObject:self.time forKey:@"self.time"];
- [coder encodeObject:self.sampleRate forKey:@"self.sampleRate"];
- [coder encodeObject:self.seq forKey:@"self.seq"];
- [coder encodeObject:self.iKey forKey:@"self.iKey"];
- [coder encodeObject:self.flags forKey:@"self.flags"];
- [coder encodeObject:self.deviceId forKey:@"self.deviceId"];
- [coder encodeObject:self.os forKey:@"self.os"];
- [coder encodeObject:self.osVer forKey:@"self.osVer"];
- [coder encodeObject:self.appId forKey:@"self.appId"];
- [coder encodeObject:self.appVer forKey:@"self.appVer"];
- [coder encodeObject:self.userId forKey:@"self.userId"];
- [coder encodeObject:self.tags forKey:@"self.tags"];
- [coder encodeObject:self.data forKey:@"self.data"];
-}
-
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITEventData.h b/submodules/HockeySDK-iOS/Classes/BITEventData.h
deleted file mode 100644
index 50bb133330..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITEventData.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#import "BITDomain.h"
-
-@interface BITEventData : BITDomain
-
-@property (nonatomic, copy, readonly) NSString *envelopeTypeName;
-@property (nonatomic, copy, readonly) NSString *dataTypeName;
-@property (nonatomic, strong) NSDictionary *measurements;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITEventData.m b/submodules/HockeySDK-iOS/Classes/BITEventData.m
deleted file mode 100644
index b5ef6f07c9..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITEventData.m
+++ /dev/null
@@ -1,66 +0,0 @@
-#import "BITEventData.h"
-
-/// Data contract class for type EventData.
-@implementation BITEventData
-@synthesize envelopeTypeName = _envelopeTypeName;
-@synthesize dataTypeName = _dataTypeName;
-@synthesize version = _version;
-@synthesize properties = _properties;
-@synthesize measurements = _measurements;
-
-/// Initializes a new instance of the class.
-- (instancetype)init {
- if ((self = [super init])) {
- _envelopeTypeName = @"Microsoft.ApplicationInsights.Event";
- _dataTypeName = @"EventData";
- _version = @2;
- _properties = [NSDictionary new];
- _measurements = [NSDictionary new];
- }
- return self;
-}
-
-///
-/// Adds all members of this class to a dictionary
-/// @returns dictionary to which the members of this class will be added.
-///
-- (NSDictionary *)serializeToDictionary {
- NSMutableDictionary *dict = [super serializeToDictionary].mutableCopy;
- if (self.name != nil) {
- [dict setObject:self.name forKey:@"name"];
- }
- if (self.properties !=nil) {
- [dict setObject:self.properties forKey:@"properties"];
- }
- if (self.measurements) {
- [dict setObject:self.measurements forKey:@"measurements"];
- }
-
- return dict;
-}
-
-#pragma mark - NSCoding
-
-- (instancetype)initWithCoder:(NSCoder *)coder {
- self = [super initWithCoder:coder];
- if(self) {
- _envelopeTypeName = [coder decodeObjectForKey:@"self.envelopeTypeName"];
- _dataTypeName = [coder decodeObjectForKey:@"self.dataTypeName"];
- _version = (NSNumber *)[coder decodeObjectForKey:@"self.version"];
- _properties = (NSDictionary *)[coder decodeObjectForKey:@"self.properties"];
- _measurements = [coder decodeObjectForKey:@"self.measurements"];
- }
- return self;
-}
-
-- (void)encodeWithCoder:(NSCoder *)coder {
- [super encodeWithCoder:coder];
- [coder encodeObject:self.envelopeTypeName forKey:@"self.envelopeTypeName"];
- [coder encodeObject:self.dataTypeName forKey:@"self.dataTypeName"];
- [coder encodeObject:self.version forKey:@"self.version"];
- [coder encodeObject:self.properties forKey:@"self.properties"];
- [coder encodeObject:self.measurements forKey:@"self.measurements"];
-}
-
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITFeedbackActivity.h b/submodules/HockeySDK-iOS/Classes/BITFeedbackActivity.h
deleted file mode 100644
index 44c08a985c..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITFeedbackActivity.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import
-
-#import "BITFeedbackComposeViewControllerDelegate.h"
-
-/**
- UIActivity subclass allowing to use the feedback interface to share content with the developer
-
- This activity can be added into an UIActivityViewController and it will use the activity data
- objects to prefill the content of `BITFeedbackComposeViewController`.
-
- This can be useful if you present some data that users can not only share but also
- report back to the developer because they have some problems, e.g. webcams not working
- any more.
-
- The activity provide a default title and image that can be further customized
- via `customActivityImage` and `customActivityTitle`.
-
- */
-
-@interface BITFeedbackActivity : UIActivity
-
-///-----------------------------------------------------------------------------
-/// @name BITFeedbackActivity customisation
-///-----------------------------------------------------------------------------
-
-
-/**
- Define the image shown when using `BITFeedbackActivity`
-
- If not set a default icon is being used.
-
- @see customActivityTitle
- */
-@property (nonatomic, strong) UIImage *customActivityImage;
-
-
-/**
- Define the title shown when using `BITFeedbackActivity`
-
- If not set, a default string is shown by using the apps name
- and adding the localized string "Feedback" to it.
-
- @see customActivityImage
- */
-@property (nonatomic, copy) NSString *customActivityTitle;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITFeedbackActivity.m b/submodules/HockeySDK-iOS/Classes/BITFeedbackActivity.m
deleted file mode 100644
index 08e1775062..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITFeedbackActivity.m
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_FEEDBACK
-
-#import "HockeySDKPrivate.h"
-
-#import "BITFeedbackActivity.h"
-
-#import "BITHockeyHelper.h"
-#import "BITFeedbackManagerPrivate.h"
-
-#import "BITHockeyBaseManagerPrivate.h"
-#import "BITHockeyAttachment.h"
-
-
-@interface BITFeedbackActivity()
-
-@property (nonatomic, strong) NSMutableArray *items;
-@property (nonatomic, strong, readwrite) UIViewController *activityViewController;
-
-@end
-
-
-@implementation BITFeedbackActivity
-
-@synthesize activityViewController = _activityViewController;
-
-#pragma mark - NSObject
-
-- (instancetype)init {
- if ((self = [super init])) {
- _customActivityImage = nil;
- _customActivityTitle = nil;
-
- _items = [NSMutableArray array];
- }
-
- return self;
-}
-
-
-
-#pragma mark - UIActivity
-
-- (NSString *)activityType {
- return @"UIActivityTypePostToHockeySDKFeedback";
-}
-
-- (NSString *)activityTitle {
- if (self.customActivityTitle)
- return self.customActivityTitle;
-
- NSString *appName = bit_appName(BITHockeyLocalizedString(@"HockeyFeedbackActivityAppPlaceholder"));
-
- return [NSString stringWithFormat:BITHockeyLocalizedString(@"HockeyFeedbackActivityButtonTitle"), appName];
-}
-
-- (UIImage *)activityImage {
- if (self.customActivityImage)
- return self.customActivityImage;
-
- return bit_imageNamed(@"feedbackActivity.png", BITHOCKEYSDK_BUNDLE);
-}
-
-
-- (BOOL)canPerformWithActivityItems:(NSArray *)activityItems {
- if ([BITHockeyManager sharedHockeyManager].disableFeedbackManager) return NO;
-
- for (UIActivityItemProvider *item in activityItems) {
- if ([item isKindOfClass:[NSString class]]) {
- return YES;
- } else if ([item isKindOfClass:[UIImage class]]) {
- return YES;
- } else if ([item isKindOfClass:[NSData class]]) {
- return YES;
- } else if ([item isKindOfClass:[BITHockeyAttachment class]]) {
- return YES;
- } else if ([item isKindOfClass:[NSURL class]]) {
- return YES;
- }
- }
- return NO;
-}
-
-- (void)prepareWithActivityItems:(NSArray *)activityItems {
- for (id item in activityItems) {
- if ([item isKindOfClass:[NSString class]] ||
- [item isKindOfClass:[UIImage class]] ||
- [item isKindOfClass:[NSData class]] ||
- [item isKindOfClass:[BITHockeyAttachment class]] ||
- [item isKindOfClass:[NSURL class]]) {
- [self.items addObject:item];
- } else {
- BITHockeyLogWarning(@"WARNING: Unknown item type %@", item);
- }
- }
-}
-
-- (UIViewController *)activityViewController {
- if (!_activityViewController) {
- // TODO: return compose controller with activity content added
- BITFeedbackManager *manager = [BITHockeyManager sharedHockeyManager].feedbackManager;
-
- BITFeedbackComposeViewController *composeViewController = [manager feedbackComposeViewController];
- composeViewController.delegate = self;
- [composeViewController prepareWithItems:self.items];
-
- _activityViewController = [manager customNavigationControllerWithRootViewController:composeViewController
- presentationStyle:UIModalPresentationFormSheet];
- _activityViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
- }
- return _activityViewController;
-}
-
-- (void)feedbackComposeViewController:(BITFeedbackComposeViewController *) __unused composeViewController didFinishWithResult:(BITFeedbackComposeResult)composeResult {
- [self activityDidFinish:composeResult == BITFeedbackComposeResultSubmitted];
-}
-
-
-@end
-
-#endif /* HOCKEYSDK_FEATURE_FEEDBACK */
diff --git a/submodules/HockeySDK-iOS/Classes/BITFeedbackComposeViewController.h b/submodules/HockeySDK-iOS/Classes/BITFeedbackComposeViewController.h
deleted file mode 100644
index ec58531894..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITFeedbackComposeViewController.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#import
-
-#import "BITFeedbackComposeViewControllerDelegate.h"
-
-/**
- View controller allowing the user to write and send new feedback
-
- To add this view controller to your own app and push it onto a navigation stack,
- don't create the instance yourself, but use the following code to get a correct instance:
-
- [[BITHockeyManager sharedHockeyManager].feedbackManager feedbackComposeViewController]
-
- To show it modally, use the following code instead:
-
- [[BITHockeyManager sharedHockeyManager].feedbackManager showFeedbackComposeView]
-
- */
-
-@interface BITFeedbackComposeViewController : UIViewController
-
-
-///-----------------------------------------------------------------------------
-/// @name Delegate
-///-----------------------------------------------------------------------------
-
-
-/**
- Sets the `BITFeedbackComposeViewControllerDelegate` delegate.
-
- The delegate is automatically set by using `[BITHockeyManager setDelegate:]`. You
- should not need to set this delegate individually.
-
- @see [BITHockeyManager setDelegate:]
- */
-@property (nonatomic, weak) id delegate;
-
-
-///-----------------------------------------------------------------------------
-/// @name Presetting content
-///-----------------------------------------------------------------------------
-
-
-/**
- Don't show the option to add images from the photo library
-
- This is helpful if your application is landscape only, since the system UI for
- selecting an image from the photo library is portrait only
- */
-@property (nonatomic) BOOL hideImageAttachmentButton;
-
-/**
- An array of data objects that should be used to prefill the compose view content
-
- The following data object classes are currently supported:
- - NSString
- - NSURL
- - UIImage
- - NSData
- - `BITHockeyAttachment`
-
- These are automatically concatenated to one text string, while any images and NSData
- objects are added as attachments to the feedback.
-
- @param items Array of data objects to prefill the feedback text message.
- */
-- (void)prepareWithItems:(NSArray *)items;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITFeedbackComposeViewController.m b/submodules/HockeySDK-iOS/Classes/BITFeedbackComposeViewController.m
deleted file mode 100644
index 49dfc46699..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITFeedbackComposeViewController.m
+++ /dev/null
@@ -1,690 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_FEEDBACK
-
-#import "HockeySDKPrivate.h"
-
-#import "BITFeedbackManagerPrivate.h"
-#import "BITFeedbackMessageAttachment.h"
-#import "BITFeedbackComposeViewController.h"
-#import "BITFeedbackUserDataViewController.h"
-
-#import "BITHockeyBaseManagerPrivate.h"
-
-#import "BITHockeyHelper.h"
-
-#import "BITImageAnnotationViewController.h"
-#import "BITHockeyAttachment.h"
-
-@interface BITFeedbackComposeViewController () {
-}
-
-@property (nonatomic, weak) BITFeedbackManager *manager;
-@property (nonatomic, strong) UITextView *textView;
-@property (nonatomic, strong) UIView *contentViewContainer;
-@property (nonatomic, strong) UIScrollView *attachmentScrollView;
-@property (nonatomic, strong) NSMutableArray *attachmentScrollViewImageViews;
-
-@property (nonatomic, strong) UIButton *addPhotoButton;
-
-@property (nonatomic, copy) NSString *text;
-
-@property (nonatomic, strong) NSMutableArray *attachments;
-@property (nonatomic, strong) NSMutableArray *imageAttachments;
-
-@property (nonatomic, strong) UIView *textAccessoryView;
-@property (nonatomic) NSInteger selectedAttachmentIndex;
-@property (nonatomic, strong) UITapGestureRecognizer *tapRecognizer;
-
-@property (nonatomic) BOOL blockUserDataScreen;
-@property (nonatomic) BOOL actionSheetVisible;
-
-/**
- * Workaround for UIImagePickerController bug.
- * The statusBar shows up when the UIImagePickerController opens.
- * The status bar does not disappear again when the UIImagePickerController is dismissed.
- * Therefore store the state when UIImagePickerController is shown and restore when viewWillAppear gets called.
- */
-@property (nonatomic, strong) NSNumber *isStatusBarHiddenBeforeShowingPhotoPicker;
-
-@end
-
-
-@implementation BITFeedbackComposeViewController
-
-
-#pragma mark - NSObject
-
-- (instancetype)init {
- self = [super init];
- if (self) {
- _blockUserDataScreen = NO;
- _actionSheetVisible = NO;
- _delegate = nil;
- _manager = [BITHockeyManager sharedHockeyManager].feedbackManager;
- _attachments = [NSMutableArray new];
- _imageAttachments = [NSMutableArray new];
- _attachmentScrollViewImageViews = [NSMutableArray new];
- _tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(scrollViewTapped:)];
- [_attachmentScrollView addGestureRecognizer:self.tapRecognizer];
-
- _text = nil;
- }
-
- return self;
-}
-
-
-#pragma mark - Public
-
-- (void)prepareWithItems:(NSArray *)items {
- for (id item in items) {
- if ([item isKindOfClass:[NSString class]]) {
- self.text = [(self.text ? self.text : @"") stringByAppendingFormat:@"%@%@", (self.text ? @" " : @""), item];
- } else if ([item isKindOfClass:[NSURL class]]) {
- self.text = [(self.text ? self.text : @"") stringByAppendingFormat:@"%@%@", (self.text ? @" " : @""), [(NSURL *)item absoluteString]];
- } else if ([item isKindOfClass:[UIImage class]]) {
- UIImage *image = item;
- BITFeedbackMessageAttachment *attachment = [BITFeedbackMessageAttachment attachmentWithData:UIImageJPEGRepresentation(image, (CGFloat)0.7) contentType:@"image/jpeg"];
- attachment.originalFilename = [NSString stringWithFormat:@"Image_%li.jpg", (unsigned long)[self.attachments count]];
- [self.attachments addObject:attachment];
- [self.imageAttachments addObject:attachment];
- } else if ([item isKindOfClass:[NSData class]]) {
- BITFeedbackMessageAttachment *attachment = [BITFeedbackMessageAttachment attachmentWithData:item contentType:@"application/octet-stream"];
- attachment.originalFilename = [NSString stringWithFormat:@"Attachment_%li.data", (unsigned long)[self.attachments count]];
- [self.attachments addObject:attachment];
- } else if ([item isKindOfClass:[BITHockeyAttachment class]]) {
- BITHockeyAttachment *sourceAttachment = (BITHockeyAttachment *)item;
-
- if (!sourceAttachment.hockeyAttachmentData) {
- BITHockeyLogDebug(@"BITHockeyAttachment instance doesn't contain any data.");
- continue;
- }
-
- NSString *filename = [NSString stringWithFormat:@"Attachment_%li.data", (unsigned long)[self.attachments count]];
- if (sourceAttachment.filename) {
- filename = sourceAttachment.filename;
- }
-
- BITFeedbackMessageAttachment *attachment = [BITFeedbackMessageAttachment attachmentWithData:sourceAttachment.hockeyAttachmentData contentType:sourceAttachment.contentType];
- attachment.originalFilename = filename;
- [self.attachments addObject:attachment];
- } else {
- BITHockeyLogWarning(@"WARNING: Unknown item type %@", item);
- }
- }
-}
-
-
-#pragma mark - Keyboard
-
-- (void)keyboardWasShown:(NSNotification*)aNotification {
- NSDictionary* info = [aNotification userInfo];
- CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
-
- BOOL isPortraitOrientation = UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]);
-
- CGRect frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
- if (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) {
- frame.size.height -= kbSize.height;
- } else {
- CGSize windowSize = [[UIScreen mainScreen] bounds].size;
- CGFloat windowHeight = windowSize.height - 20;
- CGFloat navBarHeight = self.navigationController.navigationBar.frame.size.height;
-
- if (isPortraitOrientation) {
- frame.size.height = windowHeight - navBarHeight - kbSize.height;
- } else {
- windowHeight = windowSize.height - 20;
- CGFloat modalGap = 0.0;
- if (windowHeight - kbSize.height < self.view.bounds.size.height) {
- modalGap = 30;
- } else {
- modalGap = (windowHeight - self.view.bounds.size.height) / 2;
- }
- frame.size.height = windowSize.height - navBarHeight - modalGap - kbSize.height;
- }
- }
- [self.contentViewContainer setFrame:frame];
-
- [self performSelector:@selector(refreshAttachmentScrollview) withObject:nil afterDelay:0.0];
-}
-
-- (void)keyboardWillBeHidden:(NSNotification*) __unused aNotification {
- CGRect frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
- [self.contentViewContainer setFrame:frame];
-}
-
-
-#pragma mark - View lifecycle
-
-- (void)viewDidLoad {
- [super viewDidLoad];
-
- self.title = BITHockeyLocalizedString(@"HockeyFeedbackComposeTitle");
- self.view.backgroundColor = [UIColor whiteColor];
-
- // Do any additional setup after loading the view.
- self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
- target:self
- action:@selector(dismissAction:)];
- self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackComposeSend")
- style:UIBarButtonItemStyleDone
- target:self
- action:@selector(sendAction:)];
-
- // Container that contains both the textfield and eventually the photo scroll view on the right side
- self.contentViewContainer = [[UIView alloc] initWithFrame:self.view.bounds];
- self.contentViewContainer.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
-
- [self.view addSubview:self.contentViewContainer];
-
- // message input textfield
- self.textView = [[UITextView alloc] initWithFrame:self.view.bounds];
- self.textView.font = [UIFont systemFontOfSize:17];
- self.textView.delegate = self;
- self.textView.backgroundColor = [UIColor whiteColor];
- self.textView.returnKeyType = UIReturnKeyDefault;
- self.textView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
- self.textView.accessibilityHint = BITHockeyLocalizedString(@"HockeyAccessibilityHintRequired");
-
- [self.contentViewContainer addSubview:self.textView];
-
- // Add Photo Button + Container that's displayed above the keyboard.
- if([BITHockeyHelper isPhotoAccessPossible]) {
- self.textAccessoryView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 44)];
- self.textAccessoryView.backgroundColor = [UIColor colorWithRed:(CGFloat)0.9 green:(CGFloat)0.9 blue:(CGFloat)0.9 alpha:(CGFloat)1.0];
-
- self.addPhotoButton = [UIButton buttonWithType:UIButtonTypeCustom];
- [self.addPhotoButton setTitle:BITHockeyLocalizedString(@"HockeyFeedbackComposeAttachmentAddImage") forState:UIControlStateNormal];
- [self.addPhotoButton setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal];
- [self.addPhotoButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateDisabled];
- self.addPhotoButton.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 44);
- [self.addPhotoButton addTarget:self action:@selector(addPhotoAction:) forControlEvents:UIControlEventTouchUpInside];
- self.addPhotoButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin;
- [self.textAccessoryView addSubview:self.addPhotoButton];
- }
-
-
-
- if (!self.hideImageAttachmentButton) {
- self.textView.inputAccessoryView = self.textAccessoryView;
- }
-
- // This could be a subclass, yet
- self.attachmentScrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
- self.attachmentScrollView.scrollEnabled = YES;
- self.attachmentScrollView.bounces = YES;
- self.attachmentScrollView.autoresizesSubviews = NO;
- self.attachmentScrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleRightMargin;
-#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0
- if (@available(iOS 11.0, *)) {
- self.attachmentScrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentAlways;
- }
-#endif
- [self.contentViewContainer addSubview:self.attachmentScrollView];
-}
-
-- (void)viewWillAppear:(BOOL)animated {
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(keyboardWasShown:)
- name:UIKeyboardDidShowNotification object:nil];
-
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(keyboardWillBeHidden:)
- name:UIKeyboardWillHideNotification object:nil];
-
- self.manager.currentFeedbackComposeViewController = self;
-
- [super viewWillAppear:animated];
-
- if (self.text && self.textView.text.length == 0) {
- self.textView.text = self.text;
- }
-
- if (self.isStatusBarHiddenBeforeShowingPhotoPicker) {
- [self setNeedsStatusBarAppearanceUpdate];
- }
-
- self.isStatusBarHiddenBeforeShowingPhotoPicker = nil;
-
- [self updateBarButtonState];
-}
-
-- (BOOL)prefersStatusBarHidden {
- if (self.isStatusBarHiddenBeforeShowingPhotoPicker) {
- return self.isStatusBarHiddenBeforeShowingPhotoPicker.boolValue;
- }
-
- return [super prefersStatusBarHidden];
-}
-
-- (void)viewDidAppear:(BOOL)animated {
- [super viewDidAppear:animated];
- BITFeedbackManager *strongManager = self.manager;
- if ([strongManager askManualUserDataAvailable] &&
- ([strongManager requireManualUserDataMissing] ||
- ![strongManager didAskUserData])
- ) {
- if (!self.blockUserDataScreen)
- [self setUserDataAction];
- } else {
- // Invoke delayed to fix iOS 7 iPad landscape bug, where this view will be moved if not called delayed
- [self.textView performSelector:@selector(becomeFirstResponder) withObject:nil afterDelay:0.0];
- [self refreshAttachmentScrollview];
- }
-}
-
-- (void)viewWillDisappear:(BOOL)animated {
- [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil];
- [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
-
- self.manager.currentFeedbackComposeViewController = nil;
-
- [super viewWillDisappear:animated];
-}
-
-- (void)viewDidDisappear:(BOOL)animated {
- [super viewDidDisappear:animated];
-}
-
-- (void)refreshAttachmentScrollview {
- CGFloat scrollViewWidth = 0;
-
- if (self.imageAttachments.count){
- scrollViewWidth = 100;
- }
-
- CGRect textViewFrame = self.textView.frame;
-
- CGRect scrollViewFrame = self.attachmentScrollView.frame;
-
- BOOL alreadySetup = CGRectGetWidth(scrollViewFrame) > 0;
-
- if (alreadySetup && self.imageAttachments.count == 0) {
- textViewFrame.size.width += 100;
- self.textView.frame = textViewFrame;
- scrollViewFrame.size.width = 0;
- self.attachmentScrollView.frame = scrollViewFrame;
- return;
- }
-
- if (!alreadySetup) {
- CGSize tempTextViewSize = CGSizeMake(self.contentViewContainer.frame.size.width, self.contentViewContainer.frame.size.height);
- textViewFrame.size = tempTextViewSize;
- textViewFrame.size.width -= scrollViewWidth;
- // height has to be identical to the textview!
- scrollViewFrame = CGRectMake(CGRectGetMaxX(textViewFrame), self.view.frame.origin.y, scrollViewWidth, CGRectGetHeight(self.textView.bounds));
- self.textView.frame = textViewFrame;
- self.attachmentScrollView.frame = scrollViewFrame;
- self.attachmentScrollView.contentInset = self.textView.contentInset;
- }
-
- if (self.imageAttachments.count > self.attachmentScrollViewImageViews.count){
- NSInteger numberOfViewsToCreate = self.imageAttachments.count - self.attachmentScrollViewImageViews.count;
- for (int i = 0; i 0 ) {
- self.navigationItem.rightBarButtonItem.enabled = YES;
- } else {
- self.navigationItem.rightBarButtonItem.enabled = NO;
- }
-
- if(self.addPhotoButton) {
- if (self.imageAttachments.count > 2){
- [self.addPhotoButton setEnabled:NO];
- } else {
- [self.addPhotoButton setEnabled:YES];
- }
- }
-}
-
-- (void)removeAttachmentScrollView {
- CGRect frame = self.attachmentScrollView.frame;
- frame.size.width = 0;
- self.attachmentScrollView.frame = frame;
-
- frame = self.textView.frame;
- frame.size.width += 100;
- self.textView.frame = frame;
-}
-
-
-#pragma mark - UIViewController Rotation
-
-- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
- return UIInterfaceOrientationMaskAll;
-}
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-implementations"
-- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation) __unused fromInterfaceOrientation {
- [self removeAttachmentScrollView];
-
- [self refreshAttachmentScrollview];
-}
-#pragma clang diagnostic pop
-
-#pragma mark - Private methods
-
-- (void)setUserDataAction {
- BITFeedbackUserDataViewController *userController = [[BITFeedbackUserDataViewController alloc] initWithStyle:UITableViewStyleGrouped];
- userController.delegate = self;
-
- UINavigationController *navController = [self.manager customNavigationControllerWithRootViewController:userController
- presentationStyle:UIModalPresentationFormSheet];
-
- [self presentViewController:navController animated:YES completion:nil];
-}
-
-#pragma mark - Actions
-
-- (void)dismissAction:(id) __unused sender {
- for (BITFeedbackMessageAttachment *attachment in self.attachments){
- [attachment deleteContents];
- }
-
- [self dismissWithResult:BITFeedbackComposeResultCancelled];
-}
-
-- (void)sendAction:(id) __unused sender {
- if ([self.textView isFirstResponder])
- [self.textView resignFirstResponder];
-
- NSString *text = self.textView.text;
-
- [self.manager submitMessageWithText:text andAttachments:self.attachments];
-
- [self dismissWithResult:BITFeedbackComposeResultSubmitted];
-}
-
-- (void)dismissWithResult:(BITFeedbackComposeResult) result {
- id strongDelegate = self.delegate;
- if([strongDelegate respondsToSelector:@selector(feedbackComposeViewController:didFinishWithResult:)]) {
- [strongDelegate feedbackComposeViewController:self didFinishWithResult:result];
- } else {
- [self dismissViewControllerAnimated:YES completion:nil];
- }
-}
-
-- (void)addPhotoAction:(id) __unused sender {
- if (self.actionSheetVisible) return;
-
- self.isStatusBarHiddenBeforeShowingPhotoPicker = @([[UIApplication sharedApplication] isStatusBarHidden]);
-
- // add photo.
- UIImagePickerController *pickerController = [[UIImagePickerController alloc] init];
- pickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
- pickerController.delegate = self;
- pickerController.editing = NO;
- pickerController.navigationBar.barStyle = self.manager.barStyle;
- [self presentViewController:pickerController animated:YES completion:nil];
-}
-
-- (void)scrollViewTapped:(id) __unused unused {
- UIMenuController *menuController = [UIMenuController sharedMenuController];
- [menuController setTargetRect:CGRectMake([self.tapRecognizer locationInView:self.view].x, [self.tapRecognizer locationInView:self.view].x, 1, 1) inView:self.view];
- [menuController setMenuVisible:YES animated:YES];
-}
-
-- (void)paste:(id) __unused sender {
-
-}
-
-#pragma mark - UIImagePickerControllerDelegate
-
-- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
- UIImage *pickedImage = info[UIImagePickerControllerOriginalImage];
-
- if (pickedImage){
- NSData *imageData = UIImageJPEGRepresentation(pickedImage, (CGFloat)0.7);
- BITFeedbackMessageAttachment *newAttachment = [BITFeedbackMessageAttachment attachmentWithData:imageData contentType:@"image/jpeg"];
- NSURL *imagePath = [info objectForKey:@"UIImagePickerControllerReferenceURL"];
- NSString *imageName = [imagePath lastPathComponent];
- newAttachment.originalFilename = imageName;
- [self.attachments addObject:newAttachment];
- [self.imageAttachments addObject:newAttachment];
- }
-
- [picker dismissViewControllerAnimated:YES completion:nil];
-}
-
-- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
- [picker dismissViewControllerAnimated:YES completion:nil];
-}
-
-- (void)imageButtonAction:(UIButton *)sender {
- // determine the index of the feedback
- NSInteger index = [self.attachmentScrollViewImageViews indexOfObject:sender];
-
- self.selectedAttachmentIndex = (self.attachmentScrollViewImageViews.count - index - 1);
- /* We won't use this for now until we have a more robust solution for displaying UIAlertController
- // requires iOS 8
- id uialertcontrollerClass = NSClassFromString(@"UIAlertController");
- if (uialertcontrollerClass) {
- __weak typeof(self) weakSelf = self;
-
- UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil
- message:nil
- preferredStyle:UIAlertControllerStyleActionSheet];
-
-
- UIAlertAction *cancelAction = [BITAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackComposeAttachmentCancel")
- style:UIAlertActionStyleCancel
- handler:^(UIAlertAction * action) {
- typeof(self) strongSelf = weakSelf;
- [strongSelf cancelAction];
- _actionSheetVisible = NO;
- }];
-
- [alertController addAction:cancelAction];
-
- UIAlertAction *editAction = [BITAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackComposeAttachmentEdit")
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction * action) {
- typeof(self) strongSelf = weakSelf;
- [strongSelf editAction];
- _actionSheetVisible = NO;
- }];
-
- [alertController addAction:editAction];
-
- UIAlertAction *deleteAction = [BITAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackComposeAttachmentDelete")
- style:UIAlertActionStyleDestructive
- handler:^(UIAlertAction * action) {
- typeof(self) strongSelf = weakSelf;
- [strongSelf deleteAction];
- _actionSheetVisible = NO;
- }];
-
- [alertController addAction:deleteAction];
-
- [self presentViewController:alertController animated:YES completion:nil];
- } else {
- */
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle: nil
- delegate: self
- cancelButtonTitle: BITHockeyLocalizedString(@"HockeyFeedbackComposeAttachmentCancel")
- destructiveButtonTitle: BITHockeyLocalizedString(@"HockeyFeedbackComposeAttachmentDelete")
- otherButtonTitles: BITHockeyLocalizedString(@"HockeyFeedbackComposeAttachmentEdit"), nil];
-
- [actionSheet showFromRect: sender.frame inView: self.attachmentScrollView animated: YES];
-#pragma clang diagnostic push
- /*}*/
-
- self.actionSheetVisible = YES;
- if ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || ([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){9,0,0}])) {
- [self.textView resignFirstResponder];
- }
-}
-
-
-#pragma mark - BITFeedbackUserDataDelegate
-
-- (void)userDataUpdateCancelled {
- self.blockUserDataScreen = YES;
-
- if ([self.manager requireManualUserDataMissing]) {
- if ([self.navigationController respondsToSelector:@selector(dismissViewControllerAnimated:completion:)]) {
- [self.navigationController dismissViewControllerAnimated:YES
- completion:^(void) {
- [self dismissViewControllerAnimated:YES completion:nil];
- }];
- } else {
- [self dismissViewControllerAnimated:YES completion:nil];
- [self performSelector:@selector(dismissAction:) withObject:nil afterDelay:0.4];
- }
- } else {
- [self.navigationController dismissViewControllerAnimated:YES completion:nil];
- }
-}
-
-- (void)userDataUpdateFinished {
- [self.manager saveMessages];
-
- [self.navigationController dismissViewControllerAnimated:YES completion:nil];
-}
-
-
-#pragma mark - UITextViewDelegate
-
-- (void)textViewDidChange:(UITextView *) __unused textView {
- [self updateBarButtonState];
-}
-
-
-#pragma mark - UIActionSheet Delegate
-
-- (void)deleteAction {
- if (self.selectedAttachmentIndex != NSNotFound){
- UIButton *imageButton = self.attachmentScrollViewImageViews[self.selectedAttachmentIndex];
- BITFeedbackMessageAttachment *attachment = self.imageAttachments[self.selectedAttachmentIndex];
- [attachment deleteContents]; // mandatory call to delete the files associated.
- [self.imageAttachments removeObject:attachment];
- [self.attachments removeObject:attachment];
- [imageButton removeFromSuperview];
- [self.attachmentScrollViewImageViews removeObject:imageButton];
- }
- self.selectedAttachmentIndex = NSNotFound;
-
- [self refreshAttachmentScrollview];
-
- if ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || ([[NSProcessInfo processInfo] respondsToSelector:@selector(isOperatingSystemAtLeastVersion:)] && [[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){9,0,0}])) {
- [self.textView becomeFirstResponder];
- }
-}
-
-- (void)editAction {
- if (self.selectedAttachmentIndex != NSNotFound){
- BITFeedbackMessageAttachment *attachment = self.imageAttachments[self.selectedAttachmentIndex];
- BITImageAnnotationViewController *annotationEditor = [[BITImageAnnotationViewController alloc ] init];
- annotationEditor.delegate = self;
- UINavigationController *navController = [self.manager customNavigationControllerWithRootViewController:annotationEditor presentationStyle:UIModalPresentationFullScreen];
- annotationEditor.image = attachment.imageRepresentation;
- [self presentViewController:navController animated:YES completion:nil];
- }
-}
-
-- (void)cancelAction {
- if ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || ([[NSProcessInfo processInfo] respondsToSelector:@selector(isOperatingSystemAtLeastVersion:)] && [[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){9,0,0}])) {
- [self.textView becomeFirstResponder];
- }
-}
-
-- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
- if (buttonIndex == [actionSheet destructiveButtonIndex]) {
- [self deleteAction];
- } else if (buttonIndex != [actionSheet cancelButtonIndex]) {
- [self editAction];
- } else {
- [self cancelAction];
- }
- self.actionSheetVisible = NO;
-}
-
-
-#pragma mark - Image Annotation Delegate
-
-- (void)annotationController:(BITImageAnnotationViewController *) __unused annotationController didFinishWithImage:(UIImage *)image {
- if (self.selectedAttachmentIndex != NSNotFound){
- BITFeedbackMessageAttachment *attachment = self.imageAttachments[self.selectedAttachmentIndex];
- [attachment replaceData:UIImageJPEGRepresentation(image, (CGFloat)0.7)];
- }
-
- self.selectedAttachmentIndex = NSNotFound;
-}
-
-- (void)annotationControllerDidCancel:(BITImageAnnotationViewController *) __unused annotationController {
- self.selectedAttachmentIndex = NSNotFound;
-}
-
-@end
-
-#endif /* HOCKEYSDK_FEATURE_FEEDBACK */
diff --git a/submodules/HockeySDK-iOS/Classes/BITFeedbackComposeViewControllerDelegate.h b/submodules/HockeySDK-iOS/Classes/BITFeedbackComposeViewControllerDelegate.h
deleted file mode 100644
index 99bac6cf84..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITFeedbackComposeViewControllerDelegate.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import
-
-#import "HockeySDKNullability.h"
-NS_ASSUME_NONNULL_BEGIN
-
-/**
- * The users action when composing a message
- */
-typedef NS_ENUM(NSUInteger, BITFeedbackComposeResult) {
- /**
- * user hit cancel
- */
- BITFeedbackComposeResultCancelled,
- /**
- * user hit submit
- */
- BITFeedbackComposeResultSubmitted,
-};
-
-@class BITFeedbackComposeViewController;
-
-/**
- * The `BITFeedbackComposeViewControllerDelegate` formal protocol defines methods further configuring
- * the behaviour of `BITFeedbackComposeViewController`.
- */
-
-@protocol BITFeedbackComposeViewControllerDelegate
-
-@optional
-
-///-----------------------------------------------------------------------------
-/// @name View Controller Management
-///-----------------------------------------------------------------------------
-
-/**
- * Invoked once the compose screen is finished via send or cancel
- *
- * If this is implemented, it's the responsibility of this method to dismiss the presented
- * `BITFeedbackComposeViewController`
- *
- * @param composeViewController The `BITFeedbackComposeViewController` instance invoking this delegate
- * @param composeResult The user action the lead to closing the compose view
- */
-- (void)feedbackComposeViewController:(BITFeedbackComposeViewController *)composeViewController
- didFinishWithResult:(BITFeedbackComposeResult) composeResult;
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/submodules/HockeySDK-iOS/Classes/BITFeedbackListViewCell.h b/submodules/HockeySDK-iOS/Classes/BITFeedbackListViewCell.h
deleted file mode 100644
index f8947a50ec..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITFeedbackListViewCell.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#import
-#import "BITFeedbackMessage.h"
-#import "BITAttributedLabel.h"
-
-@class BITFeedbackMessageAttachment;
-
-@protocol BITFeedbackListViewCellDelegate
-
-- (void)listCell:(id)cell didSelectAttachment:(BITFeedbackMessageAttachment *)attachment;
-
-@end
-
-/**
- * Cell background style
- */
-typedef NS_ENUM(NSUInteger, BITFeedbackListViewCellBackgroundStyle) {
- /**
- * For even rows
- */
- BITFeedbackListViewCellBackgroundStyleNormal = 0,
- /**
- * For uneven rows
- */
- BITFeedbackListViewCellBackgroundStyleAlternate = 1
-};
-
-
-@interface BITFeedbackListViewCell : UITableViewCell
-
-@property (nonatomic, strong) BITFeedbackMessage *message;
-
-@property (nonatomic) BITFeedbackListViewCellBackgroundStyle backgroundStyle;
-
-@property (nonatomic, strong) BITAttributedLabel *labelText;
-
-@property (nonatomic, weak) id delegate;
-
-+ (CGFloat) heightForRowWithMessage:(BITFeedbackMessage *)message tableViewWidth:(CGFloat)width;
-
-- (void)setAttachments:(NSArray *)attachments;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITFeedbackListViewCell.m b/submodules/HockeySDK-iOS/Classes/BITFeedbackListViewCell.m
deleted file mode 100644
index 59d661ad37..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITFeedbackListViewCell.m
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_FEEDBACK
-
-#import "HockeySDKPrivate.h"
-
-#import "BITFeedbackListViewCell.h"
-#import "BITFeedbackMessageAttachment.h"
-#import "BITActivityIndicatorButton.h"
-#import "BITFeedbackManagerPrivate.h"
-
-#import
-
-#define BACKGROUNDCOLOR_DEFAULT_OS7 BIT_RGBCOLOR(255, 255, 255)
-#define BACKGROUNDCOLOR_ALTERNATE_OS7 BIT_RGBCOLOR(255, 255, 255)
-
-#define TEXTCOLOR_TITLE BIT_RGBCOLOR(75, 75, 75)
-
-#define TEXTCOLOR_DEFAULT BIT_RGBCOLOR(25, 25, 25)
-#define TEXTCOLOR_PENDING BIT_RGBCOLOR(75, 75, 75)
-
-#define TITLE_FONTSIZE 12
-#define TEXT_FONTSIZE 15
-
-#define FRAME_SIDE_BORDER 10
-#define FRAME_TOP_BORDER 8
-#define FRAME_BOTTOM_BORDER 5
-
-#define LABEL_TITLE_Y 3
-#define LABEL_TITLE_HEIGHT 15
-
-#define LABEL_TEXT_Y 25
-
-#define ATTACHMENT_SIZE 45
-
-
-@interface BITFeedbackListViewCell ()
-
-@property (nonatomic, strong) NSDateFormatter *dateFormatter;
-@property (nonatomic, strong) NSDateFormatter *timeFormatter;
-
-@property (nonatomic, strong) UILabel *labelTitle;
-
-@property (nonatomic, strong) NSMutableArray *attachmentViews;
-
-@property (nonatomic, strong) UIView *accessoryBackgroundView;
-
-@property (nonatomic, strong) id updateAttachmentNotification;
-
-@end
-
-
-@implementation BITFeedbackListViewCell
-
-
-- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
- self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
- if (self) {
- // Initialization code
- _backgroundStyle = BITFeedbackListViewCellBackgroundStyleNormal;
-
- _message = nil;
-
- _dateFormatter = [[NSDateFormatter alloc] init];
- [_dateFormatter setTimeStyle:NSDateFormatterNoStyle];
- [_dateFormatter setDateStyle:NSDateFormatterMediumStyle];
- [_dateFormatter setLocale:[NSLocale currentLocale]];
- [_dateFormatter setDoesRelativeDateFormatting:YES];
-
- _timeFormatter = [[NSDateFormatter alloc] init];
- [_timeFormatter setTimeStyle:NSDateFormatterShortStyle];
- [_timeFormatter setDateStyle:NSDateFormatterNoStyle];
- [_timeFormatter setLocale:[NSLocale currentLocale]];
- [_timeFormatter setDoesRelativeDateFormatting:YES];
-
- _labelTitle = [[UILabel alloc] init];
- _labelTitle.font = [UIFont systemFontOfSize:TITLE_FONTSIZE];
-
- _labelText = [[BITAttributedLabel alloc] initWithFrame:CGRectZero];
- _labelText.font = [UIFont systemFontOfSize:TEXT_FONTSIZE];
- _labelText.numberOfLines = 0;
- _labelText.textAlignment = NSTextAlignmentLeft;
- _labelText.enabledTextCheckingTypes = UIDataDetectorTypeAll;
-
- _attachmentViews = [NSMutableArray new];
- [self registerObservers];
- }
- return self;
-}
-
-- (void)dealloc {
- [self unregisterObservers];
-}
-
-
-#pragma mark - Private
-
-- (void) registerObservers {
- __weak typeof(self) weakSelf = self;
- if (nil == self.updateAttachmentNotification) {
- self.updateAttachmentNotification = [[NSNotificationCenter defaultCenter] addObserverForName:kBITFeedbackUpdateAttachmentThumbnail
- object:nil
- queue:NSOperationQueue.mainQueue
- usingBlock:^(NSNotification *note) {
- typeof(self) strongSelf = weakSelf;
- [strongSelf updateAttachmentFromNotification:note];
- }];
- }
-}
-
-- (void) unregisterObservers {
- if (self.updateAttachmentNotification) {
- [[NSNotificationCenter defaultCenter] removeObserver:self.updateAttachmentNotification];
- self.updateAttachmentNotification = nil;
- }
-}
-
-- (void) updateAttachmentFromNotification:(NSNotification *)note {
- if (!self.message) return;
- if (!self.message.attachments) return;
- if (self.message.attachments.count == 0) return;
- if (!note.object) return;
- if (![note.object isKindOfClass:[BITFeedbackMessageAttachment class]]) return;
-
- BITFeedbackMessageAttachment *attachment = (BITFeedbackMessageAttachment *)note.object;
- if (![self.message.attachments containsObject:attachment]) return;
-
- // The attachment is part of the message used for this cell, so lets update it.
- [self setAttachments:self.message.previewableAttachments];
- [self setNeedsLayout];
-}
-
-- (UIColor *)backgroundColor {
-
- if (self.backgroundStyle == BITFeedbackListViewCellBackgroundStyleNormal) {
- return BACKGROUNDCOLOR_DEFAULT_OS7;
- } else {
- return BACKGROUNDCOLOR_ALTERNATE_OS7;
- }
-}
-
-- (BOOL)isSameDayWithDate1:(NSDate*)date1 date2:(NSDate*)date2 {
- NSCalendar* calendar = [NSCalendar currentCalendar];
-
- unsigned unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
-
- NSDateComponents *dateComponent1 = [calendar components:unitFlags fromDate:date1];
- NSDateComponents *dateComponent2 = [calendar components:unitFlags fromDate:date2];
-
- return ([dateComponent1 day] == [dateComponent2 day] &&
- [dateComponent1 month] == [dateComponent2 month] &&
- [dateComponent1 year] == [dateComponent2 year]);
-}
-
-
-#pragma mark - Layout
-
-+ (CGFloat) heightForRowWithMessage:(BITFeedbackMessage *)message tableViewWidth:(CGFloat)width {
-
- CGFloat baseHeight = [self heightForTextInRowWithMessage:message tableViewWidth:width];
-
- CGFloat attachmentsPerRow = floor(width / (FRAME_SIDE_BORDER + ATTACHMENT_SIZE));
-
- CGFloat calculatedHeight = baseHeight + (FRAME_TOP_BORDER + ATTACHMENT_SIZE) * ceil([message previewableAttachments].count / attachmentsPerRow);
-
- return ceil(calculatedHeight);
-}
-
-
-
-+ (CGFloat) heightForTextInRowWithMessage:(BITFeedbackMessage *)message tableViewWidth:(CGFloat)width {
- CGFloat calculatedHeight;
-
- if ([message.text respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)]) {
- CGRect calculatedRect = [message.text boundingRectWithSize:CGSizeMake(width - (2 * FRAME_SIDE_BORDER), CGFLOAT_MAX)
- options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
- attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:TEXT_FONTSIZE]}
- context:nil];
- calculatedHeight = calculatedRect.size.height + FRAME_TOP_BORDER + LABEL_TEXT_Y + FRAME_BOTTOM_BORDER;
-
- // added to make space for the images.
-
-
- } else {
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- calculatedHeight = [message.text sizeWithFont:[UIFont systemFontOfSize:TEXT_FONTSIZE]
- constrainedToSize:CGSizeMake(width - (2 * FRAME_SIDE_BORDER), CGFLOAT_MAX)
- ].height + FRAME_TOP_BORDER + LABEL_TEXT_Y + FRAME_BOTTOM_BORDER;
-
-#pragma clang diagnostic pop
- }
-
- return ceil(calculatedHeight);
-}
-
-- (void)setAttachments:(NSArray *)attachments {
- for (UIView *view in self.attachmentViews){
- [view removeFromSuperview];
- }
-
- [self.attachmentViews removeAllObjects];
-
- for (BITFeedbackMessageAttachment *attachment in attachments){
- if (attachment.localURL || attachment.sourceURL) {
- BITActivityIndicatorButton *imageView = [BITActivityIndicatorButton buttonWithType:UIButtonTypeCustom];
-
- if (attachment.localURL){
- [imageView setImage:[attachment thumbnailWithSize:CGSizeMake(ATTACHMENT_SIZE, ATTACHMENT_SIZE)] forState:UIControlStateNormal];
- [imageView setShowsActivityIndicator:NO];
- } else {
- [imageView setImage:nil forState:UIControlStateNormal];
- [imageView setShowsActivityIndicator:YES];
- }
- [imageView setContentMode:UIViewContentModeScaleAspectFit];
- [imageView addTarget:self action:@selector(imageButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
-
- [self.attachmentViews addObject:imageView];
- }
- }
-}
-
-
-- (void)layoutSubviews {
- if (!self.accessoryBackgroundView){
- self.accessoryBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 2, self.frame.size.width * 2, self.frame.size.height - 2)];
- self.accessoryBackgroundView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
- self.accessoryBackgroundView.clipsToBounds = YES;
-
- // colors
- self.accessoryBackgroundView.backgroundColor = [self backgroundColor];
- }
-
- if (self.accessoryBackgroundView.superview){
- [self.accessoryBackgroundView removeFromSuperview];
- }
- self.contentView.backgroundColor = [self backgroundColor];
- self.labelTitle.backgroundColor = [self backgroundColor];
- self.labelText.backgroundColor = [self backgroundColor];
-
- self.labelTitle.textColor = TEXTCOLOR_TITLE;
- if (self.message.status == BITFeedbackMessageStatusSendPending || self.message.status == BITFeedbackMessageStatusSendInProgress) {
- [self.labelText setTextColor:TEXTCOLOR_PENDING];
- } else {
- [self.labelText setTextColor:TEXTCOLOR_DEFAULT];
- }
-
- // background for deletion accessory view
-
-
- // header
- NSString *dateString = @"";
- if (self.message.status == BITFeedbackMessageStatusSendPending || self.message.status == BITFeedbackMessageStatusSendInProgress) {
- dateString = BITHockeyLocalizedString(@"Pending");
- } else if (self.message.date) {
- if ([self isSameDayWithDate1:[NSDate date] date2:self.message.date]) {
- dateString = [self.timeFormatter stringFromDate:self.message.date];
- } else {
- dateString = [self.dateFormatter stringFromDate:self.message.date];
- }
- }
- [self.labelTitle setText:dateString];
- [self.labelTitle setFrame:CGRectMake(FRAME_SIDE_BORDER, FRAME_TOP_BORDER + LABEL_TITLE_Y, self.frame.size.width - (2 * FRAME_SIDE_BORDER), LABEL_TITLE_HEIGHT)];
-
- if (self.message.userMessage) {
- self.labelTitle.textAlignment = NSTextAlignmentRight;
- self.labelText.textAlignment = NSTextAlignmentRight;
- } else {
- self.labelTitle.textAlignment = NSTextAlignmentLeft;
- self.labelText.textAlignment = NSTextAlignmentLeft;
- }
-
- [self addSubview:self.labelTitle];
-
- // text
- [self.labelText setText:self.message.text];
- CGSize sizeForTextLabel = CGSizeMake(self.frame.size.width - (2 * FRAME_SIDE_BORDER),
- [[self class] heightForTextInRowWithMessage:self.message tableViewWidth:self.frame.size.width] - LABEL_TEXT_Y - FRAME_BOTTOM_BORDER);
-
- [self.labelText setFrame:CGRectMake(FRAME_SIDE_BORDER, LABEL_TEXT_Y, sizeForTextLabel.width, sizeForTextLabel.height)];
-
- [self addSubview:self.labelText];
-
- CGFloat baseOffsetOfText = CGRectGetMaxY(self.labelText.frame);
-
-
- int i = 0;
-
- CGFloat attachmentsPerRow = floor(self.frame.size.width / (FRAME_SIDE_BORDER + ATTACHMENT_SIZE));
-
- for (BITActivityIndicatorButton *imageButton in self.attachmentViews) {
- imageButton.contentMode = UIViewContentModeScaleAspectFit;
- imageButton.imageView.contentMode = UIViewContentModeScaleAspectFill;
-
- if (!self.message.userMessage) {
- imageButton.frame = CGRectMake(FRAME_SIDE_BORDER + (FRAME_SIDE_BORDER + ATTACHMENT_SIZE) * (i%(int)attachmentsPerRow) , floor(i/attachmentsPerRow)*(FRAME_SIDE_BORDER + ATTACHMENT_SIZE) + baseOffsetOfText , ATTACHMENT_SIZE, ATTACHMENT_SIZE);
- } else {
- imageButton.frame = CGRectMake(self.frame.size.width - FRAME_SIDE_BORDER - ATTACHMENT_SIZE - ((FRAME_SIDE_BORDER + ATTACHMENT_SIZE) * (i%(int)attachmentsPerRow) ), floor(i/attachmentsPerRow)*(FRAME_SIDE_BORDER + ATTACHMENT_SIZE) + baseOffsetOfText , ATTACHMENT_SIZE, ATTACHMENT_SIZE);
- }
-
- if (!imageButton.superview) {
- if (self.accessoryBackgroundView.superview) {
- [self insertSubview:imageButton aboveSubview:self.accessoryBackgroundView];
- } else {
- [self addSubview:imageButton];
- }
- }
-
- i++;
- }
-
- [super layoutSubviews];
-}
-
-- (void)imageButtonPressed:(id)sender {
- id strongDelegate = self.delegate;
- if ([strongDelegate respondsToSelector:@selector(listCell:didSelectAttachment:)]) {
- NSUInteger index = [self.attachmentViews indexOfObject:sender];
- if (index != NSNotFound && [self.message previewableAttachments].count > index) {
- BITFeedbackMessageAttachment *attachment = [self.message previewableAttachments][index];
- [strongDelegate listCell:self didSelectAttachment:attachment];
- }
- }
-}
-
-- (NSString *)accessibilityLabel {
- NSString *messageTime = [self.labelTitle accessibilityLabel];
- NSString *messageText = [self.labelText accessibilityLabel];
- return [NSString stringWithFormat:@"%@, %@", messageTime, messageText];
-}
-
-@end
-
-#endif /* HOCKEYSDK_FEATURE_FEEDBACK */
diff --git a/submodules/HockeySDK-iOS/Classes/BITFeedbackListViewController.h b/submodules/HockeySDK-iOS/Classes/BITFeedbackListViewController.h
deleted file mode 100644
index 62fd91d518..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITFeedbackListViewController.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#import
-#import
-
-#import "BITHockeyBaseViewController.h"
-
-/**
- View controller providing a default interface to manage feedback
-
- The message list interface contains options to locally delete single messages
- by swiping over them, or deleting all messages. This will not delete the messages
- on the server though!
-
- It is also integrates actions to invoke the user interface to compose a new messages,
- reload the list content from the server and changing the users name or email if these
- are allowed to be set.
-
- To add this view controller to your own app and push it onto a navigation stack,
- don't create the instance yourself, but use the following code to get a correct instance:
-
- [[BITHockeyManager sharedHockeyManager].feedbackManager feedbackListViewController:NO]
-
- To show it modally, use the following code instead:
-
- [[BITHockeyManager sharedHockeyManager].feedbackManager feedbackListViewController:YES]
-
- This ensures that the presentation on iOS 6 and iOS 7 will use the current design on each OS Version.
- */
-
-@interface BITFeedbackListViewController : BITHockeyBaseViewController {
-}
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITFeedbackListViewController.m b/submodules/HockeySDK-iOS/Classes/BITFeedbackListViewController.m
deleted file mode 100644
index 14a1dcbc98..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITFeedbackListViewController.m
+++ /dev/null
@@ -1,804 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_FEEDBACK
-
-#import "HockeySDKPrivate.h"
-
-#import "BITFeedbackManagerPrivate.h"
-#import "BITFeedbackManager.h"
-#import "BITFeedbackListViewController.h"
-#import "BITFeedbackListViewCell.h"
-#import "BITFeedbackComposeViewController.h"
-#import "BITFeedbackUserDataViewController.h"
-#import "BITFeedbackMessage.h"
-#import "BITFeedbackMessageAttachment.h"
-#import "BITAttributedLabel.h"
-
-#import "BITHockeyBaseManagerPrivate.h"
-
-#import "BITHockeyHelper.h"
-#import
-#import
-
-#define DEFAULT_TEXTCOLOR BIT_RGBCOLOR(75, 75, 75)
-
-#define BORDER_COLOR BIT_RGBCOLOR(215, 215, 215)
-
-
-@interface BITFeedbackListViewController ()
-
-@property (nonatomic, weak) BITFeedbackManager *manager;
-@property (nonatomic, strong) NSDateFormatter *lastUpdateDateFormatter;
-@property (nonatomic) BOOL userDataComposeFlow;
-@property (nonatomic, strong) NSArray *cachedPreviewItems;
-@property (nonatomic, strong) NSOperationQueue *thumbnailQueue;
-@property (nonatomic) NSInteger deleteButtonSection;
-@property (nonatomic) NSInteger userButtonSection;
-@property (nonatomic) NSInteger numberOfSectionsBeforeRotation;
-@property (nonatomic) NSInteger numberOfMessagesBeforeRotation;
-
-@end
-
-
-@implementation BITFeedbackListViewController
-
-- (instancetype)initWithStyle:(UITableViewStyle)style {
- if ((self = [super initWithStyle:style])) {
- _manager = [BITHockeyManager sharedHockeyManager].feedbackManager;
-
- _deleteButtonSection = -1;
- self.userButtonSection = -1;
- _userDataComposeFlow = NO;
-
- _numberOfSectionsBeforeRotation = -1;
- _numberOfMessagesBeforeRotation = -1;
-
-
- _lastUpdateDateFormatter = [[NSDateFormatter alloc] init];
- [_lastUpdateDateFormatter setDateStyle:NSDateFormatterShortStyle];
- [_lastUpdateDateFormatter setTimeStyle:NSDateFormatterShortStyle];
- _lastUpdateDateFormatter.locale = [NSLocale currentLocale];
-
- _thumbnailQueue = [NSOperationQueue new];
- }
- return self;
-}
-
-
-- (void)dealloc {
- [[NSNotificationCenter defaultCenter] removeObserver:self name:BITHockeyFeedbackMessagesLoadingStarted object:nil];
- [[NSNotificationCenter defaultCenter] removeObserver:self name:BITHockeyFeedbackMessagesLoadingFinished object:nil];
-
- [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(showDelayedUserDataViewController) object:nil];
-}
-
-
-#pragma mark - View lifecycle
-
-- (void)viewDidLoad {
- [super viewDidLoad];
-
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(startLoadingIndicator)
- name:BITHockeyFeedbackMessagesLoadingStarted
- object:nil];
-
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(updateList)
- name:BITHockeyFeedbackMessagesLoadingFinished
- object:nil];
-
- self.title = BITHockeyLocalizedString(@"HockeyFeedbackListTitle");
-
- self.tableView.delegate = self;
- self.tableView.dataSource = self;
- self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
- [self.tableView setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth];
-
- if ([UIRefreshControl class]) {
- self.refreshControl = [[UIRefreshControl alloc] init];
- [self.refreshControl addTarget:self action:@selector(reloadList) forControlEvents:UIControlEventValueChanged];
- } else {
- self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh
- target:self
- action:@selector(reloadList)];
- }
-}
-
-- (void)startLoadingIndicator {
- if ([UIRefreshControl class]) {
- [self.refreshControl beginRefreshing];
- } else {
- self.navigationItem.rightBarButtonItem.enabled = NO;
- }
-}
-
-- (void)stopLoadingIndicator {
- if ([UIRefreshControl class]) {
- [self.refreshControl endRefreshing];
- } else {
- self.navigationItem.rightBarButtonItem.enabled = YES;
- }
-}
-
-- (BOOL)isRefreshingWithNewControl {
- if ([UIRefreshControl class]) {
- return [self.refreshControl isRefreshing];
- }
- return NO;
-}
-
-- (void)reloadList {
- [self startLoadingIndicator];
-
- [self.manager updateMessagesList];
-}
-
-- (void)updateList {
- dispatch_async(dispatch_get_main_queue(), ^{
- CGSize contentSize = self.tableView.contentSize;
- CGPoint contentOffset = self.tableView.contentOffset;
-
- [self refreshPreviewItems];
- [self.tableView reloadData];
-
- if (contentSize.height > 0 &&
- self.tableView.contentSize.height > self.tableView.frame.size.height &&
- self.tableView.contentSize.height > contentSize.height &&
- ![self isRefreshingWithNewControl])
- [self.tableView setContentOffset:CGPointMake(contentOffset.x, self.tableView.contentSize.height - contentSize.height + contentOffset.y) animated:NO];
-
- [self stopLoadingIndicator];
-
- [self.tableView flashScrollIndicators];
- });
-}
-
-- (void)viewDidAppear:(BOOL)animated {
- if (self.userDataComposeFlow) {
- self.userDataComposeFlow = NO;
- }
- BITFeedbackManager *strongManager = self.manager;
- strongManager.currentFeedbackListViewController = self;
-
- [strongManager updateMessagesListIfRequired];
-
- if ([strongManager numberOfMessages] == 0 &&
- [strongManager askManualUserDataAvailable] &&
- [strongManager requireManualUserDataMissing] &&
- ![strongManager didAskUserData]
- ) {
- self.userDataComposeFlow = YES;
-
- if ([strongManager showFirstRequiredPresentationModal]) {
- [self setUserDataAction:nil];
- } else {
- // In case of presenting the feedback in a UIPopoverController it appears
- // that the animation is not yet finished (though it should) and pushing
- // the user data view on top of the navigation stack right away will
- // cause the following warning to appear in the console:
- // "nested push animation can result in corrupted navigation bar"
- [self performSelector:@selector(showDelayedUserDataViewController) withObject:nil afterDelay:0.0];
- }
- } else {
- [self.tableView reloadData];
- }
-
- [super viewDidAppear:animated];
-}
-
-- (void)viewWillDisappear:(BOOL)animated {
- self.manager.currentFeedbackListViewController = nil;
-
- [super viewWillDisappear:animated];
-}
-
-
-#pragma mark - Private methods
-
-- (void)showDelayedUserDataViewController {
- BITFeedbackUserDataViewController *userController = [[BITFeedbackUserDataViewController alloc] initWithStyle:UITableViewStyleGrouped];
- userController.delegate = self;
-
- [self.navigationController pushViewController:userController animated:YES];
-}
-
-- (void)setUserDataAction:(id) __unused sender {
- BITFeedbackUserDataViewController *userController = [[BITFeedbackUserDataViewController alloc] initWithStyle:UITableViewStyleGrouped];
- userController.delegate = self;
-
- UINavigationController *navController = [self.manager customNavigationControllerWithRootViewController:userController
- presentationStyle:UIModalPresentationFormSheet];
-
- [self presentViewController:navController animated:YES completion:nil];
-}
-
-- (void)newFeedbackAction:(id) __unused sender {
- BITFeedbackManager *strongManager = self.manager;
- BITFeedbackComposeViewController *composeController = [strongManager feedbackComposeViewController];
-
- UINavigationController *navController = [strongManager customNavigationControllerWithRootViewController:composeController
- presentationStyle:UIModalPresentationFormSheet];
-
- [self presentViewController:navController animated:YES completion:nil];
-}
-
-- (void)deleteAllMessages {
- [self.manager deleteAllMessages];
- [self refreshPreviewItems];
-
- [self.tableView reloadData];
-}
-
-- (void)deleteAllMessagesAction:(id) __unused sender {
- NSString *title = BITHockeyLocalizedString(@"HockeyFeedbackListButtonDeleteAllMessages");
- NSString *message = BITHockeyLocalizedString(@"HockeyFeedbackListDeleteAllTitle");
- UIAlertControllerStyle controllerStyle = UIAlertControllerStyleAlert;
- if (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) {
- controllerStyle = UIAlertControllerStyleActionSheet;
- title = BITHockeyLocalizedString(@"HockeyFeedbackListDeleteAllTitle");
- message = nil;
- }
- __weak typeof(self) weakSelf = self;
- UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title
- message:message
- preferredStyle:controllerStyle];
- UIAlertAction* cancelAction = [BITAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackListDeleteAllCancel")
- style:UIAlertActionStyleCancel
- handler:^(UIAlertAction __unused *action) {}];
- [alertController addAction:cancelAction];
- UIAlertAction* deleteAction = [BITAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackListDeleteAllDelete")
- style:UIAlertActionStyleDestructive
- handler:^(UIAlertAction __unused *action) {
- typeof(self) strongSelf = weakSelf;
- [strongSelf deleteAllMessages];
- }];
- [alertController addAction:deleteAction];
- [self presentViewController:alertController animated:YES completion:nil];
-}
-
-- (UIView*) viewForShowingActionSheetOnPhone {
- //find the topmost presented view controller
- //and use its view
- UIViewController* topMostPresentedViewController = self.view.window.rootViewController;
- while(topMostPresentedViewController.presentedViewController) {
- topMostPresentedViewController = topMostPresentedViewController.presentedViewController;
- }
- UIView* view = topMostPresentedViewController.view;
-
- if(nil == view) {
- //hope for the best. Should work
- //on simple view(controller) hierarchies
- view = self.view;
- }
-
- return view;
-}
-
-#pragma mark - BITFeedbackUserDataDelegate
-
--(void)userDataUpdateCancelled {
- if (self.userDataComposeFlow) {
- if ([self.manager showFirstRequiredPresentationModal]) {
- __weak typeof(self) weakSelf = self;
- [self dismissViewControllerAnimated:YES completion:^(void){
- typeof(self) strongSelf = weakSelf;
- [strongSelf.tableView reloadData];
- }];
- } else {
- [self.navigationController popToViewController:self animated:YES];
- }
- } else {
- [self dismissViewControllerAnimated:YES completion:^(void){}];
- }
-}
-
--(void)userDataUpdateFinished {
- BITFeedbackManager *strongManager = self.manager;
- [strongManager saveMessages];
- [self refreshPreviewItems];
-
- if (self.userDataComposeFlow) {
- if ([strongManager showFirstRequiredPresentationModal]) {
- __weak typeof(self) weakSelf = self;
- [self dismissViewControllerAnimated:YES completion:^(void){
- typeof(self) strongSelf = weakSelf;
- [strongSelf newFeedbackAction:nil];
- }];
- } else {
- BITFeedbackComposeViewController *composeController = [[BITFeedbackComposeViewController alloc] init];
- composeController.delegate = self;
-
- [self.navigationController pushViewController:composeController animated:YES];
- }
- } else {
- [self dismissViewControllerAnimated:YES completion:^(void){}];
- }
-}
-
-
-#pragma mark - BITFeedbackComposeViewControllerDelegate
-
-- (void)feedbackComposeViewController:(BITFeedbackComposeViewController *)composeViewController
- didFinishWithResult:(BITFeedbackComposeResult)composeResult {
- BITFeedbackManager *strongManager = self.manager;
- if (self.userDataComposeFlow) {
- if ([strongManager showFirstRequiredPresentationModal]) {
- __weak typeof(self) weakSelf = self;
- [self dismissViewControllerAnimated:YES completion:^(void){
- typeof(self) strongSelf = weakSelf;
- [strongSelf.tableView reloadData];
- }];
- } else {
- [self.navigationController popToViewController:self animated:YES];
- }
- } else {
- [self dismissViewControllerAnimated:YES completion:^(void){}];
- }
- id strongDelegate = strongManager.delegate;
- if ([strongDelegate respondsToSelector:@selector(feedbackComposeViewController:didFinishWithResult:)]) {
- [strongDelegate feedbackComposeViewController:composeViewController didFinishWithResult:composeResult];
- }
-}
-
-
-#pragma mark - UIViewController Rotation
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-implementations"
-- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
- self.numberOfSectionsBeforeRotation = [self numberOfSectionsInTableView:self.tableView];
- self.numberOfMessagesBeforeRotation = [self.manager numberOfMessages];
- [self.tableView reloadData];
- [self.tableView beginUpdates];
- [self.tableView endUpdates];
-
- self.numberOfSectionsBeforeRotation = -1;
- self.numberOfMessagesBeforeRotation = -1;
- [self.tableView reloadData];
-
- [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
-}
-#pragma clang diagnostic pop
-
-- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
- return UIInterfaceOrientationMaskAll;
-}
-
-#pragma mark - Table view data source
-
-- (NSInteger)numberOfSectionsInTableView:(UITableView *) __unused tableView {
- if (self.numberOfSectionsBeforeRotation >= 0)
- return self.numberOfSectionsBeforeRotation;
-
- NSInteger sections = 2;
- self.deleteButtonSection = -1;
- self.userButtonSection = -1;
- BITFeedbackManager *strongManager = self.manager;
- if ([strongManager isManualUserDataAvailable] || [strongManager didAskUserData]) {
- self.userButtonSection = sections;
- sections++;
- }
-
- if ([strongManager numberOfMessages] > 0) {
- self.deleteButtonSection = sections;
- sections++;
- }
-
- return sections;
-}
-
-- (NSInteger)tableView:(UITableView *) __unused tableView numberOfRowsInSection:(NSInteger)section {
- if (section == 1) {
- if (self.numberOfMessagesBeforeRotation >= 0)
- return self.numberOfMessagesBeforeRotation;
- return [self.manager numberOfMessages];
- } else {
- return 1;
- }
-}
-
-- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
- if (section == 0) {
- return 30;
- }
- return [super tableView:tableView heightForHeaderInSection:section];
-}
-
-- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
- if (section == 0) {
- BITFeedbackManager *strongManager = self.manager;
- UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 30.0)];
- UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectMake(16.0, 5.0, self.view.frame.size.width - (CGFloat)32.0, 25.0)];
- textLabel.text = [NSString stringWithFormat:BITHockeyLocalizedString(@"HockeyFeedbackListLastUpdated"),
- [strongManager lastCheck] ? [self.lastUpdateDateFormatter stringFromDate:[strongManager lastCheck]] : BITHockeyLocalizedString(@"HockeyFeedbackListNeverUpdated")];
- textLabel.font = [UIFont systemFontOfSize:10];
- textLabel.textColor = DEFAULT_TEXTCOLOR;
- [containerView addSubview:textLabel];
-
- return containerView;
- }
-
- return [super tableView:tableView viewForHeaderInSection:section];
-}
-
-- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
- static NSString *CellIdentifier = @"MessageCell";
- static NSString *LastUpdateIdentifier = @"LastUpdateCell";
- static NSString *ButtonTopIdentifier = @"ButtonTopCell";
- static NSString *ButtonBottomIdentifier = @"ButtonBottomCell";
- static NSString *ButtonDeleteIdentifier = @"ButtonDeleteCell";
- BITFeedbackManager *strongManager = self.manager;
- if (indexPath.section == 0 && indexPath.row == 1) {
- UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:LastUpdateIdentifier];
-
- if (!cell) {
- cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:LastUpdateIdentifier];
- cell.textLabel.font = [UIFont systemFontOfSize:10];
- cell.textLabel.textColor = DEFAULT_TEXTCOLOR;
- cell.accessoryType = UITableViewCellAccessoryNone;
- cell.selectionStyle = UITableViewCellSelectionStyleNone;
- cell.textLabel.textAlignment = NSTextAlignmentCenter;
- }
- cell.textLabel.accessibilityTraits = UIAccessibilityTraitStaticText;
- cell.textLabel.text = [NSString stringWithFormat:BITHockeyLocalizedString(@"HockeyFeedbackListLastUpdated"),
- [strongManager lastCheck] ? [self.lastUpdateDateFormatter stringFromDate:[strongManager lastCheck]] : BITHockeyLocalizedString(@"HockeyFeedbackListNeverUpdated")];
-
- return cell;
- } else if (indexPath.section == 0 || indexPath.section >= 2) {
- UITableViewCell *cell = nil;
-
- NSString *identifier = nil;
- if (indexPath.section == 0) {
- identifier = ButtonTopIdentifier;
- } else if (indexPath.section == self.userButtonSection) {
- identifier = ButtonBottomIdentifier;
- } else {
- identifier = ButtonDeleteIdentifier;
- }
-
- cell = [tableView dequeueReusableCellWithIdentifier:identifier];
-
- if (!cell) {
- cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
-
- cell.textLabel.font = [UIFont systemFontOfSize:14];
- cell.textLabel.numberOfLines = 0;
- cell.accessoryType = UITableViewCellAccessoryNone;
- cell.selectionStyle = UITableViewCellSelectionStyleGray;
- }
-
- // Set accessibilityTraits to UIAccessibilityTraitNone to make sure we're not setting the trait to an incorrect type for recycled cells.
- cell.textLabel.accessibilityTraits = UIAccessibilityTraitNone;
-
- // button
- NSString *titleString = nil;
-
- UIColor *titleColor = BIT_RGBCOLOR(35, 111, 251);
- if ([self.view respondsToSelector:@selector(tintColor)]){
- titleColor = self.view.tintColor;
- }
- if (indexPath.section == 0) {
- cell.textLabel.accessibilityTraits = UIAccessibilityTraitButton;
- if ([strongManager numberOfMessages] == 0) {
- titleString = BITHockeyLocalizedString(@"HockeyFeedbackListButtonWriteFeedback");
- } else {
- titleString = BITHockeyLocalizedString(@"HockeyFeedbackListButtonWriteResponse");
- }
- } else if (indexPath.section == self.userButtonSection) {
- if ([strongManager requireUserName] == BITFeedbackUserDataElementRequired ||
- ([strongManager requireUserName] == BITFeedbackUserDataElementOptional && [strongManager userName] != nil)
- ) {
- cell.textLabel.accessibilityTraits = UIAccessibilityTraitStaticText;
- titleString = [NSString stringWithFormat:BITHockeyLocalizedString(@"HockeyFeedbackListButtonUserDataWithName"), [strongManager userName] ?: @"-"];
- } else if ([strongManager requireUserEmail] == BITFeedbackUserDataElementRequired ||
- ([strongManager requireUserEmail] == BITFeedbackUserDataElementOptional && [strongManager userEmail] != nil)
- ) {
- cell.textLabel.accessibilityTraits = UIAccessibilityTraitStaticText;
- titleString = [NSString stringWithFormat:BITHockeyLocalizedString(@"HockeyFeedbackListButtonUserDataWithEmail"), [strongManager userEmail] ?: @"-"];
- } else if ([strongManager requireUserName] == BITFeedbackUserDataElementOptional) {
- cell.textLabel.accessibilityTraits = UIAccessibilityTraitButton;
- titleString = BITHockeyLocalizedString(@"HockeyFeedbackListButtonUserDataSetName");
- } else {
- cell.textLabel.accessibilityTraits = UIAccessibilityTraitButton;
- titleString = BITHockeyLocalizedString(@"HockeyFeedbackListButtonUserDataSetEmail");
- }
- } else {
- cell.textLabel.accessibilityTraits = UIAccessibilityTraitButton;
- titleString = BITHockeyLocalizedString(@"HockeyFeedbackListButtonDeleteAllMessages");
- titleColor = BIT_RGBCOLOR(251, 35, 35);
- }
-
- cell.textLabel.text = titleString;
- cell.textLabel.textColor = titleColor;
-
- return cell;
- } else {
- BITFeedbackListViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
-
- if (!cell) {
- cell = [[BITFeedbackListViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
- cell.accessoryType = UITableViewCellAccessoryNone;
- cell.selectionStyle = UITableViewCellSelectionStyleNone;
- }
-
- if (indexPath.row == 0 || indexPath.row % 2 == 0) {
- cell.backgroundStyle = BITFeedbackListViewCellBackgroundStyleAlternate;
- } else {
- cell.backgroundStyle = BITFeedbackListViewCellBackgroundStyleNormal;
- }
-
- BITFeedbackMessage *message = [strongManager messageAtIndex:indexPath.row];
- cell.message = message;
- cell.labelText.delegate = self;
- cell.labelText.userInteractionEnabled = YES;
- cell.delegate = self;
- [cell setAttachments:message.previewableAttachments];
-
- for (BITFeedbackMessageAttachment *attachment in message.attachments){
- if (attachment.needsLoadingFromURL && !attachment.isLoading){
- attachment.isLoading = YES;
- NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:(NSURL *)[NSURL URLWithString:attachment.sourceURL]];
- __weak typeof (self) weakSelf = self;
- NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
- __block NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
-
- NSURLSessionDataTask *task = [session dataTaskWithRequest:request
- completionHandler: ^(NSData *data, NSURLResponse __unused *response, NSError *error) {
- typeof (self) strongSelf = weakSelf;
-
- [session finishTasksAndInvalidate];
-
- [strongSelf handleResponseForAttachment:attachment responseData:data error:error];
- }];
- [task resume];
- }
- }
-
- if (indexPath.row != 0) {
- UIView *lineView1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, cell.frame.size.width, 1)];
- lineView1.backgroundColor = BORDER_COLOR;
- lineView1.autoresizingMask = UIViewAutoresizingFlexibleWidth;
- [cell addSubview:lineView1];
- }
-
- return cell;
- }
-}
-
-- (void)handleResponseForAttachment:(BITFeedbackMessageAttachment *)attachment responseData:(NSData *)responseData error:(NSError *) __unused error {
- attachment.isLoading = NO;
- if (responseData.length) {
- dispatch_async(dispatch_get_main_queue(), ^{
- [attachment replaceData:responseData];
- [[NSNotificationCenter defaultCenter] postNotificationName:kBITFeedbackUpdateAttachmentThumbnail object:attachment];
- [[BITHockeyManager sharedHockeyManager].feedbackManager saveMessages];
- [self.tableView reloadData];
- });
- }
-}
-
-
-- (BOOL)tableView:(UITableView *) __unused tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
- if (indexPath.section == 1)
- return YES;
-
- return NO;
-}
-
-- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
- if (editingStyle == UITableViewCellEditingStyleDelete) {
- BITFeedbackManager *strongManager = self.manager;
- BITFeedbackMessage *message = [strongManager messageAtIndex:indexPath.row];
- BOOL messageHasAttachments = ([message attachments].count > 0);
-
- if ([strongManager deleteMessageAtIndex:indexPath.row]) {
- if ([strongManager numberOfMessages] > 0) {
- [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
- } else {
- [tableView reloadData];
- }
-
- if (messageHasAttachments) {
- [self refreshPreviewItems];
- }
- }
- }
-}
-
-
-#pragma mark - Table view delegate
-
-- (CGFloat)tableView:(UITableView *) __unused tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
- if (indexPath.section == 0 ) {
- return 44;
- }
- if (indexPath.section >= 2) {
- return 44;
- }
-
- BITFeedbackMessage *message = [self.manager messageAtIndex:indexPath.row];
- if (!message) return 44;
-
- return [BITFeedbackListViewCell heightForRowWithMessage:message tableViewWidth:self.view.frame.size.width];
-}
-
-- (void)tableView:(UITableView *) __unused tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
- if (indexPath.section == 0) {
- [self newFeedbackAction:self];
- } else if (indexPath.section == self.userButtonSection) {
- [self setUserDataAction:self];
- } else if (indexPath.section == self.deleteButtonSection) {
- [self deleteAllMessagesAction:self];
- }
-}
-
-#pragma mark - BITAttributedLabelDelegate
-
-- (void)attributedLabel:(BITAttributedLabel *) __unused label didSelectLinkWithURL:(NSURL *)url {
- UIAlertControllerStyle controllerStyle = UIAlertControllerStyleAlert;
- if (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) {
- controllerStyle = UIAlertControllerStyleActionSheet;
- }
- UIAlertController *linkAction = [UIAlertController alertControllerWithTitle:[url absoluteString]
- message:nil
- preferredStyle:controllerStyle];
- UIAlertAction* cancelAction = [BITAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackListLinkActionCancel")
- style:UIAlertActionStyleCancel
- handler:^(UIAlertAction __unused *action) {}];
- [linkAction addAction:cancelAction];
- UIAlertAction* openAction = [BITAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackListLinkActionOpen")
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction __unused *action) {
- [[UIApplication sharedApplication] openURL:(NSURL*)[NSURL URLWithString:(NSString*)[url absoluteString]]];
- }];
- [linkAction addAction:openAction];
- UIAlertAction* copyAction = [BITAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackListLinkActionCopy")
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction __unused *action) {
- UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
- pasteboard.URL = [NSURL URLWithString:(NSString*)[url absoluteString]];
- }];
- [linkAction addAction:copyAction];
- [self presentViewController:linkAction animated:YES completion:nil];
-}
-
-#pragma mark - UIActionSheetDelegate
-
-- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
- if (buttonIndex == actionSheet.cancelButtonIndex) {
- return;
- }
-
- if ([actionSheet tag] == 0) {
- if (buttonIndex == [actionSheet destructiveButtonIndex]) {
- [self deleteAllMessages];
- }
- } else {
- if (buttonIndex == [actionSheet firstOtherButtonIndex]) {
- [[UIApplication sharedApplication] openURL:(NSURL *)[NSURL URLWithString:actionSheet.title]];
- } else {
- UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
- pasteboard.URL = [NSURL URLWithString:actionSheet.title];
- }
- }
-}
-
-#pragma mark - ListViewCellDelegate
-
-- (void)listCell:(id) __unused cell didSelectAttachment:(BITFeedbackMessageAttachment *)attachment {
- if (!self.cachedPreviewItems){
- [self refreshPreviewItems];
- }
-
- QLPreviewController *previewController = [[QLPreviewController alloc] init];
- previewController.dataSource = self;
-
- [self presentViewController:previewController animated:YES completion:nil];
-
- if (self.cachedPreviewItems.count > [self.cachedPreviewItems indexOfObject:attachment]) {
- [previewController setCurrentPreviewItemIndex:[self.cachedPreviewItems indexOfObject:attachment]];
- }
-}
-
-- (void)refreshPreviewItems {
- self.cachedPreviewItems = nil;
- NSMutableArray *collectedAttachments = [NSMutableArray new];
- BITFeedbackManager *strongManager = self.manager;
- for (uint i = 0; i < strongManager.numberOfMessages; i++) {
- BITFeedbackMessage *message = [strongManager messageAtIndex:i];
- [collectedAttachments addObjectsFromArray:message.previewableAttachments];
- }
-
- self.cachedPreviewItems = collectedAttachments;
-}
-
-- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *) __unused controller {
- return self.cachedPreviewItems.count;
-}
-
-- (id )previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index {
- if (index >= 0) {
- __weak QLPreviewController* blockController = controller;
- BITFeedbackMessageAttachment *attachment = self.cachedPreviewItems[index];
-
- if (attachment.needsLoadingFromURL && !attachment.isLoading) {
- attachment.isLoading = YES;
- NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:(NSURL *)[NSURL URLWithString:attachment.sourceURL]];
-
- __weak typeof (self) weakSelf = self;
- NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
- __block NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
-
- NSURLSessionDataTask *task = [session dataTaskWithRequest:request
- completionHandler: ^(NSData *data, NSURLResponse __unused *response, NSError __unused *error) {
- dispatch_async(dispatch_get_main_queue(), ^{
- typeof (self) strongSelf = weakSelf;
-
- [session finishTasksAndInvalidate];
-
- [strongSelf previewController:blockController updateAttachment:attachment data:data];
- });
- }];
- [task resume];
- return attachment;
- } else {
- return self.cachedPreviewItems[index];
- }
- }
-
- return [self placeholder];
-}
-
-- (void)previewController:(QLPreviewController *)controller updateAttachment:(BITFeedbackMessageAttachment *)attachment data:( NSData *)data {
- attachment.isLoading = NO;
- if (data.length) {
- [attachment replaceData:data];
- [controller reloadData];
-
- [[BITHockeyManager sharedHockeyManager].feedbackManager saveMessages];
- } else {
- [controller reloadData];
- }
-}
-
-- (BITFeedbackMessageAttachment *)placeholder {
- UIImage *placeholderImage = bit_imageNamed(@"FeedbackPlaceHolder", BITHOCKEYSDK_BUNDLE);
-
- BITFeedbackMessageAttachment *placeholder = [BITFeedbackMessageAttachment attachmentWithData:UIImageJPEGRepresentation(placeholderImage, (CGFloat)0.7) contentType:@"image/jpeg"];
-
- return placeholder;
-}
-
-@end
-
-#endif /* HOCKEYSDK_FEATURE_FEEDBACK */
diff --git a/submodules/HockeySDK-iOS/Classes/BITFeedbackManager.h b/submodules/HockeySDK-iOS/Classes/BITFeedbackManager.h
deleted file mode 100644
index 507788df71..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITFeedbackManager.h
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#import
-
-#import "BITHockeyBaseManager.h"
-#import "BITFeedbackListViewController.h"
-#import "BITFeedbackComposeViewController.h"
-
-#import "HockeySDKNullability.h"
-NS_ASSUME_NONNULL_BEGIN
-
-// Notification message which tells that loading messages finished
-#define BITHockeyFeedbackMessagesLoadingStarted @"BITHockeyFeedbackMessagesLoadingStarted"
-
-// Notification message which tells that loading messages finished
-#define BITHockeyFeedbackMessagesLoadingFinished @"BITHockeyFeedbackMessagesLoadingFinished"
-
-
-/**
- * Defines behavior of the user data field
- */
-typedef NS_ENUM(NSInteger, BITFeedbackUserDataElement) {
- /**
- * don't ask for this user data element at all
- */
- BITFeedbackUserDataElementDontShow = 0,
- /**
- * the user may provide it, but does not have to
- */
- BITFeedbackUserDataElementOptional = 1,
- /**
- * the user has to provide this to continue
- */
- BITFeedbackUserDataElementRequired = 2
-};
-
-/**
- * Available modes for opening the feedback compose interface with a screenshot attached
- */
-typedef NS_ENUM(NSInteger, BITFeedbackObservationMode) {
- /**
- * No SDK provided trigger is active.
- */
- BITFeedbackObservationNone = 0,
- /**
- * Triggers when the user takes a screenshot. This will grab the latest image from the camera roll. Requires iOS 7 or later!
- */
- BITFeedbackObservationModeOnScreenshot = 1,
- /**
- * Triggers when the user taps with three fingers on the screen. Captures a screenshot and attaches it to the composer.
- */
- BITFeedbackObservationModeThreeFingerTap = 2,
- /**
- * Allows both BITFeedbackObservationModeOnScreenshot and BITFeedbackObservationModeThreeFingerTap at the same time.
- */
- BITFeedbackObservationModeAll = 3
-};
-
-
-@class BITFeedbackMessage;
-@protocol BITFeedbackManagerDelegate;
-
-/**
- The feedback module.
-
- This is the HockeySDK module for letting your users communicate directly with you via
- the app and an integrated user interface. It provides a single threaded
- discussion with a user running your app.
-
- You should never create your own instance of `BITFeedbackManager` but use the one provided
- by the `[BITHockeyManager sharedHockeyManager]`:
-
- [BITHockeyManager sharedHockeyManager].feedbackManager
-
- The user interface provides a list view that can be presented modally using
- `[BITFeedbackManager showFeedbackListView]` or adding
- `[BITFeedbackManager feedbackListViewController:]` to push onto a navigation stack.
- This list integrates all features to load new messages, write new messages, view messages
- and ask the user for additional (optional) data like name and email.
-
- If the user provides the email address, all responses from the server will also be sent
- to the user via email and the user is also able to respond directly via email, too.
-
- The message list interface also contains options to locally delete single messages
- by swiping over them, or deleting all messages. This will not delete the messages
- on the server, though!
-
- It also integrates actions to invoke the user interface to compose a new message,
- reload the list content from the server and change the users name or email if these
- are allowed to be set.
-
- It is also possible to invoke the user interface to compose a new message in your
- own code, by calling `[BITFeedbackManager showFeedbackComposeView]` modally or adding
- `[BITFeedbackManager feedbackComposeViewController]` to push onto a navigation stack.
-
- If new messages are written while the device is offline, the SDK automatically retries to
- send them once the app starts again or gets active again, or if the notification
- `BITHockeyNetworkDidBecomeReachableNotification` is fired.
-
- A third option is to include the `BITFeedbackActivity` into an UIActivityViewController.
- This can be useful if you present some data that users can not only share but also
- report back to the developer because they have some problems, e.g. webcams not working
- any more. The activity provides a default title and image that can also be customized.
-
- New messages are automatically loaded on startup, when the app becomes active again
- or when the notification `BITHockeyNetworkDidBecomeReachableNotification` is fired. This
- only happens if the user ever did initiate a conversation by writing the first
- feedback message. The app developer has to fire this notification to trigger another retry
- when it detects the device having network access again. The SDK only retries automatically
- when the app becomes active again.
-
- Implementing the `BITFeedbackManagerDelegate` protocol will notify your app when a new
- message was received from the server. The `BITFeedbackComposeViewControllerDelegate`
- protocol informs your app about events related to sending feedback messages.
-
- */
-
-@interface BITFeedbackManager : BITHockeyBaseManager
-
-///-----------------------------------------------------------------------------
-/// @name General settings
-///-----------------------------------------------------------------------------
-
-
-/**
- Define if a name has to be provided by the user when providing feedback
-
- - `BITFeedbackUserDataElementDontShow`: Don't ask for this user data element at all
- - `BITFeedbackUserDataElementOptional`: The user may provide it, but does not have to
- - `BITFeedbackUserDataElementRequired`: The user has to provide this to continue
-
- The default value is `BITFeedbackUserDataElementOptional`.
-
- @warning If you provide a non nil value for the `BITFeedbackManager` class via
- `[BITHockeyManagerDelegate userNameForHockeyManager:componentManager:]` then this
- property will automatically be set to `BITFeedbackUserDataElementDontShow`
-
- @see BITFeedbackUserDataElement
- @see requireUserEmail
- @see `[BITHockeyManagerDelegate userNameForHockeyManager:componentManager:]`
- */
-@property (nonatomic, readwrite) BITFeedbackUserDataElement requireUserName;
-
-
-/**
- Define if an email address has to be provided by the user when providing feedback
-
- If the user provides the email address, all responses from the server will also be send
- to the user via email and the user is also able to respond directly via email too.
-
- - `BITFeedbackUserDataElementDontShow`: Don't ask for this user data element at all
- - `BITFeedbackUserDataElementOptional`: The user may provide it, but does not have to
- - `BITFeedbackUserDataElementRequired`: The user has to provide this to continue
-
- The default value is `BITFeedbackUserDataElementOptional`.
-
- @warning If you provide a non nil value for the `BITFeedbackManager` class via
- `[BITHockeyManagerDelegate userEmailForHockeyManager:componentManager:]` then this
- property will automatically be set to `BITFeedbackUserDataElementDontShow`
-
- @see BITFeedbackUserDataElement
- @see requireUserName
- @see `[BITHockeyManagerDelegate userEmailForHockeyManager:componentManager:]`
- */
-@property (nonatomic, readwrite) BITFeedbackUserDataElement requireUserEmail;
-
-
-/**
- Indicates if an alert should be shown when new messages have arrived
-
- This lets the user view the new feedback by choosing the appropriate option
- in the alert sheet, and the `BITFeedbackListViewController` will be shown.
-
- The alert is only shown, if the newest message didn't originate from the current user.
- This requires the users email address to be present! The optional userid property
- cannot be used, because users could also answer via email and then this information
- is not available.
-
- Default is `YES`
- @see feedbackListViewController:
- @see requireUserEmail
- @see `[BITHockeyManagerDelegate userEmailForHockeyManager:componentManager:]`
- */
-@property (nonatomic, readwrite) BOOL showAlertOnIncomingMessages;
-
-
-/**
- Define the trigger that opens the feedback composer and attaches a screenshot
-
- The following modes are available:
-
- - `BITFeedbackObservationNone`: No SDK based trigger is active. You can implement your
- own trigger and then call `[[BITHockeyManager sharedHockeyManager].feedbackManager showFeedbackComposeViewWithGeneratedScreenshot];` to handle your custom events
- that should trigger this.
- - `BITFeedbackObservationModeOnScreenshot`: Triggers when the user takes a screenshot.
- This will grab the latest image from the camera roll. It also requires to add a NSPhotoLibraryUsageDescription to your app's Info.plist.
- - `BITFeedbackObservationModeThreeFingerTap`: Triggers when the user taps on the screen with three fingers. Takes a screenshot and attaches it to the composer. It also requires to add a NSPhotoLibraryUsageDescription to your app's Info.plist.
-
- Default is `BITFeedbackObservationNone`.
- If BITFeedbackManger was disabled, setting a new value will be ignored.
- @see `[BITHockeyManager disableFeedbackManager]`
-
- @see showFeedbackComposeViewWithGeneratedScreenshot
- */
-@property (nonatomic, readwrite) BITFeedbackObservationMode feedbackObservationMode;
-
-/**
- Don't show the option to add images from the photo library
-
- This is helpful if your application is landscape only, since the system UI for
- selecting an image from the photo library is portrait only
-
- This setting is used for all feedback compose views that are created by the
- `BITFeedbackManager`. If you invoke your own `BITFeedbackComposeViewController`,
- then set the appropriate property on the view controller directl!.
- */
-@property (nonatomic) BOOL feedbackComposeHideImageAttachmentButton;
-
-
-///-----------------------------------------------------------------------------
-/// @name User Interface
-///-----------------------------------------------------------------------------
-
-
-/**
- Indicates if a forced user data UI presentation is shown modal
-
- If `requireUserName` and/or `requireUserEmail` are enabled, the first presentation
- of `feedbackListViewController:` and subsequent `feedbackComposeViewController:`
- will automatically present a UI that lets the user provide this data and compose
- a message. By default this is shown (since SDK 3.1) as a modal sheet.
-
- If you want the SDK to push this UI onto the navigation stack in this specific scenario,
- then change the property to `NO`.
-
- @warning If you are presenting the `BITFeedbackListViewController` in a popover, this property should not be changed!
-
- Default is `YES`
- @see requireUserName
- @see requireUserEmail
- @see showFeedbackComposeView
- @see feedbackComposeViewController
- @see showFeedbackListView
- @see feedbackListViewController:
- */
-@property (nonatomic, readwrite) BOOL showFirstRequiredPresentationModal;
-
-
-/**
- Return a screenshot UIImage instance from the current visible screen
-
- @return UIImage instance containing a screenshot of the current screen
- */
-- (UIImage *)screenshot;
-
-
-/**
- Present the modal feedback list user interface.
-
- @warning This methods needs to be called on the main thread!
- */
-- (void)showFeedbackListView;
-
-
-/**
- Create an feedback list view
-
- @param modal Return a view ready for modal presentation with integrated navigation bar
- @return `BITFeedbackListViewController` The feedback list view controller,
- e.g. to push it onto a navigation stack.
- */
-- (BITFeedbackListViewController *)feedbackListViewController:(BOOL)modal;
-
-
-/**
- Present the modal feedback compose message user interface.
-
- @warning This methods needs to be called on the main thread!
- */
-- (void)showFeedbackComposeView;
-
-/**
- Present the modal feedback compose message user interface with the items given.
-
- All NSString-Content in the array will be concatenated and result in the message,
- while all UIImage and NSData-instances will be turned into attachments.
-
- Alternatively you can implement the `preparedItemsForFeedbackManager:` delegate method
- and call `showFeedbackComposeView` instead. If you use both, the items from the delegate method
- and the items passed with this method will be combined.
-
- @param items an NSArray with objects that should be attached
- @see `[BITFeedbackComposeViewController prepareWithItems:]`
- @see `BITFeedbackManagerDelegate preparedItemsForFeedbackManager:`
- @warning This methods needs to be called on the main thread!
- */
-- (void)showFeedbackComposeViewWithPreparedItems:(nullable NSArray *)items;
-
-/**
- Presents a modal feedback compose interface with a screenshot attached which is taken at the time of calling this method.
-
- This should be used when your own trigger fires. The following code should be used:
-
- [[BITHockeyManager sharedHockeyManager].feedbackManager showFeedbackComposeViewWithGeneratedScreenshot];
-
- @see feedbackObservationMode
- @warning This methods needs to be called on the main thread!
- */
-- (void)showFeedbackComposeViewWithGeneratedScreenshot;
-
-
-/**
- Create a feedback compose view
-
- This method also adds items from `feedbackComposerPreparedItems` and
- the `preparedItemsForFeedbackManager:` delegate methods to the instance of
- `BITFeedbackComposeViewController` that will be returned.
-
- Example to show a modal feedback compose UI with prefilled text
-
- BITFeedbackComposeViewController *feedbackCompose = [[BITHockeyManager sharedHockeyManager].feedbackManager feedbackComposeViewController];
-
- [feedbackCompose prepareWithItems:
- @[@"Adding some example default text and also adding a link.",
- [NSURL URLWithString:@"http://hockeayyp.net/"]]];
-
- UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:feedbackCompose];
- navController.modalPresentationStyle = UIModalPresentationFormSheet;
- [self presentViewController:navController animated:YES completion:nil];
-
- @return `BITFeedbackComposeViewController` The compose feedback view controller,
- e.g. to push it onto a navigation stack.
- */
-- (BITFeedbackComposeViewController *)feedbackComposeViewController;
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/submodules/HockeySDK-iOS/Classes/BITFeedbackManager.m b/submodules/HockeySDK-iOS/Classes/BITFeedbackManager.m
deleted file mode 100644
index 04f7d16bd6..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITFeedbackManager.m
+++ /dev/null
@@ -1,1302 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2016 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_FEEDBACK
-
-#import
-
-#import "HockeySDKPrivate.h"
-
-#import "BITFeedbackManager.h"
-#import "BITFeedbackMessageAttachment.h"
-#import "BITFeedbackManagerPrivate.h"
-#import "BITHockeyBaseManagerPrivate.h"
-
-#import "HockeySDKNullability.h"
-#import "BITHockeyHelper.h"
-#import "BITHockeyHelper+Application.h"
-#import "BITHockeyAppClient.h"
-
-#define kBITFeedbackUserDataAsked @"HockeyFeedbackUserDataAsked"
-#define kBITFeedbackDateOfLastCheck @"HockeyFeedbackDateOfLastCheck"
-#define kBITFeedbackMessages @"HockeyFeedbackMessages"
-#define kBITFeedbackToken @"HockeyFeedbackToken"
-#define kBITFeedbackUserID @"HockeyFeedbackuserID"
-#define kBITFeedbackName @"HockeyFeedbackName"
-#define kBITFeedbackEmail @"HockeyFeedbackEmail"
-#define kBITFeedbackLastMessageID @"HockeyFeedbackLastMessageID"
-#define kBITFeedbackAppID @"HockeyFeedbackAppID"
-
-NSString *const kBITFeedbackUpdateAttachmentThumbnail = @"BITFeedbackUpdateAttachmentThumbnail";
-
-typedef void (^BITLatestImageFetchCompletionBlock)(UIImage *_Nonnull latestImage);
-
-@interface BITFeedbackManager ()
-
-@property (nonatomic, strong) NSFileManager *fileManager;
-@property (nonatomic, copy) NSString *settingsFile;
-@property (nonatomic, weak) id appDidBecomeActiveObserver;
-@property (nonatomic, weak) id appDidEnterBackgroundObserver;
-@property (nonatomic, weak) id networkDidBecomeReachableObserver;
-@property (nonatomic) BOOL incomingMessagesAlertShowing;
-@property (nonatomic) BOOL didEnterBackgroundState;
-@property (nonatomic) BOOL networkRequestInProgress;
-@property (nonatomic) BITFeedbackObservationMode observationMode;
-
-@end
-
-@implementation BITFeedbackManager
-
-#pragma mark - Initialization
-
-- (instancetype)init {
- if ((self = [super init])) {
- _currentFeedbackListViewController = nil;
- _currentFeedbackComposeViewController = nil;
- _didAskUserData = NO;
-
- _requireUserName = BITFeedbackUserDataElementOptional;
- _requireUserEmail = BITFeedbackUserDataElementOptional;
- _showAlertOnIncomingMessages = YES;
- _showFirstRequiredPresentationModal = YES;
-
- _disableFeedbackManager = NO;
- _networkRequestInProgress = NO;
- _incomingMessagesAlertShowing = NO;
- _lastCheck = nil;
- _token = nil;
- _lastMessageID = nil;
-
- self.feedbackList = [NSMutableArray array];
-
- _fileManager = [[NSFileManager alloc] init];
-
- _settingsFile = [bit_settingsDir() stringByAppendingPathComponent:BITHOCKEY_FEEDBACK_SETTINGS];
-
- _userID = nil;
- _userName = nil;
- _userEmail = nil;
- }
- return self;
-}
-
-- (void)dealloc {
- [self unregisterObservers];
-}
-
-- (void)didBecomeActiveActions {
- if ([self isFeedbackManagerDisabled]) return;
- if (!self.didEnterBackgroundState) return;
-
- self.didEnterBackgroundState = NO;
-
- if ([self.feedbackList count] == 0) {
- [self loadMessages];
- } else {
- [self updateAppDefinedUserData];
- }
-
- if ([self allowFetchingNewMessages]) {
- [self updateMessagesList];
- }
-}
-
-- (void)didEnterBackgroundActions {
- self.didEnterBackgroundState = NO;
-
- if ([BITHockeyHelper applicationState] == BITApplicationStateBackground) {
- self.didEnterBackgroundState = YES;
- }
-}
-
-#pragma mark - Observers
-
-- (void)registerObservers {
- __weak typeof(self) weakSelf = self;
- if (nil == self.appDidEnterBackgroundObserver) {
- self.appDidEnterBackgroundObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidEnterBackgroundNotification
- object:nil
- queue:NSOperationQueue.mainQueue
- usingBlock:^(NSNotification __unused *note) {
- typeof(self) strongSelf = weakSelf;
- [strongSelf didEnterBackgroundActions];
- }];
- }
- if (nil == self.appDidBecomeActiveObserver) {
- self.appDidBecomeActiveObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification
- object:nil
- queue:NSOperationQueue.mainQueue
- usingBlock:^(NSNotification __unused *note) {
- typeof(self) strongSelf = weakSelf;
- [strongSelf didBecomeActiveActions];
- }];
- }
- if (nil == self.networkDidBecomeReachableObserver) {
- self.networkDidBecomeReachableObserver = [[NSNotificationCenter defaultCenter] addObserverForName:BITHockeyNetworkDidBecomeReachableNotification
- object:nil
- queue:NSOperationQueue.mainQueue
- usingBlock:^(NSNotification __unused *note) {
- typeof(self) strongSelf = weakSelf;
- [strongSelf didBecomeActiveActions];
- }];
- }
-}
-
-- (void)unregisterObservers {
- id strongDidEnterBackgroundObserver = self.appDidEnterBackgroundObserver;
- id strongDidBecomeActiveObserver = self.appDidBecomeActiveObserver;
- id strongNetworkDidBecomeReachableObserver = self.networkDidBecomeReachableObserver;
- if (strongDidEnterBackgroundObserver) {
- [[NSNotificationCenter defaultCenter] removeObserver:strongDidEnterBackgroundObserver];
- self.appDidEnterBackgroundObserver = nil;
- }
- if (strongDidBecomeActiveObserver) {
- [[NSNotificationCenter defaultCenter] removeObserver:strongDidBecomeActiveObserver];
- self.appDidBecomeActiveObserver = nil;
- }
- if (strongNetworkDidBecomeReachableObserver) {
- [[NSNotificationCenter defaultCenter] removeObserver:strongNetworkDidBecomeReachableObserver];
- self.networkDidBecomeReachableObserver = nil;
- }
-}
-
-#pragma mark - Private methods
-
-- (NSString *)uuidString {
- CFUUIDRef theToken = CFUUIDCreate(NULL);
- NSString *stringUUID = (__bridge_transfer NSString *) CFUUIDCreateString(NULL, theToken);
- CFRelease(theToken);
-
- return stringUUID;
-}
-
-- (NSString *)uuidAsLowerCaseAndShortened {
- return [[[self uuidString] lowercaseString] stringByReplacingOccurrencesOfString:@"-" withString:@""];
-}
-
-#pragma mark - Feedback Modal UI
-
-- (UIImage *)screenshot {
- return bit_screenshot();
-}
-
-- (BITFeedbackListViewController *)feedbackListViewController:(BOOL)modal {
- return [[BITFeedbackListViewController alloc] initWithStyle:UITableViewStyleGrouped modal:modal];
-}
-
-- (void)showFeedbackListView {
- if (self.currentFeedbackListViewController) {
- BITHockeyLogDebug(@"INFO: update view already visible, aborting");
- return;
- }
- dispatch_async(dispatch_get_main_queue(), ^{
- [self showView:[self feedbackListViewController:YES]];
- });
-}
-
-
-- (BITFeedbackComposeViewController *)feedbackComposeViewController {
- BITFeedbackComposeViewController *composeViewController = [[BITFeedbackComposeViewController alloc] init];
-
- NSArray *preparedItems = [NSArray array];
- id strongDelegate = self.delegate;
- if ([strongDelegate respondsToSelector:@selector(preparedItemsForFeedbackManager:)]) {
- preparedItems = [preparedItems arrayByAddingObjectsFromArray:(NSArray *)[strongDelegate preparedItemsForFeedbackManager:self]];
- }
-
- [composeViewController prepareWithItems:preparedItems];
- [composeViewController setHideImageAttachmentButton:self.feedbackComposeHideImageAttachmentButton];
-
- // by default set the delegate to be identical to the one of BITFeedbackManager
- [composeViewController setDelegate:strongDelegate];
- return composeViewController;
-}
-
-- (void)showFeedbackComposeView {
- [self showFeedbackComposeViewWithPreparedItems:nil];
-}
-
-- (void)showFeedbackComposeViewWithPreparedItems:(NSArray *)items {
- if (self.currentFeedbackComposeViewController) {
- BITHockeyLogDebug(@"INFO: Feedback view already visible, aborting");
- return;
- }
- BITFeedbackComposeViewController *composeView = [self feedbackComposeViewController];
- [composeView prepareWithItems:items];
- dispatch_async(dispatch_get_main_queue(), ^{
- [self showView:composeView];
- });
-}
-
-- (void)showFeedbackComposeViewWithGeneratedScreenshot {
- UIImage *screenshot = bit_screenshot();
- [self showFeedbackComposeViewWithPreparedItems:@[screenshot]];
-}
-
-#pragma mark - Manager Control
-
-- (void)startManager {
- if ([self isFeedbackManagerDisabled]) return;
-
- [self registerObservers];
-
- [self isiOS10PhotoPolicySet];
-
- // we are already delayed, so the notification already came in and this won't invoked twice
- switch ([BITHockeyHelper applicationState]) {
- case BITApplicationStateActive:
- // we did startup, so yes we are coming from background
- self.didEnterBackgroundState = YES;
-
- [self didBecomeActiveActions];
- break;
- case BITApplicationStateBackground:
- case BITApplicationStateInactive:
- case BITApplicationStateUnknown:
- // do nothing, wait for active state
- break;
- }
-}
-
-- (BOOL)allowFetchingNewMessages {
- BOOL fetchNewMessages = YES;
- id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate;
- if ([strongDelegate respondsToSelector:@selector(allowAutomaticFetchingForNewFeedbackForManager:)]) {
- fetchNewMessages = [strongDelegate allowAutomaticFetchingForNewFeedbackForManager:self];
- }
- return fetchNewMessages;
-}
-
-- (void)updateMessagesList {
- if (self.networkRequestInProgress) return;
-
- NSArray *pendingMessages = [self messagesWithStatus:BITFeedbackMessageStatusSendPending];
- if ([pendingMessages count] > 0) {
- [self submitPendingMessages];
- } else {
- [self fetchMessageUpdates];
- }
-}
-
-- (void)updateMessagesListIfRequired {
- double now = [[NSDate date] timeIntervalSince1970];
- if ((now - [self.lastCheck timeIntervalSince1970] > 30)) {
- [self updateMessagesList];
- }
-}
-
-- (BOOL)updateUserIDUsingKeychainAndDelegate {
- BOOL availableViaDelegate = NO;
-
- NSString *userID = [self stringValueFromKeychainForKey:kBITHockeyMetaUserID];
- id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate;
- if ([strongDelegate respondsToSelector:@selector(userIDForHockeyManager:componentManager:)]) {
- userID = [strongDelegate userIDForHockeyManager:[BITHockeyManager sharedHockeyManager] componentManager:self];
- }
-
- if (userID) {
- availableViaDelegate = YES;
- self.userID = userID;
- }
-
- return availableViaDelegate;
-}
-
-- (BOOL)updateUserNameUsingKeychainAndDelegate {
- BOOL availableViaDelegate = NO;
-
- NSString *userName = [self stringValueFromKeychainForKey:kBITHockeyMetaUserName];
- id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate;
- if ([strongDelegate respondsToSelector:@selector(userNameForHockeyManager:componentManager:)]) {
- userName = [strongDelegate userNameForHockeyManager:[BITHockeyManager sharedHockeyManager] componentManager:self];
- }
-
- if (userName) {
- availableViaDelegate = YES;
- self.userName = userName;
- self.requireUserName = BITFeedbackUserDataElementDontShow;
- }
-
- return availableViaDelegate;
-}
-
-- (BOOL)updateUserEmailUsingKeychainAndDelegate {
- BOOL availableViaDelegate = NO;
-
- NSString *userEmail = [self stringValueFromKeychainForKey:kBITHockeyMetaUserEmail];
- id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate;
- if ([strongDelegate respondsToSelector:@selector(userEmailForHockeyManager:componentManager:)]) {
- userEmail = [strongDelegate userEmailForHockeyManager:[BITHockeyManager sharedHockeyManager] componentManager:self];
- }
-
- if (userEmail) {
- availableViaDelegate = YES;
- self.userEmail = userEmail;
- self.requireUserEmail = BITFeedbackUserDataElementDontShow;
- }
-
- return availableViaDelegate;
-}
-
-- (void)updateAppDefinedUserData {
- [self updateUserIDUsingKeychainAndDelegate];
- [self updateUserNameUsingKeychainAndDelegate];
- [self updateUserEmailUsingKeychainAndDelegate];
-
- // if both values are shown via the delegates, we never ever did ask and will never ever ask for user data
- if (self.requireUserName == BITFeedbackUserDataElementDontShow &&
- self.requireUserEmail == BITFeedbackUserDataElementDontShow) {
- self.didAskUserData = NO;
- }
-}
-
-- (BOOL)isiOS10PhotoPolicySet {
- BOOL isiOS10PhotoPolicySet = [BITHockeyHelper isPhotoAccessPossible];
- if (bit_isDebuggerAttached()) {
- if (!isiOS10PhotoPolicySet) {
- BITHockeyLogWarning(@"You are using HockeyApp's Feedback feature in iOS 10 or later. iOS 10 requires you to add the usage strings to your app's info.plist. "
- @"Attaching screenshots to feedback is disabled. Please add the String for NSPhotoLibraryUsageDescription to your info.plist to enable screenshot attachments.");
- }
- }
- return isiOS10PhotoPolicySet;
-}
-
-#pragma mark - Local Storage
-
-- (void)loadMessages {
- BOOL userIDViaDelegate = [self updateUserIDUsingKeychainAndDelegate];
- BOOL userNameViaDelegate = [self updateUserNameUsingKeychainAndDelegate];
- BOOL userEmailViaDelegate = [self updateUserEmailUsingKeychainAndDelegate];
-
- if (![self.fileManager fileExistsAtPath:self.settingsFile])
- return;
-
- NSData *codedData = [[NSData alloc] initWithContentsOfFile:self.settingsFile];
- if (codedData == nil) return;
-
- NSKeyedUnarchiver *unarchiver = nil;
-
- @try {
- unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:codedData];
- }
- @catch (NSException __unused *exception) {
- return;
- }
-
- if (!userIDViaDelegate) {
- if ([unarchiver containsValueForKey:kBITFeedbackUserID]) {
- self.userID = [unarchiver decodeObjectForKey:kBITFeedbackUserID];
- [self addStringValueToKeychain:self.userID forKey:kBITFeedbackUserID];
- }
- self.userID = [self stringValueFromKeychainForKey:kBITFeedbackUserID];
- }
-
- if (!userNameViaDelegate) {
- if ([unarchiver containsValueForKey:kBITFeedbackName]) {
- self.userName = [unarchiver decodeObjectForKey:kBITFeedbackName];
- [self addStringValueToKeychain:self.userName forKey:kBITFeedbackName];
- }
- self.userName = [self stringValueFromKeychainForKey:kBITFeedbackName];
- }
-
- if (!userEmailViaDelegate) {
- if ([unarchiver containsValueForKey:kBITFeedbackEmail]) {
- self.userEmail = [unarchiver decodeObjectForKey:kBITFeedbackEmail];
- [self addStringValueToKeychain:self.userEmail forKey:kBITFeedbackEmail];
- }
- self.userEmail = [self stringValueFromKeychainForKey:kBITFeedbackEmail];
- }
-
- if ([unarchiver containsValueForKey:kBITFeedbackUserDataAsked])
- self.didAskUserData = YES;
-
- if ([unarchiver containsValueForKey:kBITFeedbackToken]) {
- self.token = [unarchiver decodeObjectForKey:kBITFeedbackToken];
- [self addStringValueToKeychain:self.token forKey:kBITFeedbackToken];
- }
- self.token = [self stringValueFromKeychainForKey:kBITFeedbackToken];
-
- if ([unarchiver containsValueForKey:kBITFeedbackAppID]) {
- NSString *appID = [unarchiver decodeObjectForKey:kBITFeedbackAppID];
-
- // the stored thread is from another application identifier, so clear the token
- // which will cause the new posts to create a new thread on the server for the
- // current app identifier
- if ([appID compare:self.appIdentifier] != NSOrderedSame) {
- self.token = nil;
- }
- }
-
- if ([self shouldForceNewThread]) {
- self.token = nil;
- }
-
- if ([unarchiver containsValueForKey:kBITFeedbackDateOfLastCheck])
- self.lastCheck = [unarchiver decodeObjectForKey:kBITFeedbackDateOfLastCheck];
-
- if ([unarchiver containsValueForKey:kBITFeedbackLastMessageID])
- self.lastMessageID = [unarchiver decodeObjectForKey:kBITFeedbackLastMessageID];
-
- if ([unarchiver containsValueForKey:kBITFeedbackMessages]) {
- [self.feedbackList setArray:(NSArray *)[unarchiver decodeObjectForKey:kBITFeedbackMessages]];
-
- [self sortFeedbackList];
-
- // inform the UI to update its data in case the list is already showing
- [[NSNotificationCenter defaultCenter] postNotificationName:BITHockeyFeedbackMessagesLoadingFinished object:nil];
- }
-
- [unarchiver finishDecoding];
-
- if (!self.lastCheck) {
- self.lastCheck = [NSDate distantPast];
- }
-}
-
-
-- (void)saveMessages {
- [self sortFeedbackList];
-
- NSMutableData *data = [[NSMutableData alloc] init];
- NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
-
- if (self.didAskUserData)
- [archiver encodeObject:[NSNumber numberWithBool:YES] forKey:kBITFeedbackUserDataAsked];
-
- if (self.token)
- [self addStringValueToKeychain:self.token forKey:kBITFeedbackToken];
-
- if (self.appIdentifier)
- [archiver encodeObject:self.appIdentifier forKey:kBITFeedbackAppID];
-
- if (self.userID)
- [self addStringValueToKeychain:self.userID forKey:kBITFeedbackUserID];
-
- if (self.userName)
- [self addStringValueToKeychain:self.userName forKey:kBITFeedbackName];
-
- if (self.userEmail)
- [self addStringValueToKeychain:self.userEmail forKey:kBITFeedbackEmail];
-
- if (self.lastCheck)
- [archiver encodeObject:self.lastCheck forKey:kBITFeedbackDateOfLastCheck];
-
- if (self.lastMessageID)
- [archiver encodeObject:self.lastMessageID forKey:kBITFeedbackLastMessageID];
-
- [archiver encodeObject:self.feedbackList forKey:kBITFeedbackMessages];
-
- [archiver finishEncoding];
- [data writeToFile:self.settingsFile atomically:YES];
-}
-
-
-- (void)updateDidAskUserData {
- if (!self.didAskUserData) {
- self.didAskUserData = YES;
-
- [self saveMessages];
- }
-}
-
-#pragma mark - Messages
-
-- (void)sortFeedbackList {
- [self.feedbackList sortUsingComparator:^(BITFeedbackMessage *obj1, BITFeedbackMessage *obj2) {
- NSDate *date1 = [obj1 date];
- NSDate *date2 = [obj2 date];
-
- // not send, in conflict and send in progress messages on top, sorted by date
- // read and unread on bottom, sorted by date
- // archived on the very bottom
-
- if ([obj1 status] >= BITFeedbackMessageStatusSendInProgress && [obj2 status] < BITFeedbackMessageStatusSendInProgress) {
- return NSOrderedDescending;
- } else if ([obj1 status] < BITFeedbackMessageStatusSendInProgress && [obj2 status] >= BITFeedbackMessageStatusSendInProgress) {
- return NSOrderedAscending;
- } else if ([obj1 status] == BITFeedbackMessageStatusArchived && [obj2 status] < BITFeedbackMessageStatusArchived) {
- return NSOrderedDescending;
- } else if ([obj1 status] < BITFeedbackMessageStatusArchived && [obj2 status] == BITFeedbackMessageStatusArchived) {
- return NSOrderedAscending;
- } else {
- return (NSInteger) [date2 compare:date1];
- }
- }];
-}
-
-- (NSUInteger)numberOfMessages {
- return [self.feedbackList count];
-}
-
-- (BITFeedbackMessage *)messageAtIndex:(NSUInteger)index {
- if ([self.feedbackList count] > index) {
- return [self.feedbackList objectAtIndex:index];
- }
-
- return nil;
-}
-
-- (BITFeedbackMessage *)messageWithID:(NSNumber *)messageID {
- __block BITFeedbackMessage *message = nil;
-
- [self.feedbackList enumerateObjectsUsingBlock:^(BITFeedbackMessage *objMessage, NSUInteger __unused messagesIdx, BOOL *stop) {
- if ([[objMessage identifier] isEqualToNumber:messageID]) {
- message = objMessage;
- *stop = YES;
- }
- }];
-
- return message;
-}
-
-- (NSArray *)messagesWithStatus:(BITFeedbackMessageStatus)status {
- NSMutableArray *resultMessages = [[NSMutableArray alloc] initWithCapacity:[self.feedbackList count]];
-
- [self.feedbackList enumerateObjectsUsingBlock:^(BITFeedbackMessage *objMessage, NSUInteger __unused messagesIdx, BOOL __unused *stop) {
- if ([objMessage status] == status) {
- [resultMessages addObject:objMessage];
- }
- }];
-
- return [NSArray arrayWithArray:resultMessages];;
-}
-
-- (BITFeedbackMessage *)lastMessageHavingID {
- __block BITFeedbackMessage *message = nil;
-
-
- // Note: the logic here is slightly different than in our mac SDK, as self.feedbackList is sorted in different order.
- // Compare the implementation of - (void)sortFeedbackList; in both SDKs.
- [self.feedbackList enumerateObjectsUsingBlock:^(BITFeedbackMessage *objMessage, NSUInteger __unused messagesIdx, BOOL *stop) {
- if ([[objMessage identifier] integerValue] != 0) {
- message = objMessage;
- *stop = YES;
- }
- }];
-
- return message;
-}
-
-- (void)markSendInProgressMessagesAsPending {
- // make sure message that may have not been send successfully, get back into the right state to be send again
- [self.feedbackList enumerateObjectsUsingBlock:^(id objMessage, NSUInteger __unused messagesIdx, BOOL __unused *stop) {
- if ([(BITFeedbackMessage *) objMessage status] == BITFeedbackMessageStatusSendInProgress)
- [(BITFeedbackMessage *) objMessage setStatus:BITFeedbackMessageStatusSendPending];
- }];
-}
-
-- (void)markSendInProgressMessagesAsInConflict {
- // make sure message that may have not been send successfully, get back into the right state to be send again
- [self.feedbackList enumerateObjectsUsingBlock:^(id objMessage, NSUInteger __unused messagesIdx, BOOL __unused *stop) {
- if ([(BITFeedbackMessage *) objMessage status] == BITFeedbackMessageStatusSendInProgress)
- [(BITFeedbackMessage *) objMessage setStatus:BITFeedbackMessageStatusInConflict];
- }];
-}
-
-- (void)updateLastMessageID {
- BITFeedbackMessage *lastMessageHavingID = [self lastMessageHavingID];
- if (lastMessageHavingID) {
- if (!self.lastMessageID || [self.lastMessageID compare:[lastMessageHavingID identifier]] != NSOrderedSame)
- self.lastMessageID = [lastMessageHavingID identifier];
- }
-}
-
-- (BOOL)deleteMessageAtIndex:(NSUInteger)index {
- if (self.feedbackList && [self.feedbackList count] > index && [self.feedbackList objectAtIndex:index]) {
- BITFeedbackMessage *message = self.feedbackList[index];
- [message deleteContents];
- [self.feedbackList removeObjectAtIndex:index];
-
- [self saveMessages];
- return YES;
- }
-
- return NO;
-}
-
-- (void)deleteAllMessages {
- [self.feedbackList removeAllObjects];
-
- [self saveMessages];
-}
-
-- (BOOL)shouldForceNewThread {
- id strongDelegate = self.delegate;
- if (strongDelegate && [strongDelegate respondsToSelector:@selector(forceNewFeedbackThreadForFeedbackManager:)]) {
- return [strongDelegate forceNewFeedbackThreadForFeedbackManager:self];
- } else {
- return NO;
- }
-}
-
-
-#pragma mark - User
-
-- (BOOL)askManualUserDataAvailable {
- [self updateAppDefinedUserData];
-
- if (self.requireUserName == BITFeedbackUserDataElementDontShow &&
- self.requireUserEmail == BITFeedbackUserDataElementDontShow)
- return NO;
-
- return YES;
-}
-
-- (BOOL)requireManualUserDataMissing {
- [self updateAppDefinedUserData];
-
- if (self.requireUserName == BITFeedbackUserDataElementRequired && !self.userName)
- return YES;
-
- if (self.requireUserEmail == BITFeedbackUserDataElementRequired && !self.userEmail)
- return YES;
-
- return NO;
-}
-
-- (BOOL)isManualUserDataAvailable {
- [self updateAppDefinedUserData];
-
- if ((self.requireUserName != BITFeedbackUserDataElementDontShow && self.userName) ||
- (self.requireUserEmail != BITFeedbackUserDataElementDontShow && self.userEmail))
- return YES;
-
- return NO;
-}
-
-
-#pragma mark - Networking
-
-- (void)updateMessageListFromResponse:(NSDictionary *)jsonDictionary {
- if (!jsonDictionary) {
- // nil is used when the server returns 404, so we need to mark all existing threads as archives and delete the discussion token
-
- NSArray *messagesSendInProgress = [self messagesWithStatus:BITFeedbackMessageStatusSendInProgress];
- NSInteger pendingMessagesCount = [messagesSendInProgress count] + [[self messagesWithStatus:BITFeedbackMessageStatusSendPending] count];
-
- [self markSendInProgressMessagesAsPending];
-
- [self.feedbackList enumerateObjectsUsingBlock:^(id objMessage, NSUInteger __unused messagesIdx, BOOL __unused *stop) {
- if ([(BITFeedbackMessage *) objMessage status] != BITFeedbackMessageStatusSendPending)
- [(BITFeedbackMessage *) objMessage setStatus:BITFeedbackMessageStatusArchived];
- }];
-
- if ([self token]) {
- self.token = nil;
- }
-
- NSInteger pendingMessagesCountAfterProcessing = [[self messagesWithStatus:BITFeedbackMessageStatusSendPending] count];
-
- [self saveMessages];
-
- // check if this request was successful and we have more messages pending and continue if positive
- if (pendingMessagesCount > pendingMessagesCountAfterProcessing && pendingMessagesCountAfterProcessing > 0) {
- [self performSelector:@selector(submitPendingMessages) withObject:nil afterDelay:0.1];
- }
-
- return;
- }
-
- NSDictionary *feedback = [jsonDictionary objectForKey:@"feedback"];
- NSString *token = [jsonDictionary objectForKey:@"token"];
- NSDictionary *feedbackObject = [jsonDictionary objectForKey:@"feedback"];
- if (feedback && token && feedbackObject) {
- if ([self shouldForceNewThread]) {
- self.token = nil;
- } else {
- // update the thread token, which is not available until the 1st message was successfully sent
- self.token = token;
- }
-
- self.lastCheck = [NSDate date];
-
- // add all new messages
- NSArray *feedMessages = [feedbackObject objectForKey:@"messages"];
-
- // get the message that was currently sent if available
- NSArray *messagesSendInProgress = [self messagesWithStatus:BITFeedbackMessageStatusSendInProgress];
-
- NSInteger pendingMessagesCount = [messagesSendInProgress count] + [[self messagesWithStatus:BITFeedbackMessageStatusSendPending] count];
-
- __block BOOL newMessage = NO;
- NSMutableSet *returnedMessageIDs = [[NSMutableSet alloc] init];
-
- [feedMessages enumerateObjectsUsingBlock:^(id objMessage, NSUInteger __unused messagesIdx, BOOL __unused *stop) {
- if ([(NSDictionary *) objMessage objectForKey:@"id"]) {
- NSNumber *messageID = [(NSDictionary *) objMessage objectForKey:@"id"];
- [returnedMessageIDs addObject:messageID];
-
- BITFeedbackMessage *thisMessage = [self messageWithID:messageID];
- if (!thisMessage) {
- // check if this is a message that was sent right now
- __block BITFeedbackMessage *matchingSendInProgressOrInConflictMessage = nil;
-
- // TODO: match messages in state conflict
-
- [messagesSendInProgress enumerateObjectsUsingBlock:^(id objSendInProgressMessage, NSUInteger __unused messagesSendInProgressIdx, BOOL *stop2) {
- if ([[(NSDictionary *) objMessage objectForKey:@"token"] isEqualToString:[(BITFeedbackMessage *) objSendInProgressMessage token]]) {
- matchingSendInProgressOrInConflictMessage = objSendInProgressMessage;
- *stop2 = YES;
- }
- }];
-
- if (matchingSendInProgressOrInConflictMessage) {
- matchingSendInProgressOrInConflictMessage.date = [self parseRFC3339Date:[(NSDictionary *) objMessage objectForKey:@"created_at"]];
- matchingSendInProgressOrInConflictMessage.identifier = messageID;
- matchingSendInProgressOrInConflictMessage.status = BITFeedbackMessageStatusRead;
- NSArray *feedbackAttachments = [(NSDictionary *) objMessage objectForKey:@"attachments"];
- if (matchingSendInProgressOrInConflictMessage.attachments.count == feedbackAttachments.count) {
- int attachmentIndex = 0;
- for (BITFeedbackMessageAttachment *attachment in matchingSendInProgressOrInConflictMessage.attachments) {
- attachment.identifier = feedbackAttachments[attachmentIndex][@"id"];
- attachment.sourceURL = feedbackAttachments[attachmentIndex][@"url"];
- attachmentIndex++;
- }
- }
- } else {
- if ([(NSDictionary *) objMessage objectForKey:@"clean_text"] || [(NSDictionary *) objMessage objectForKey:@"text"] || [(NSDictionary *) objMessage objectForKey:@"attachments"]) {
- BITFeedbackMessage *message = [[BITFeedbackMessage alloc] init];
- message.text = [(NSDictionary *) objMessage objectForKey:@"clean_text"] ?: [(NSDictionary *) objMessage objectForKey:@"text"] ?: @"";
- message.name = [(NSDictionary *) objMessage objectForKey:@"name"] ?: @"";
- message.email = [(NSDictionary *) objMessage objectForKey:@"email"] ?: @"";
-
- message.date = [self parseRFC3339Date:[(NSDictionary *) objMessage objectForKey:@"created_at"]] ?: [NSDate date];
- message.identifier = [(NSDictionary *) objMessage objectForKey:@"id"];
- message.status = BITFeedbackMessageStatusUnread;
-
- for (NSDictionary *attachmentData in objMessage[@"attachments"]) {
- BITFeedbackMessageAttachment *newAttachment = [BITFeedbackMessageAttachment new];
- newAttachment.originalFilename = attachmentData[@"file_name"];
- newAttachment.identifier = attachmentData[@"id"];
- newAttachment.sourceURL = attachmentData[@"url"];
- newAttachment.contentType = attachmentData[@"content_type"];
- [message addAttachmentsObject:newAttachment];
- }
-
- [self.feedbackList addObject:message];
-
- newMessage = YES;
- }
- }
- } else {
- // we should never get any messages back that are already stored locally,
- // since we add the last_message_id to the request
- }
- }
- }];
-
- [self markSendInProgressMessagesAsPending];
-
- [self sortFeedbackList];
- [self updateLastMessageID];
-
- // we got a new incoming message, trigger user notification system
- if (newMessage) {
- // check if the latest message is from the users own email address, then don't show an alert since they answered using their own email
- BOOL latestMessageFromUser = NO;
-
- BITFeedbackMessage *latestMessage = [self lastMessageHavingID];
- if (self.userEmail && latestMessage.email && [self.userEmail compare:latestMessage.email] == NSOrderedSame)
- latestMessageFromUser = YES;
- id strongDelegate = self.delegate;
- if (!latestMessageFromUser) {
- if ([strongDelegate respondsToSelector:@selector(feedbackManagerDidReceiveNewFeedback:)]) {
- [strongDelegate feedbackManagerDidReceiveNewFeedback:self];
- }
-
- if (self.showAlertOnIncomingMessages && !self.currentFeedbackListViewController && !self.currentFeedbackComposeViewController) {
- dispatch_async(dispatch_get_main_queue(), ^{
- UIAlertController *alertController = [UIAlertController alertControllerWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackNewMessageTitle")
- message:BITHockeyLocalizedString(@"HockeyFeedbackNewMessageText")
- preferredStyle:UIAlertControllerStyleAlert];
- UIAlertAction *cancelAction = [BITAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackIgnore")
- style:UIAlertActionStyleCancel
- handler:nil];
- UIAlertAction *showAction = [BITAlertAction actionWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackShow")
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction __unused * __nonnull action) {
- [self showFeedbackListView];
- }];
- [alertController addAction:cancelAction];
- [alertController addAction:showAction];
-
- [self showAlertController:alertController];
- self.incomingMessagesAlertShowing = YES;
- });
- }
- }
- }
-
- NSInteger pendingMessagesCountAfterProcessing = [[self messagesWithStatus:BITFeedbackMessageStatusSendPending] count];
-
- // check if this request was successful and we have more messages pending and continue if positive
- if (pendingMessagesCount > pendingMessagesCountAfterProcessing && pendingMessagesCountAfterProcessing > 0) {
- [self performSelector:@selector(submitPendingMessages) withObject:nil afterDelay:0.1];
- }
-
- } else {
- [self markSendInProgressMessagesAsPending];
- }
-
- [self saveMessages];
-
- return;
-}
-
-
-- (void)sendNetworkRequestWithHTTPMethod:(NSString *)httpMethod withMessage:(BITFeedbackMessage *)message completionHandler:(void (^)(NSError *error))completionHandler {
- NSString *boundary = @"----FOO";
-
- self.networkRequestInProgress = YES;
- // inform the UI to update its data in case the list is already showing
- [[NSNotificationCenter defaultCenter] postNotificationName:BITHockeyFeedbackMessagesLoadingStarted object:nil];
-
- NSString *tokenParameter = @"";
- if ([self token]) {
- tokenParameter = [NSString stringWithFormat:@"/%@", [self token]];
- }
- NSMutableString *parameter = [NSMutableString stringWithFormat:@"api/2/apps/%@/feedback%@", [self encodedAppIdentifier], tokenParameter];
-
- NSString *lastMessageID = @"";
- if (!self.lastMessageID) {
- [self updateLastMessageID];
- }
- if (self.lastMessageID) {
- lastMessageID = [NSString stringWithFormat:@"&last_message_id=%li", (long) [self.lastMessageID integerValue]];
- }
-
- [parameter appendFormat:@"?format=json&bundle_version=%@&sdk=%@&sdk_version=%@%@",
- bit_URLEncodedString([[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]),
- BITHOCKEY_NAME,
- BITHOCKEY_VERSION,
- lastMessageID
- ];
-
- // build request & send
- NSString *url = [NSString stringWithFormat:@"%@%@", self.serverURL, parameter];
- BITHockeyLogDebug(@"INFO: sending api request to %@", url);
-
- NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:(NSURL *)[NSURL URLWithString:url] cachePolicy:1 timeoutInterval:10.0];
- [request setHTTPMethod:httpMethod];
- [request setValue:@"Hockey/iOS" forHTTPHeaderField:@"User-Agent"];
- [request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];
-
- if (message) {
- NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
- [request setValue:contentType forHTTPHeaderField:@"Content-type"];
-
- NSMutableData *postBody = [NSMutableData data];
-
- [postBody appendData:[BITHockeyAppClient dataWithPostValue:@"Apple" forKey:@"oem" boundary:boundary]];
- [postBody appendData:[BITHockeyAppClient dataWithPostValue:[[UIDevice currentDevice] systemVersion] forKey:@"os_version" boundary:boundary]];
- [postBody appendData:[BITHockeyAppClient dataWithPostValue:[self getDevicePlatform] forKey:@"model" boundary:boundary]];
- [postBody appendData:[BITHockeyAppClient dataWithPostValue:[[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0] forKey:@"lang" boundary:boundary]];
- [postBody appendData:[BITHockeyAppClient dataWithPostValue:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"] forKey:@"bundle_version" boundary:boundary]];
- [postBody appendData:[BITHockeyAppClient dataWithPostValue:[message text] forKey:@"text" boundary:boundary]];
- [postBody appendData:[BITHockeyAppClient dataWithPostValue:[message token] forKey:@"message_token" boundary:boundary]];
-
- NSString *installString = bit_appAnonID(NO);
- if (installString) {
- [postBody appendData:[BITHockeyAppClient dataWithPostValue:installString forKey:@"install_string" boundary:boundary]];
- }
-
- if (self.userID) {
- [postBody appendData:[BITHockeyAppClient dataWithPostValue:self.userID forKey:@"user_string" boundary:boundary]];
- }
- if (self.userName) {
- [postBody appendData:[BITHockeyAppClient dataWithPostValue:self.userName forKey:@"name" boundary:boundary]];
- }
- if (self.userEmail) {
- [postBody appendData:[BITHockeyAppClient dataWithPostValue:self.userEmail forKey:@"email" boundary:boundary]];
- }
-
-
- NSInteger photoIndex = 0;
-
- for (BITFeedbackMessageAttachment *attachment in message.attachments) {
- NSString *key = [NSString stringWithFormat:@"attachment%ld", (long) photoIndex];
-
- NSString *filename = attachment.originalFilename;
-
- if (!filename) {
- filename = [NSString stringWithFormat:@"Attachment %ld", (long) photoIndex];
- }
-
- [postBody appendData:[BITHockeyAppClient dataWithPostValue:attachment.data forKey:key contentType:attachment.contentType boundary:boundary filename:filename]];
-
- photoIndex++;
- }
-
- [postBody appendData:(NSData *)[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
-
-
- [request setHTTPBody:postBody];
- }
- __weak typeof(self) weakSelf = self;
- NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
- __block NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
-
- NSURLSessionDataTask *task = [session dataTaskWithRequest:request
- completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
- typeof(self) strongSelf = weakSelf;
-
- [session finishTasksAndInvalidate];
-
- [strongSelf handleFeedbackMessageResponse:response data:data error:error completion:completionHandler];
- }];
- [task resume];
-
-}
-
-- (void)handleFeedbackMessageResponse:(NSURLResponse *)response data:(NSData *)responseData error:(NSError *)error completion:(void (^)(NSError *error))completionHandler {
- self.networkRequestInProgress = NO;
-
- if (error) {
- [self reportError:error];
- [self markSendInProgressMessagesAsPending];
- if (completionHandler) {
- completionHandler(error);
- }
- } else {
- NSInteger statusCode = [(NSHTTPURLResponse *) response statusCode];
- if (statusCode == 404) {
- // thread has been deleted, we archive it
- [self updateMessageListFromResponse:nil];
- } else if (statusCode == 409) {
- // we submitted a message that is already on the server, mark it as being in conflict and resolve it with another fetch
-
- if (!self.token) {
- // set the token to the first message token, since this is identical
- __block NSString *token = nil;
-
- [self.feedbackList enumerateObjectsUsingBlock:^(id objMessage, NSUInteger __unused messagesIdx, BOOL *stop) {
- if ([(BITFeedbackMessage *) objMessage status] == BITFeedbackMessageStatusSendInProgress) {
- token = [(BITFeedbackMessage *) objMessage token];
- *stop = YES;
- }
- }];
-
- if (token) {
- self.token = token;
- }
- }
-
- [self markSendInProgressMessagesAsInConflict];
- [self saveMessages];
- [self performSelector:@selector(fetchMessageUpdates) withObject:nil afterDelay:0.2];
- } else if ([responseData length]) {
- NSString *responseString = [[NSString alloc] initWithBytes:[responseData bytes] length:[responseData length] encoding:NSUTF8StringEncoding];
- BITHockeyLogDebug(@"INFO: Received API response: %@", responseString);
-
- if (responseString && [responseString dataUsingEncoding:NSUTF8StringEncoding]) {
- NSError *localError = NULL;
-
- NSDictionary *feedDict = (NSDictionary *) [NSJSONSerialization JSONObjectWithData:(NSData *)[responseString dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&localError];
-
- // server returned empty response?
- if (localError) {
- [self reportError:localError];
- } else if (![feedDict count]) {
- [self reportError:[NSError errorWithDomain:kBITFeedbackErrorDomain
- code:BITFeedbackAPIServerReturnedEmptyResponse
- userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Server returned empty response.", NSLocalizedDescriptionKey, nil]]];
- } else {
- BITHockeyLogDebug(@"INFO: Received API response: %@", responseString);
- NSString *status = [feedDict objectForKey:@"status"];
- if ([status compare:@"success"] != NSOrderedSame) {
- [self reportError:[NSError errorWithDomain:kBITFeedbackErrorDomain
- code:BITFeedbackAPIServerReturnedInvalidStatus
- userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Server returned invalid status.", NSLocalizedDescriptionKey, nil]]];
- } else {
- [self updateMessageListFromResponse:feedDict];
- }
- }
- }
- }
-
- [self markSendInProgressMessagesAsPending];
- if (completionHandler) {
- completionHandler(error);
- }
- }
-}
-
-- (void)fetchMessageUpdates {
- if ([self.feedbackList count] == 0 && !self.token) {
- // inform the UI to update its data in case the list is already showing
- [[NSNotificationCenter defaultCenter] postNotificationName:BITHockeyFeedbackMessagesLoadingFinished object:nil];
-
- return;
- }
-
- [self sendNetworkRequestWithHTTPMethod:@"GET"
- withMessage:nil
- completionHandler:^(NSError __unused *error) {
- // inform the UI to update its data in case the list is already showing
- [[NSNotificationCenter defaultCenter] postNotificationName:BITHockeyFeedbackMessagesLoadingFinished object:nil];
- }];
-}
-
-- (void)submitPendingMessages {
- if (self.networkRequestInProgress) {
- [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(submitPendingMessages) object:nil];
- [self performSelector:@selector(submitPendingMessages) withObject:nil afterDelay:2.0];
- return;
- }
-
- // app defined user data may have changed, update it
- [self updateAppDefinedUserData];
- [self saveMessages];
-
- NSArray *pendingMessages = [self messagesWithStatus:BITFeedbackMessageStatusSendPending];
-
- if ([pendingMessages count] > 0) {
- // we send one message at a time
- BITFeedbackMessage *messageToSend = pendingMessages[0];
-
- [messageToSend setStatus:BITFeedbackMessageStatusSendInProgress];
- if (self.userID)
- [messageToSend setUserID:self.userID];
- if (self.userName)
- [messageToSend setName:self.userName];
- if (self.userEmail)
- [messageToSend setEmail:self.userEmail];
-
- NSString *httpMethod = @"POST";
- if ([self token]) {
- httpMethod = @"PUT";
- }
-
- [self sendNetworkRequestWithHTTPMethod:httpMethod
- withMessage:messageToSend
- completionHandler:^(NSError *error) {
- if (error) {
- [self markSendInProgressMessagesAsPending];
- [self saveMessages];
- }
-
- // inform the UI to update its data in case the list is already showing
- [[NSNotificationCenter defaultCenter] postNotificationName:BITHockeyFeedbackMessagesLoadingFinished object:nil];
- }];
- }
-}
-
-- (void)submitMessageWithText:(NSString *)text andAttachments:(NSArray *)attachments {
- BITFeedbackMessage *message = [[BITFeedbackMessage alloc] init];
- message.text = text;
- [message setStatus:BITFeedbackMessageStatusSendPending];
- [message setToken:[self uuidAsLowerCaseAndShortened]];
- [message setAttachments:attachments];
- [message setUserMessage:YES];
-
- [self.feedbackList addObject:message];
-
- [self submitPendingMessages];
-}
-
-#pragma mark - Observation Handling
-
-- (void)setFeedbackObservationMode:(BITFeedbackObservationMode)feedbackObservationMode {
- //Ignore if feedback manager is disabled
- if ([self isFeedbackManagerDisabled]) return;
-
- if (feedbackObservationMode != _feedbackObservationMode) {
- _feedbackObservationMode = feedbackObservationMode;
-
- // Reset the other observation modes.
- if (feedbackObservationMode == BITFeedbackObservationNone) {
- if (self.observationModeOnScreenshotEnabled) {
- [self setObservationModeOnScreenshotEnabled:NO];
- }
- if (self.observationModeThreeFingerTapEnabled) {
- [self setObservationModeThreeFingerTapEnabled:NO];
- }
- BITHockeyLogVerbose(@"Set feedbackObservationMode to BITFeedbackObservationNone");
- }
-
- if (feedbackObservationMode == BITFeedbackObservationModeOnScreenshot) {
- [self setObservationModeOnScreenshotEnabled:YES];
- if (self.observationModeThreeFingerTapEnabled) {
- [self setObservationModeThreeFingerTapEnabled:NO];
- }
- }
-
- if (feedbackObservationMode == BITFeedbackObservationModeThreeFingerTap) {
- [self setObservationModeThreeFingerTapEnabled:YES];
- if (self.observationModeOnScreenshotEnabled) {
- [self setObservationModeOnScreenshotEnabled:NO];
- }
- }
-
- if (feedbackObservationMode == BITFeedbackObservationModeAll) {
- [self setObservationModeOnScreenshotEnabled:YES];
- [self setObservationModeThreeFingerTapEnabled:YES];
- }
- }
-}
-
-- (void)setObservationModeOnScreenshotEnabled:(BOOL)observationModeOnScreenshotEnabled {
- // Enable/disable screenshot notification
- if (observationModeOnScreenshotEnabled) {
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(screenshotNotificationReceived:) name:UIApplicationUserDidTakeScreenshotNotification object:nil];
- BITHockeyLogVerbose(@"Added observer for UIApplocationUserDidTakeScreenshotNotification.");
- } else {
- [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationUserDidTakeScreenshotNotification object:nil];
- BITHockeyLogVerbose(@"Removed observer for UIApplocationUserDidTakeScreenshotNotification.");
- }
-
- _observationModeOnScreenshotEnabled = observationModeOnScreenshotEnabled;
-
- BITHockeyLogVerbose(@"Enabled BITFeedbackObservationModeOnScreenshot.");
-}
-
-- (void)setObservationModeThreeFingerTapEnabled:(BOOL)observationModeThreeFingerTapEnabled {
- _observationModeThreeFingerTapEnabled = observationModeThreeFingerTapEnabled;
-
- if (observationModeThreeFingerTapEnabled) {
- if (!self.tapRecognizer) {
- self.tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(screenshotTripleTap:)];
- self.tapRecognizer.numberOfTouchesRequired = 3;
- self.tapRecognizer.delegate = self;
-
- dispatch_async(dispatch_get_main_queue(), ^{
- if (self.tapRecognizer) {
- [[UIApplication sharedApplication].keyWindow addGestureRecognizer:self.tapRecognizer];
- }
- });
- }
-
- BITHockeyLogVerbose(@"Enabled BITFeedbackObservationModeThreeFingerTap.");
- } else {
- [[[UIApplication sharedApplication] keyWindow] removeGestureRecognizer:self.tapRecognizer];
- self.tapRecognizer = nil;
- BITHockeyLogVerbose(@"Disabled BITFeedbackObservationModeThreeFingerTap.");
- }
-}
-
-- (void)screenshotNotificationReceived:(NSNotification *) __unused notification {
- // Don't do anything if FeedbackManager was disabled.
- if ([self isFeedbackManagerDisabled]) return;
-
- double amountOfSeconds = 1.5;
- dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t) (amountOfSeconds * NSEC_PER_SEC));
-
- dispatch_after(delayTime, dispatch_get_main_queue(), ^{
- [self extractLastPictureFromLibraryAndLaunchFeedback];
- });
-}
-
-- (void)extractLastPictureFromLibraryAndLaunchFeedback {
- [self requestLatestImageWithCompletionHandler:^(UIImage *latestImage) {
- [self showFeedbackComposeViewWithPreparedItems:@[latestImage]];
- }];
-}
-
-- (void)requestLatestImageWithCompletionHandler:(BITLatestImageFetchCompletionBlock)completionHandler {
- if (!completionHandler) {return;}
-
- // Safeguard in case the dev hasn't set the NSPhotoLibraryUsageDescription in their Info.plist
- if (![self isiOS10PhotoPolicySet]) {return;}
-
- [self fetchLatestImageUsingPhotoLibraryWithCompletionHandler:completionHandler];
-}
-
-- (void)fetchLatestImageUsingPhotoLibraryWithCompletionHandler:(BITLatestImageFetchCompletionBlock)completionHandler {
- // Safeguard in case the dev hasn't set the NSPhotoLibraryUsageDescription in their Info.plist
- if (![self isiOS10PhotoPolicySet]) {return;}
-
- [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
- switch (status) {
- case PHAuthorizationStatusDenied:
- case PHAuthorizationStatusRestricted:
- BITHockeyLogDebug(@"INFO: The latest image could not be fetched, no permissions.");
- break;
-
- case PHAuthorizationStatusAuthorized:
- [self loadLatestImageAssetWithCompletionHandler:completionHandler];
- break;
- case PHAuthorizationStatusNotDetermined:
- BITHockeyLogDebug(@"INFO: The Photo Library authorization status is undetermined. This should not happen.");
- break;
- }
- }];
-}
-
-- (void)loadLatestImageAssetWithCompletionHandler:(BITLatestImageFetchCompletionBlock)completionHandler {
-
- // Safeguard in case the dev hasn't set the NSPhotoLibraryUsageDescription in their Info.plist
- if (![self isiOS10PhotoPolicySet]) {return;}
-
- PHImageManager *imageManager = PHImageManager.defaultManager;
-
- PHFetchOptions *fetchOptions = [PHFetchOptions new];
- fetchOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]];
-
- PHFetchResult *fetchResult = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:fetchOptions];
-
- if (fetchResult.count > 0) {
- PHAsset *latestImageAsset = (PHAsset *) fetchResult.lastObject;
- if (latestImageAsset) {
- PHImageRequestOptions *options = [PHImageRequestOptions new];
- options.version = PHImageRequestOptionsVersionOriginal;
- options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
- options.resizeMode = PHImageRequestOptionsResizeModeNone;
-
- [imageManager requestImageDataForAsset:latestImageAsset options:options resultHandler:^(NSData *_Nullable imageData, NSString *_Nullable __unused dataUTI, UIImageOrientation __unused orientation, NSDictionary *_Nullable __unused info) {
- if (imageData) {
- completionHandler((UIImage *)[UIImage imageWithData:(NSData *)imageData]);
- } else {
- BITHockeyLogDebug(@"INFO: The latest image could not be fetched, requested image data was empty.");
- }
- }];
- }
- } else {
- BITHockeyLogDebug(@"INFO: The latest image could not be fetched, the fetch result was empty.");
- }
-}
-
-- (void)screenshotTripleTap:(UITapGestureRecognizer *)tapRecognizer {
- // Don't do anything if FeedbackManager was disabled.
- if ([self isFeedbackManagerDisabled]) return;
-
- if (tapRecognizer.state == UIGestureRecognizerStateRecognized) {
- [self showFeedbackComposeViewWithGeneratedScreenshot];
- }
-}
-
-- (BOOL)gestureRecognizer:(UIGestureRecognizer *) __unused gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *) __unused otherGestureRecognizer {
- return YES;
-}
-
-@end
-
-
-#endif /* HOCKEYSDK_FEATURE_FEEDBACK */
diff --git a/submodules/HockeySDK-iOS/Classes/BITFeedbackManagerDelegate.h b/submodules/HockeySDK-iOS/Classes/BITFeedbackManagerDelegate.h
deleted file mode 100644
index 9afb889462..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITFeedbackManagerDelegate.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Authors: Stephan Diederich, Benjamin Scholtysik
- *
- * Copyright (c) 2013-2016 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import
-#import "BITFeedbackComposeViewControllerDelegate.h"
-
-#import "HockeySDKNullability.h"
-NS_ASSUME_NONNULL_BEGIN
-
-@class BITFeedbackManager;
-
-/**
- * Delegate protocol which is notified about changes in the feedbackManager
- * @TODO
- * * move shouldShowUpdateAlert from feedbackManager here
- */
-@protocol BITFeedbackManagerDelegate
-
-@optional
-
-/**
- * Can be implemented to control wether the feedback manager should automatically
- * fetch for new messages on app startup or when becoming active.
- *
- * By default the SDK fetches on app startup or when the app is becoming active again
- * if there are already messages existing or pending on the device.
- *
- * You could disable it e.g. depending on available mobile network/WLAN connection
- * or let it fetch less frequently.
- *
- * @param feedbackManager The feedbackManager which did detect the new messages
- */
-- (BOOL)allowAutomaticFetchingForNewFeedbackForManager:(BITFeedbackManager *)feedbackManager;
-
-
-/**
- * can be implemented to know when new feedback from the server arrived
- *
- * @param feedbackManager The feedbackManager which did detect the new messages
- */
-- (void)feedbackManagerDidReceiveNewFeedback:(BITFeedbackManager *)feedbackManager;
-
-
-/**
- * This optional method can be implemented to provide items to prefill
- * the FeedbackComposeMessage user interface with the given items.
- *
- * If the user sends the feedback message, these items will be attached to that message.
- *
- * All NSString-Content in the array will be concatenated and result in the message,
- * while all UIImage and NSData-instances will be turned into attachments.
- *
- * @param feedbackManager The BITFeedbackManager instance that will handle sending the feedback.
- *
- * @return An array containing the items to be attached to the feedback message
- * @see `[BITFeedbackComposeViewController prepareWithItems:]
- */
-- (nullable NSArray *)preparedItemsForFeedbackManager:(BITFeedbackManager *)feedbackManager;
-
-/**
- * Indicates if a new thread should be created for each new feedback message
- *
- * Setting it to `YES` will force a new thread whenever a new message is sent as
- * opposed to the default resume thread behaviour.
- *
- * @return A BOOL indicating if each feedback message should be sent as a new thread.
- */
-- (BOOL)forceNewFeedbackThreadForFeedbackManager:(BITFeedbackManager *)feedbackManager;
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/submodules/HockeySDK-iOS/Classes/BITFeedbackManagerPrivate.h b/submodules/HockeySDK-iOS/Classes/BITFeedbackManagerPrivate.h
deleted file mode 100644
index ab4bbe1935..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITFeedbackManagerPrivate.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Author: Andreas Linde
- * Kent Sutherland
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * Copyright (c) 2011 Andreas Linde & Kent Sutherland.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#if HOCKEYSDK_FEATURE_FEEDBACK
-
-extern NSString *const kBITFeedbackUpdateAttachmentThumbnail;
-
-#import "BITFeedbackMessage.h"
-
-@class UITapGestureRecognizer;
-
-@interface BITFeedbackManager () {
-}
-
-
-///-----------------------------------------------------------------------------
-/// @name Delegate
-///-----------------------------------------------------------------------------
-
-/**
- Sets the `BITFeedbackManagerDelegate` delegate.
-
- Can be set to be notified when new feedback is received from the server.
-
- The delegate is automatically set by using `[BITHockeyManager setDelegate:]`. You
- should not need to set this delegate individually.
-
- @see `[BITHockeyManager setDelegate:]`
- */
-@property (nonatomic, weak) id delegate;
-
-
-@property (nonatomic, strong) NSMutableArray *feedbackList;
-@property (nonatomic, copy) NSString *token;
-
-
-// used by BITHockeyManager if disable status is changed
-@property (nonatomic, getter = isFeedbackManagerDisabled) BOOL disableFeedbackManager;
-// TapRecognizer used in case feedback observation mode is BITFeedbackObservationModeThreeFingerTap is set.
-@property(nonatomic, strong) UITapGestureRecognizer *tapRecognizer;
-@property(nonatomic) BOOL observationModeOnScreenshotEnabled;
-@property(nonatomic) BOOL observationModeThreeFingerTapEnabled;
-
-
-@property (nonatomic, strong) BITFeedbackListViewController *currentFeedbackListViewController;
-@property (nonatomic, strong) BITFeedbackComposeViewController *currentFeedbackComposeViewController;
-@property (nonatomic) BOOL didAskUserData;
-
-@property (nonatomic, strong) NSDate *lastCheck;
-
-@property (nonatomic, strong) NSNumber *lastMessageID;
-
-@property (nonatomic, copy) NSString *userID;
-@property (nonatomic, copy) NSString *userName;
-@property (nonatomic, copy) NSString *userEmail;
-
-
-
-// Fetch user meta data
-- (BOOL)updateUserIDUsingKeychainAndDelegate;
-- (BOOL)updateUserNameUsingKeychainAndDelegate;
-- (BOOL)updateUserEmailUsingKeychainAndDelegate;
-
-// check if the user wants to influence when fetching of new messages may be done
-- (BOOL)allowFetchingNewMessages;
-
-// load new messages from the server
-- (void)updateMessagesList;
-
-// load new messages from the server if the last request is too long ago
-- (void)updateMessagesListIfRequired;
-
-- (NSUInteger)numberOfMessages;
-- (BITFeedbackMessage *)messageAtIndex:(NSUInteger)index;
-
-- (void)submitMessageWithText:(NSString *)text andAttachments:(NSArray *)photos;
-- (void)submitPendingMessages;
-
-// Returns YES if manual user data can be entered, required or optional
-- (BOOL)askManualUserDataAvailable;
-
-// Returns YES if required user data is missing?
-- (BOOL)requireManualUserDataMissing;
-
-// Returns YES if user data is available and can be edited
-- (BOOL)isManualUserDataAvailable;
-
-// used in the user data screen
-- (void)updateDidAskUserData;
-
-
-- (BITFeedbackMessage *)messageWithID:(NSNumber *)messageID;
-
-- (NSArray *)messagesWithStatus:(BITFeedbackMessageStatus)status;
-
-- (void)saveMessages;
-
-- (void)fetchMessageUpdates;
-- (void)updateMessageListFromResponse:(NSDictionary *)jsonDictionary;
-
-- (BOOL)deleteMessageAtIndex:(NSUInteger)index;
-- (void)deleteAllMessages;
-
-@end
-
-#endif /* HOCKEYSDK_FEATURE_FEEDBACK */
diff --git a/submodules/HockeySDK-iOS/Classes/BITFeedbackMessage.h b/submodules/HockeySDK-iOS/Classes/BITFeedbackMessage.h
deleted file mode 100644
index c33caa983d..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITFeedbackMessage.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#import
-
-@class BITFeedbackMessageAttachment;
-
-/**
- * Status for each feedback message
- */
-typedef NS_ENUM(NSInteger, BITFeedbackMessageStatus) {
- /**
- * default and new messages from SDK per default
- */
- BITFeedbackMessageStatusSendPending = 0,
- /**
- * message is in conflict, happens if the message is already stored on the server and tried sending it again
- */
- BITFeedbackMessageStatusInConflict = 1,
- /**
- * sending of message is in progress
- */
- BITFeedbackMessageStatusSendInProgress = 2,
- /**
- * new messages from server
- */
- BITFeedbackMessageStatusUnread = 3,
- /**
- * messages from server once read and new local messages once successful send from SDK
- */
- BITFeedbackMessageStatusRead = 4,
- /**
- * message is archived, happens if the thread is deleted from the server
- */
- BITFeedbackMessageStatusArchived = 5
-};
-
-/**
- * An individual feedback message
- */
-@interface BITFeedbackMessage : NSObject {
-}
-
-@property (nonatomic, copy) NSString *text;
-@property (nonatomic, copy) NSString *userID;
-@property (nonatomic, copy) NSString *name;
-@property (nonatomic, copy) NSString *email;
-@property (nonatomic, copy) NSDate *date;
-@property (nonatomic, copy) NSNumber *identifier;
-@property (nonatomic, copy) NSString *token;
-@property (nonatomic, strong) NSArray *attachments;
-@property (nonatomic) BITFeedbackMessageStatus status;
-@property (nonatomic) BOOL userMessage;
-
-/**
- Delete local cached attachment data
-
- @warning This method must be called before a feedback message is deleted.
- */
-- (void)deleteContents;
-
-/**
- Add an attachment to a message
-
- @param object BITFeedbackMessageAttachment instance representing the attachment that should be added
- */
-- (void)addAttachmentsObject:(BITFeedbackMessageAttachment *)object;
-
-/**
- Return the attachments that can be viewed
-
- @return NSArray containing the attachment objects that can be previewed
- */
-- (NSArray *)previewableAttachments;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITFeedbackMessage.m b/submodules/HockeySDK-iOS/Classes/BITFeedbackMessage.m
deleted file mode 100644
index e0c05c4055..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITFeedbackMessage.m
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_FEEDBACK
-
-#import "BITFeedbackMessage.h"
-#import "BITFeedbackMessageAttachment.h"
-
-@implementation BITFeedbackMessage
-
-
-#pragma mark - NSObject
-
-- (instancetype) init {
- if ((self = [super init])) {
- _text = nil;
- _userID = nil;
- _name = nil;
- _email = nil;
- _date = [[NSDate alloc] init];
- _token = nil;
- _attachments = nil;
- _identifier = [[NSNumber alloc] initWithInteger:0];
- _status = BITFeedbackMessageStatusSendPending;
- _userMessage = NO;
- }
- return self;
-}
-
-
-#pragma mark - NSCoder
-
-- (void)encodeWithCoder:(NSCoder *)encoder {
- [encoder encodeObject:self.text forKey:@"text"];
- [encoder encodeObject:self.userID forKey:@"userID"];
- [encoder encodeObject:self.name forKey:@"name"];
- [encoder encodeObject:self.email forKey:@"email"];
- [encoder encodeObject:self.date forKey:@"date"];
- [encoder encodeObject:self.identifier forKey:@"id"];
- [encoder encodeObject:self.attachments forKey:@"attachments"];
- [encoder encodeInteger:self.status forKey:@"status"];
- [encoder encodeBool:self.userMessage forKey:@"userMessage"];
- [encoder encodeObject:self.token forKey:@"token"];
-}
-
-- (instancetype)initWithCoder:(NSCoder *)decoder {
- if ((self = [self init])) {
- self.text = [decoder decodeObjectForKey:@"text"];
- self.userID = [decoder decodeObjectForKey:@"userID"];
- self.name = [decoder decodeObjectForKey:@"name"];
- self.email = [decoder decodeObjectForKey:@"email"];
- self.date = [decoder decodeObjectForKey:@"date"];
- self.identifier = [decoder decodeObjectForKey:@"id"];
- self.attachments = [decoder decodeObjectForKey:@"attachments"];
- self.status = (BITFeedbackMessageStatus)[decoder decodeIntegerForKey:@"status"];
- self.userMessage = [decoder decodeBoolForKey:@"userMessage"];
- self.token = [decoder decodeObjectForKey:@"token"];
- }
- return self;
-}
-
-#pragma mark - Deletion
-
-- (void)deleteContents {
- for (BITFeedbackMessageAttachment *attachment in self.attachments){
- [attachment deleteContents];
- }
-}
-
-- (NSArray *)previewableAttachments {
- NSMutableArray *returnArray = [NSMutableArray new];
-
- for (BITFeedbackMessageAttachment *attachment in self.attachments){
- if ([QLPreviewController canPreviewItem:attachment ]){
- [returnArray addObject:attachment];
- }
- }
-
- return returnArray;
-}
-
-- (void)addAttachmentsObject:(BITFeedbackMessageAttachment *)object{
- if (!self.attachments){
- self.attachments = [NSArray array];
- }
- self.attachments = [self.attachments arrayByAddingObject:object];
-}
-
-
-@end
-
-#endif /* HOCKEYSDK_FEATURE_FEEDBACK */
diff --git a/submodules/HockeySDK-iOS/Classes/BITFeedbackMessageAttachment.h b/submodules/HockeySDK-iOS/Classes/BITFeedbackMessageAttachment.h
deleted file mode 100644
index bdfaec0085..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITFeedbackMessageAttachment.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Author: Moritz Haarmann
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import
-#import
-#import
-
-/**
- * An individual feedback message attachment
- */
-@interface BITFeedbackMessageAttachment : NSObject
-
-@property (nonatomic, copy) NSNumber *identifier;
-@property (nonatomic, copy) NSString *originalFilename;
-@property (nonatomic, copy) NSString *contentType;
-@property (nonatomic, copy) NSString *sourceURL;
-@property (nonatomic) BOOL isLoading;
-@property (nonatomic, readonly) NSData *data;
-
-
-@property (nonatomic, readonly) UIImage *imageRepresentation;
-
-
-+ (BITFeedbackMessageAttachment *)attachmentWithData:(NSData *)data contentType:(NSString *)contentType;
-
-- (UIImage *)thumbnailWithSize:(CGSize)size;
-
-- (void)replaceData:(NSData *)data;
-
-- (void)deleteContents;
-
-- (BOOL)needsLoadingFromURL;
-
-- (BOOL)isImage;
-
-- (NSURL *)localURL;
-
-/**
- Used to determine whether QuickLook can preview this file or not. If not, we don't download it.
- */
-- (NSString*)possibleFilename;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITFeedbackMessageAttachment.m b/submodules/HockeySDK-iOS/Classes/BITFeedbackMessageAttachment.m
deleted file mode 100644
index 1ea27ed79d..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITFeedbackMessageAttachment.m
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Author: Moritz Haarmann
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_FEEDBACK
-
-#import "BITFeedbackMessageAttachment.h"
-#import "BITHockeyHelper.h"
-#import "HockeySDKPrivate.h"
-#import
-
-#define kCacheFolderName @"attachments"
-
-@interface BITFeedbackMessageAttachment()
-
-@property (nonatomic, strong) NSMutableDictionary *thumbnailRepresentations;
-@property (nonatomic, strong) NSData *internalData;
-@property (nonatomic, copy) NSString *filename;
-@property (nonatomic, copy) NSString *tempFilename;
-@property (nonatomic, copy) NSString *cachePath;
-@property (nonatomic, strong) NSFileManager *fm;
-
-@end
-
-@implementation BITFeedbackMessageAttachment
-
-+ (BITFeedbackMessageAttachment *)attachmentWithData:(NSData *)data contentType:(NSString *)contentType {
-
- static NSDateFormatter *formatter;
-
- if(!formatter) {
- formatter = [NSDateFormatter new];
- formatter.dateStyle = NSDateFormatterShortStyle;
- formatter.timeStyle = NSDateFormatterShortStyle;
- }
-
- BITFeedbackMessageAttachment *newAttachment = [BITFeedbackMessageAttachment new];
- newAttachment.contentType = contentType;
- newAttachment.data = data;
- newAttachment.originalFilename = [NSString stringWithFormat:@"Attachment: %@", [formatter stringFromDate:[NSDate date]]];
-
- return newAttachment;
-}
-
-- (instancetype)init {
- if ((self = [super init])) {
- _isLoading = NO;
- _thumbnailRepresentations = [NSMutableDictionary new];
-
- _fm = [[NSFileManager alloc] init];
- _cachePath = [bit_settingsDir() stringByAppendingPathComponent:kCacheFolderName];
-
- BOOL isDirectory;
-
- if (![_fm fileExistsAtPath:_cachePath isDirectory:&isDirectory]){
- [_fm createDirectoryAtPath:_cachePath withIntermediateDirectories:YES attributes:nil error:nil];
- }
-
- }
- return self;
-}
-
-- (void)setData:(NSData *)data {
- self.internalData = data;
- self.filename = [self possibleFilename];
- [self.internalData writeToFile:self.filename atomically:YES];
-}
-
-- (NSData *)data {
- if (!self.internalData && self.filename) {
- self.internalData = [NSData dataWithContentsOfFile:self.filename];
- }
-
- if (self.internalData) {
- return self.internalData;
- }
-
- return [NSData data];
-}
-
-- (void)replaceData:(NSData *)data {
- self.data = data;
- self.thumbnailRepresentations = [NSMutableDictionary new];
-}
-
-- (BOOL)needsLoadingFromURL {
- return (self.sourceURL && ![self.fm fileExistsAtPath:(NSString *)[self.localURL path]]);
-}
-
-- (BOOL)isImage {
- return ([self.contentType rangeOfString:@"image"].location != NSNotFound);
-}
-
-- (NSURL *)localURL {
- if (self.filename && [self.fm fileExistsAtPath:self.filename]) {
- return [NSURL fileURLWithPath:self.filename];
- }
-
- return [NSURL URLWithString:@""];
-}
-
-
-#pragma mark NSCoding
-
-- (void)encodeWithCoder:(NSCoder *)aCoder {
- [aCoder encodeObject:self.contentType forKey:@"contentType"];
- [aCoder encodeObject:self.filename forKey:@"filename"];
- [aCoder encodeObject:self.originalFilename forKey:@"originalFilename"];
- [aCoder encodeObject:self.sourceURL forKey:@"url"];
-}
-
-- (instancetype)initWithCoder:(NSCoder *)aDecoder {
- if ((self = [self init])) {
- self.contentType = [aDecoder decodeObjectForKey:@"contentType"];
- self.filename = [aDecoder decodeObjectForKey:@"filename"];
- self.thumbnailRepresentations = [NSMutableDictionary new];
- self.originalFilename = [aDecoder decodeObjectForKey:@"originalFilename"];
- self.sourceURL = [aDecoder decodeObjectForKey:@"url"];
- }
-
- return self;
-}
-
-
-#pragma mark - Thumbnails / Image Representation
-
-- (UIImage *)imageRepresentation {
- if ([self.contentType rangeOfString:@"image"].location != NSNotFound && self.filename ) {
- return [UIImage imageWithData:self.data];
- } else {
- // Create a Icon ..
- UIDocumentInteractionController* docController = [[UIDocumentInteractionController alloc] init];
- docController.name = self.originalFilename;
- NSArray* icons = docController.icons;
- if (icons.count){
- return icons[0];
- } else {
- return nil;
- }
- }
-}
-
-- (UIImage *)thumbnailWithSize:(CGSize)size {
- id cacheKey = [NSValue valueWithCGSize:size];
-
- if (!self.thumbnailRepresentations[cacheKey]) {
- UIImage *image = self.imageRepresentation;
- // consider the scale.
- if (!image) {
- return nil;
- }
-
- CGFloat scale = [UIScreen mainScreen].scale;
-
- if (scale != image.scale) {
-
- CGSize scaledSize = CGSizeApplyAffineTransform(size, CGAffineTransformMakeScale(scale, scale));
- UIImage *thumbnail = bit_imageToFitSize(image, scaledSize, YES) ;
-
- UIImage *scaledThumbnail = [UIImage imageWithCGImage:(CGImageRef)thumbnail.CGImage scale:scale orientation:thumbnail.imageOrientation];
- if (thumbnail) {
- [self.thumbnailRepresentations setObject:scaledThumbnail forKey:cacheKey];
- }
-
- } else {
- UIImage *thumbnail = bit_imageToFitSize(image, size, YES) ;
-
- [self.thumbnailRepresentations setObject:thumbnail forKey:cacheKey];
-
- }
-
- }
-
- return self.thumbnailRepresentations[cacheKey];
-}
-
-
-#pragma mark - Persistence Helpers
-
-- (void)setFilename:(NSString *)filename {
- if (filename) {
- filename = [self.cachePath stringByAppendingPathComponent:[filename lastPathComponent]];
- }
- _filename = filename;
-}
-
-- (NSString *)possibleFilename {
- if (self.tempFilename) {
- return self.tempFilename;
- }
-
- NSString *uniqueString = bit_UUID();
- self.tempFilename = [self.cachePath stringByAppendingPathComponent:uniqueString];
-
- // File extension that suits the Content type.
-
- CFStringRef mimeType = (__bridge CFStringRef)self.contentType;
- if (mimeType) {
- CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType, NULL);
- CFStringRef extension = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassFilenameExtension);
- if (extension) {
- self.tempFilename = [self.tempFilename stringByAppendingPathExtension:(__bridge NSString *)(extension)];
- CFRelease(extension);
- }
- if (uti) {
- CFRelease(uti);
- }
- }
-
- return self.tempFilename;
-}
-
-- (void)deleteContents {
- if (self.filename) {
- [self.fm removeItemAtPath:self.filename error:nil];
- self.filename = nil;
- }
-}
-
-
-#pragma mark - QLPreviewItem
-
-- (NSString *)previewItemTitle {
- return self.originalFilename;
-}
-
-- (NSURL *)previewItemURL {
- if (self.localURL){
- return self.localURL;
- } else if (self.sourceURL) {
- NSString *filename = self.possibleFilename;
- if (filename) {
- return [NSURL fileURLWithPath:filename];
- }
- }
-
- return [NSURL URLWithString:(NSString *)[[NSBundle mainBundle] pathForResource:@"FeedbackPlaceholder" ofType:@"png"]];
-}
-
-@end
-
-#endif /* HOCKEYSDK_FEATURE_FEEDBACK */
diff --git a/submodules/HockeySDK-iOS/Classes/BITFeedbackUserDataViewController.h b/submodules/HockeySDK-iOS/Classes/BITFeedbackUserDataViewController.h
deleted file mode 100644
index 84128d086d..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITFeedbackUserDataViewController.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#import
-
-@protocol BITFeedbackUserDataDelegate;
-
-@interface BITFeedbackUserDataViewController : UITableViewController
-
-@property (nonatomic, weak) id delegate;
-
-@end
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-@protocol BITFeedbackUserDataDelegate
-
-@required
-
-// cancel action is invoked
-- (void)userDataUpdateCancelled;
-
-// save action is invoked and all required data available
-- (void)userDataUpdateFinished;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITFeedbackUserDataViewController.m b/submodules/HockeySDK-iOS/Classes/BITFeedbackUserDataViewController.m
deleted file mode 100644
index 4b49a7e1ee..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITFeedbackUserDataViewController.m
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_FEEDBACK
-
-#import "HockeySDKPrivate.h"
-#import "BITHockeyHelper.h"
-
-#import "BITFeedbackUserDataViewController.h"
-#import "BITFeedbackManagerPrivate.h"
-
-@interface BITFeedbackUserDataViewController () {
-}
-
-@property (nonatomic, weak) BITFeedbackManager *manager;
-
-@property (nonatomic, copy) NSString *name;
-@property (nonatomic, copy) NSString *email;
-@end
-
-
-@implementation BITFeedbackUserDataViewController
-
-
-- (instancetype)initWithStyle:(UITableViewStyle)style {
- self = [super initWithStyle:style];
- if (self) {
- _delegate = nil;
-
- _manager = [BITHockeyManager sharedHockeyManager].feedbackManager;
- _name = @"";
- _email = @"";
- }
- return self;
-}
-
-- (void)viewDidLoad {
- [super viewDidLoad];
-
- self.title = BITHockeyLocalizedString(@"HockeyFeedbackUserDataTitle");
-
- [self.tableView setScrollEnabled:NO];
-}
-
-- (void)viewWillAppear:(BOOL)animated {
- [super viewWillAppear:animated];
-
- // Do any additional setup after loading the view.
- self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
- target:self
- action:@selector(dismissAction:)];
-
- self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave
- target:self
- action:@selector(saveAction:)];
-
- BITFeedbackManager *strongManager = self.manager;
- if ([strongManager userName])
- self.name = [strongManager userName];
-
- if ([strongManager userEmail])
- self.email = [strongManager userEmail];
-
- [strongManager updateDidAskUserData];
-
- self.navigationItem.rightBarButtonItem.enabled = [self allRequiredFieldsEntered];
-}
-
-#pragma mark - UIViewController Rotation
-
-- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
- return UIInterfaceOrientationMaskAll;
-}
-
-#pragma mark - Private methods
-- (BOOL)allRequiredFieldsEntered {
- BITFeedbackManager *strongManager = self.manager;
- if ([strongManager requireUserName] == BITFeedbackUserDataElementRequired && [self.name length] == 0)
- return NO;
-
- if ([strongManager requireUserEmail] == BITFeedbackUserDataElementRequired && [self.email length] == 0)
- return NO;
-
- if ([self.email length] > 0 && !bit_validateEmail(self.email))
- return NO;
-
- return YES;
-}
-
-- (void)userNameEntered:(id)sender {
- self.name = [(UITextField *)sender text];
-
- self.navigationItem.rightBarButtonItem.enabled = [self allRequiredFieldsEntered];
-}
-
-- (void)userEmailEntered:(id)sender {
- self.email = [(UITextField *)sender text];
-
- self.navigationItem.rightBarButtonItem.enabled = [self allRequiredFieldsEntered];
-}
-
-- (void)dismissAction:(id) __unused sender {
- [self.delegate userDataUpdateCancelled];
-}
-
-- (void)saveAction:(id) __unused sender {
- BITFeedbackManager *strongManager = self.manager;
- if ([strongManager requireUserName]) {
- [strongManager setUserName:self.name];
- }
-
- if ([strongManager requireUserEmail]) {
- [strongManager setUserEmail:self.email];
- }
-
- [self.delegate userDataUpdateFinished];
-}
-
-#pragma mark - Table view data source
-
-- (NSInteger)numberOfSectionsInTableView:(UITableView *) __unused tableView {
- return 1;
-}
-
-- (NSInteger)tableView:(UITableView *) __unused tableView numberOfRowsInSection:(NSInteger) __unused section {
- NSInteger rows = 0;
- BITFeedbackManager *strongManager = self.manager;
- if ([strongManager requireUserName] != BITFeedbackUserDataElementDontShow)
- rows ++;
-
- if ([strongManager requireUserEmail] != BITFeedbackUserDataElementDontShow)
- rows ++;
-
- return rows;
-}
-
-- (NSString *)tableView:(UITableView *) __unused tableView titleForFooterInSection:(NSInteger)section {
- if (section == 0) {
- return BITHockeyLocalizedString(@"HockeyFeedbackUserDataDescription");
- }
-
- return nil;
-}
-
-- (UITableViewCell *)tableView:(UITableView *) __unused tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
- static NSString *CellIdentifier = @"InputCell";
- BITFeedbackManager *strongManager = self.manager;
- UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
- if (cell == nil) {
- cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
-
- cell.accessoryType = UITableViewCellAccessoryNone;
- cell.selectionStyle = UITableViewCellSelectionStyleNone;
- cell.backgroundColor = [UIColor whiteColor];
-
- UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(110, 11, self.view.frame.size.width - 110 - 35, 24)];
- if (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) {
- textField.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
- }
- textField.adjustsFontSizeToFitWidth = YES;
- textField.textColor = [UIColor blackColor];
- textField.backgroundColor = [UIColor lightGrayColor];
-
- if ([indexPath row] == 0 && [strongManager requireUserName] != BITFeedbackUserDataElementDontShow) {
- textField.placeholder = BITHockeyLocalizedString(@"HockeyFeedbackUserDataNamePlaceHolder");
- textField.text = self.name;
- if (strongManager.requireUserName == BITFeedbackUserDataElementRequired) {
- textField.accessibilityHint = BITHockeyLocalizedString(@"HockeyAccessibilityHintRequired");
- }
-
- textField.keyboardType = UIKeyboardTypeDefault;
- if ([strongManager requireUserEmail])
- textField.returnKeyType = UIReturnKeyNext;
- else
- textField.returnKeyType = UIReturnKeyDone;
- textField.autocapitalizationType = UITextAutocapitalizationTypeWords;
- [textField addTarget:self action:@selector(userNameEntered:) forControlEvents:UIControlEventEditingChanged];
- [textField becomeFirstResponder];
- } else {
- textField.placeholder = BITHockeyLocalizedString(@"HockeyFeedbackUserDataEmailPlaceholder");
- textField.text = self.email;
- if (strongManager.requireUserEmail == BITFeedbackUserDataElementRequired) {
- textField.accessibilityHint = BITHockeyLocalizedString(@"HockeyAccessibilityHintRequired");
- }
-
- textField.keyboardType = UIKeyboardTypeEmailAddress;
- textField.returnKeyType = UIReturnKeyDone;
- textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
- [textField addTarget:self action:@selector(userEmailEntered:) forControlEvents:UIControlEventEditingChanged];
- if (![strongManager requireUserName])
- [textField becomeFirstResponder];
- }
-
- textField.backgroundColor = [UIColor whiteColor];
- textField.autocorrectionType = UITextAutocorrectionTypeNo;
- textField.textAlignment = NSTextAlignmentLeft;
- textField.delegate = self;
- textField.tag = indexPath.row;
-
- textField.clearButtonMode = UITextFieldViewModeWhileEditing;
- [textField setEnabled: YES];
-
- [cell addSubview:textField];
- }
-
- if ([indexPath row] == 0 && [strongManager requireUserName] != BITFeedbackUserDataElementDontShow) {
- cell.textLabel.text = BITHockeyLocalizedString(@"HockeyFeedbackUserDataName");
- } else {
- cell.textLabel.text = BITHockeyLocalizedString(@"HockeyFeedbackUserDataEmail");
- }
-
- return cell;
-}
-
-
-#pragma mark - UITextFieldDelegate
-
-- (BOOL)textFieldShouldReturn:(UITextField *)textField {
- NSInteger nextTag = textField.tag + 1;
-
- UIResponder* nextResponder = [self.view viewWithTag:nextTag];
- if (nextResponder) {
- [nextResponder becomeFirstResponder];
- } else {
- if ([self allRequiredFieldsEntered]) {
- if ([textField isFirstResponder])
- [textField resignFirstResponder];
-
- [self saveAction:nil];
- }
- }
- return NO;
-}
-
-
-@end
-
-#endif /* HOCKEYSDK_FEATURE_FEEDBACK */
diff --git a/submodules/HockeySDK-iOS/Classes/BITGZIP.h b/submodules/HockeySDK-iOS/Classes/BITGZIP.h
deleted file mode 100644
index dba000867f..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITGZIP.h
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-// GZIP.h
-//
-// Version 1.0.3
-//
-// Created by Nick Lockwood on 03/06/2012.
-// Copyright (C) 2012 Charcoal Design
-//
-// Distributed under the permissive zlib License
-// Get the latest version from here:
-//
-// https://github.com/nicklockwood/GZIP
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-// claim that you wrote the original software. If you use this software
-// in a product, an acknowledgment in the product documentation would be
-// appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such, and must not be
-// misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source distribution.
-//
-
-#import
-
-#import "HockeySDKNullability.h"
-NS_ASSUME_NONNULL_BEGIN
-
-@interface NSData (BITGZIP)
-
-- (nullable NSData *)bit_gzippedDataWithCompressionLevel:(float)level;
-- (nullable NSData *)bit_gzippedData;
-- (nullable NSData *)bit_gunzippedData;
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/submodules/HockeySDK-iOS/Classes/BITHockeyAppClient.h b/submodules/HockeySDK-iOS/Classes/BITHockeyAppClient.h
deleted file mode 100644
index 2cd677b10c..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITHockeyAppClient.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Author: Stephan Diederich
- *
- * Copyright (c) 2013-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import
-
-extern NSString * const kBITHockeyAppClientBoundary;
-
-/**
- * Generic Hockey API client
- */
-@interface BITHockeyAppClient : NSObject
-
-/**
- * designated initializer
- *
- * @param baseURL the baseURL of the HockeyApp instance
- */
-- (instancetype) initWithBaseURL:(NSURL*) baseURL;
-
-/**
- * baseURL to which relative paths are appended
- */
-@property (nonatomic, strong) NSURL *baseURL;
-
-/**
- * creates an NRURLRequest for the given method and path by using
- * the internally stored baseURL.
- *
- * @param method the HTTPMethod to check, must not be nil
- * @param params parameters for the request (only supported for GET and POST for now)
- * @param path path to append to baseURL. can be nil in which case "/" is appended
- *
- * @return an NSMutableURLRequest for further configuration
- */
-- (NSMutableURLRequest *) requestWithMethod:(NSString*) method
- path:(NSString *) path
- parameters:(NSDictionary *) params;
-
-/**
- * Access to the internal operation queue
- */
-@property (nonatomic, strong) NSOperationQueue *operationQueue;
-
-#pragma mark - Helpers
-/**
- * create a post body from the given value, key and boundary. This is a convenience call to
- * dataWithPostValue:forKey:contentType:boundary and aimed at NSString-content.
- *
- * @param value -
- * @param key -
- * @param boundary -
- *
- * @return NSData instance configured to be attached on a (post) URLRequest
- */
-+ (NSData *)dataWithPostValue:(NSString *)value forKey:(NSString *)key boundary:(NSString *) boundary;
-
-/**
- * create a post body from the given value, key and boundary and content type.
- *
- * @param value -
- * @param key -
- *@param contentType -
- * @param boundary -
- * @param filename -
- *
- * @return NSData instance configured to be attached on a (post) URLRequest
- */
-+ (NSData *)dataWithPostValue:(NSData *)value forKey:(NSString *)key contentType:(NSString *)contentType boundary:(NSString *) boundary filename:(NSString *)filename;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITHockeyAppClient.m b/submodules/HockeySDK-iOS/Classes/BITHockeyAppClient.m
deleted file mode 100644
index 6da7df4b60..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITHockeyAppClient.m
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Author: Stephan Diederich
- *
- * Copyright (c) 2013-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-#import "BITHockeyAppClient.h"
-
-NSString * const kBITHockeyAppClientBoundary = @"----FOO";
-
-@implementation BITHockeyAppClient
-
-- (instancetype)initWithBaseURL:(NSURL *)baseURL {
- self = [super init];
- if ( self ) {
- NSParameterAssert(baseURL);
- _baseURL = baseURL;
- }
- return self;
-}
-
-#pragma mark - Networking
-- (NSMutableURLRequest *) requestWithMethod:(NSString*) method
- path:(NSString *) path
- parameters:(NSDictionary *)params {
- NSParameterAssert(self.baseURL);
- NSParameterAssert(method);
- NSParameterAssert(params == nil || [method isEqualToString:@"POST"] || [method isEqualToString:@"GET"]);
- path = path ? : @"";
-
- NSURL *endpoint = [self.baseURL URLByAppendingPathComponent:path];
- NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:endpoint];
- request.HTTPMethod = method;
-
- if (params) {
- if ([method isEqualToString:@"GET"]) {
- NSString *absoluteURLString = [endpoint absoluteString];
- //either path already has parameters, or not
- NSString *appenderFormat = [path rangeOfString:@"?"].location == NSNotFound ? @"?%@" : @"&%@";
-
- endpoint = [NSURL URLWithString:[absoluteURLString stringByAppendingFormat:appenderFormat,
- [self.class queryStringFromParameters:params withEncoding:NSUTF8StringEncoding]]];
- [request setURL:endpoint];
- } else {
- //TODO: this is crap. Boundary must be the same as the one in appendData
- //unify this!
- NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", kBITHockeyAppClientBoundary];
- [request setValue:contentType forHTTPHeaderField:@"Content-type"];
-
- NSMutableData *postBody = [NSMutableData data];
- [params enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *value, BOOL __unused *stop) {
- [postBody appendData:[[self class] dataWithPostValue:value forKey:key boundary:kBITHockeyAppClientBoundary]];
- }];
-
- [postBody appendData:(NSData *)[[NSString stringWithFormat:@"--%@--\r\n", kBITHockeyAppClientBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
-
- [request setHTTPBody:postBody];
- }
- }
-
- return request;
-}
-
-+ (NSData *)dataWithPostValue:(NSString *)value forKey:(NSString *)key boundary:(NSString *) boundary {
- return [self dataWithPostValue:[value dataUsingEncoding:NSUTF8StringEncoding] forKey:key contentType:@"text" boundary:boundary filename:nil];
-}
-
-+ (NSData *)dataWithPostValue:(NSData *)value forKey:(NSString *)key contentType:(NSString *)contentType boundary:(NSString *) boundary filename:(NSString *)filename {
- NSMutableData *postBody = [NSMutableData data];
-
- [postBody appendData:(NSData *)[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
-
- // There's certainly a better way to check if we are supposed to send binary data here.
- if (filename){
- [postBody appendData:(NSData *)[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", key, filename] dataUsingEncoding:NSUTF8StringEncoding]];
- [postBody appendData:(NSData *)[[NSString stringWithFormat:@"Content-Type: %@\r\n", contentType] dataUsingEncoding:NSUTF8StringEncoding]];
- [postBody appendData:(NSData *)[[NSString stringWithFormat:@"Content-Transfer-Encoding: binary\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
- } else {
- [postBody appendData:(NSData *)[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]];
- [postBody appendData:(NSData *)[[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", contentType] dataUsingEncoding:NSUTF8StringEncoding]];
- }
-
- [postBody appendData:value];
- [postBody appendData:(NSData *)[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
-
- return postBody;
-}
-
-
-+ (NSString *) queryStringFromParameters:(NSDictionary *) params withEncoding:(NSStringEncoding) __unused encoding {
- NSMutableString *queryString = [NSMutableString new];
- [params enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSString* value, BOOL __unused *stop) {
- NSAssert([key isKindOfClass:[NSString class]], @"Query parameters can only be string-string pairs");
- NSAssert([value isKindOfClass:[NSString class]], @"Query parameters can only be string-string pairs");
-
- [queryString appendFormat:queryString.length ? @"&%@=%@" : @"%@=%@", key, value];
- }];
- return queryString;
-}
-
-- (NSOperationQueue *)operationQueue {
- if(nil == _operationQueue) {
- _operationQueue = [[NSOperationQueue alloc] init];
- _operationQueue.maxConcurrentOperationCount = 1;
- }
- return _operationQueue;
-}
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITHockeyAttachment.h b/submodules/HockeySDK-iOS/Classes/BITHockeyAttachment.h
deleted file mode 100644
index ec6cd02df4..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITHockeyAttachment.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import
-
-/**
- Provides support to add binary attachments to crash reports and feedback messages
-
- This is used by `[BITCrashManagerDelegate attachmentForCrashManager:]`,
- `[BITFeedbackComposeViewController prepareWithItems:]` and
- `[BITFeedbackManager showFeedbackComposeViewWithPreparedItems:]`
- */
-@interface BITHockeyAttachment : NSObject
-
-/**
- The filename the attachment should get
- */
-@property (nonatomic, readonly, copy) NSString *filename;
-
-/**
- The attachment data as NSData object
- */
-@property (nonatomic, readonly, strong) NSData *hockeyAttachmentData;
-
-/**
- The content type of your data as MIME type
- */
-@property (nonatomic, readonly, copy) NSString *contentType;
-
-/**
- Create an BITHockeyAttachment instance with a given filename and NSData object
-
- @param filename The filename the attachment should get. If nil will get a automatically generated filename
- @param hockeyAttachmentData The attachment data as NSData. The instance will be ignore if this is set to nil!
- @param contentType The content type of your data as MIME type. If nil will be set to "application/octet-stream"
-
- @return An instance of BITHockeyAttachment.
- */
-- (instancetype)initWithFilename:(NSString *)filename
- hockeyAttachmentData:(NSData *)hockeyAttachmentData
- contentType:(NSString *)contentType;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITHockeyAttachment.m b/submodules/HockeySDK-iOS/Classes/BITHockeyAttachment.m
deleted file mode 100644
index 283f267785..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITHockeyAttachment.m
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_CRASH_REPORTER || HOCKEYSDK_FEATURE_FEEDBACK
-
-#import "BITHockeyAttachment.h"
-
-@implementation BITHockeyAttachment
-
-- (instancetype)initWithFilename:(NSString *)filename
- hockeyAttachmentData:(NSData *)hockeyAttachmentData
- contentType:(NSString *)contentType
-{
- if ((self = [super init])) {
- _filename = filename;
-
- _hockeyAttachmentData = hockeyAttachmentData;
-
- if (contentType) {
- _contentType = contentType;
- } else {
- _contentType = @"application/octet-stream";
- }
-
- }
-
- return self;
-}
-
-
-#pragma mark - NSCoder
-
-- (void)encodeWithCoder:(NSCoder *)encoder {
- if (self.filename) {
- [encoder encodeObject:self.filename forKey:@"filename"];
- }
- if (self.hockeyAttachmentData) {
- [encoder encodeObject:self.hockeyAttachmentData forKey:@"data"];
- }
- [encoder encodeObject:self.contentType forKey:@"contentType"];
-}
-
-- (instancetype)initWithCoder:(NSCoder *)decoder {
- if ((self = [super init])) {
- _filename = [decoder decodeObjectForKey:@"filename"];
- _hockeyAttachmentData = [decoder decodeObjectForKey:@"data"];
- _contentType = [decoder decodeObjectForKey:@"contentType"];
- }
- return self;
-}
-
-@end
-
-#endif /* HOCKEYSDK_FEATURE_CRASH_REPORTER || HOCKEYSDK_FEATURE_FEEDBACK */
diff --git a/submodules/HockeySDK-iOS/Classes/BITHockeyBaseManager.h b/submodules/HockeySDK-iOS/Classes/BITHockeyBaseManager.h
deleted file mode 100644
index 20da0b8c18..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITHockeyBaseManager.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import
-#import
-
-
-/**
- The internal superclass for all component managers
-
- */
-
-@interface BITHockeyBaseManager : NSObject
-
-///-----------------------------------------------------------------------------
-/// @name Modules
-///-----------------------------------------------------------------------------
-
-
-/**
- Defines the server URL to send data to or request data from
-
- By default this is set to the HockeyApp servers and there rarely should be a
- need to modify that.
- */
-@property (nonatomic, copy) NSString *serverURL;
-
-
-///-----------------------------------------------------------------------------
-/// @name User Interface
-///-----------------------------------------------------------------------------
-
-/**
- The UIBarStyle of the update user interface navigation bar.
-
- Default is UIBarStyleBlackOpaque
- @see navigationBarTintColor
- */
-@property (nonatomic, assign) UIBarStyle barStyle;
-
-/**
- The navigationbar tint color of the update user interface navigation bar.
-
- The navigationBarTintColor is used by default, you can either overwrite it `navigationBarTintColor`
- or define another `barStyle` instead.
-
- Default is RGB(25, 25, 25)
- @see barStyle
- */
-@property (nonatomic, strong) UIColor *navigationBarTintColor;
-
-/**
- The UIModalPresentationStyle for showing the update user interface when invoked
- with the update alert.
- */
-@property (nonatomic, assign) UIModalPresentationStyle modalPresentationStyle;
-
-+ (void)setPresentAlert:(void (^)(UIAlertController *))presentAlert;
-+ (void)setPresentView:(void (^)(UIViewController *))presentView;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITHockeyBaseManager.m b/submodules/HockeySDK-iOS/Classes/BITHockeyBaseManager.m
deleted file mode 100644
index 03b70b80cf..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITHockeyBaseManager.m
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import "HockeySDK.h"
-#import "HockeySDKPrivate.h"
-
-#import "BITHockeyHelper.h"
-
-#import "BITHockeyBaseManager.h"
-#import "BITHockeyBaseManagerPrivate.h"
-#if HOCKEYSDK_FEATURE_AUTHENTICATOR || HOCKEYSDK_FEATURE_UPDATES || HOCKEYSDK_FEATURE_FEEDBACK
-#import "BITHockeyBaseViewController.h"
-#endif
-
-#import "BITKeychainUtils.h"
-
-#import
-#import
-#import
-
-// We need BIT_UNUSED macro to make sure there aren't any warnings when building
-// HockeySDK Distribution scheme. Since several configurations are build in this scheme
-// and different features can be turned on and off we can't just use __unused attribute.
-#if !defined (HOCKEYSDK_CONFIGURATION_ReleaseCrashOnlyExtensions)
-#if HOCKEYSDK_FEATURE_AUTHENTICATOR || HOCKEYSDK_FEATURE_UPDATES || HOCKEYSDK_FEATURE_FEEDBACK
-#define BIT_UNUSED
-#else
-#define BIT_UNUSED __unused
-#endif
-#endif
-
-@interface BITHockeyBaseManager ()
-
-@property (nonatomic, strong) UINavigationController *navController;
-@property (nonatomic, strong) NSDateFormatter *rfc3339Formatter;
-
-@end
-
-static void (^_presentAlert)(UIAlertController *) = nil;
-static void (^_presentView)(UIViewController *) = nil;
-
-@implementation BITHockeyBaseManager
-
-- (instancetype)init {
- if ((self = [super init])) {
- _serverURL = BITHOCKEYSDK_URL;
- _barStyle = UIBarStyleDefault;
- _modalPresentationStyle = UIModalPresentationFormSheet;
-
- NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
- _rfc3339Formatter = [[NSDateFormatter alloc] init];
- [_rfc3339Formatter setLocale:enUSPOSIXLocale];
- [_rfc3339Formatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"];
- [_rfc3339Formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
- }
- return self;
-}
-
-- (instancetype)initWithAppIdentifier:(NSString *)appIdentifier appEnvironment:(BITEnvironment)environment {
- if ((self = [self init])) {
- _appIdentifier = appIdentifier;
- _appEnvironment = environment;
- }
- return self;
-}
-
-
-#pragma mark - Private
-
-- (void)reportError:(NSError *)error {
- BITHockeyLogError(@"ERROR: %@", [error localizedDescription]);
-}
-
-- (NSString *)encodedAppIdentifier {
- return bit_encodeAppIdentifier(self.appIdentifier);
-}
-
-- (NSString *)getDevicePlatform {
- size_t size;
- sysctlbyname("hw.machine", NULL, &size, NULL, 0);
- char *answer = (char*)malloc(size);
- if (answer == NULL)
- return @"";
- sysctlbyname("hw.machine", answer, &size, NULL, 0);
- NSString *platform = [NSString stringWithCString:answer encoding: NSUTF8StringEncoding];
- free(answer);
- return platform;
-}
-
-- (NSString *)executableUUID {
- const struct mach_header *executableHeader = NULL;
- for (uint32_t i = 0; i < _dyld_image_count(); i++) {
- const struct mach_header *header = _dyld_get_image_header(i);
- if (header->filetype == MH_EXECUTE) {
- executableHeader = header;
- break;
- }
- }
-
- if (!executableHeader)
- return @"";
-
- BOOL is64bit = executableHeader->magic == MH_MAGIC_64 || executableHeader->magic == MH_CIGAM_64;
- uintptr_t cursor = (uintptr_t)executableHeader + (is64bit ? sizeof(struct mach_header_64) : sizeof(struct mach_header));
- const struct segment_command *segmentCommand = NULL;
- for (uint32_t i = 0; i < executableHeader->ncmds; i++, cursor += segmentCommand->cmdsize) {
- segmentCommand = (struct segment_command *)cursor;
- if (segmentCommand->cmd == LC_UUID) {
- const struct uuid_command *uuidCommand = (const struct uuid_command *)segmentCommand;
- const uint8_t *uuid = uuidCommand->uuid;
- return [[NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
- uuid[0], uuid[1], uuid[2], uuid[3],
- uuid[4], uuid[5], uuid[6], uuid[7],
- uuid[8], uuid[9], uuid[10], uuid[11],
- uuid[12], uuid[13], uuid[14], uuid[15]]
- lowercaseString];
- }
- }
-
- return @"";
-}
-
-#if !defined (HOCKEYSDK_CONFIGURATION_ReleaseCrashOnlyExtensions)
-- (UIWindow *)findVisibleWindow {
- UIWindow *visibleWindow = [UIApplication sharedApplication].keyWindow;
-
- if (!(visibleWindow.hidden)) {
- return visibleWindow;
- }
-
- // if the rootViewController property (available >= iOS 4.0) of the main window is set, we present the modal view controller on top of the rootViewController
- NSArray *windows = [[UIApplication sharedApplication] windows];
- for (UIWindow *window in windows) {
- if (!window.hidden && !visibleWindow) {
- visibleWindow = window;
- }
- if ([UIWindow instancesRespondToSelector:@selector(rootViewController)]) {
- if (!(window.hidden) && ([window rootViewController])) {
- visibleWindow = window;
- BITHockeyLogDebug(@"INFO: UIWindow with rootViewController found: %@", visibleWindow);
- break;
- }
- }
- }
-
- return visibleWindow;
-}
-
-/**
- * Provide a custom UINavigationController with customized appearance settings
- *
- * @param viewController The root viewController
- * @param modalPresentationStyle The modal presentation style
- *
- * @return A UINavigationController
- */
-- (UINavigationController *)customNavigationControllerWithRootViewController:(UIViewController *)viewController presentationStyle:(UIModalPresentationStyle)modalPresentationStyle {
- UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController];
- navController.navigationBar.barStyle = self.barStyle;
- if (self.navigationBarTintColor) {
- navController.navigationBar.tintColor = self.navigationBarTintColor;
- } else {
- // in case of iOS 7 we overwrite the tint color on the navigation bar
- if ([UIWindow instancesRespondToSelector:NSSelectorFromString(@"tintColor")]) {
- [navController.navigationBar setTintColor:BIT_RGBCOLOR(0, 122, 255)];
- }
- }
- navController.modalPresentationStyle = modalPresentationStyle;
-
- return navController;
-}
-
-- (UIViewController *)visibleWindowRootViewController {
- UIViewController *parentViewController = nil;
- id strongDelegate = [BITHockeyManager sharedHockeyManager].delegate;
- if ([strongDelegate respondsToSelector:@selector(viewControllerForHockeyManager:componentManager:)]) {
- parentViewController = [strongDelegate viewControllerForHockeyManager:[BITHockeyManager sharedHockeyManager] componentManager:self];
- }
-
- UIWindow *visibleWindow = [self findVisibleWindow];
-
- if (parentViewController == nil) {
- parentViewController = [visibleWindow rootViewController];
- }
-
- // use topmost modal view
- while (parentViewController.presentedViewController) {
- parentViewController = parentViewController.presentedViewController;
- }
-
- // special addition to get rootViewController from three20 which has it's own controller handling
- if (NSClassFromString(@"TTNavigator")) {
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
- UIViewController *ttParentViewController = nil;
- ttParentViewController = [[NSClassFromString(@"TTNavigator") performSelector:(NSSelectorFromString(@"navigator"))] visibleViewController];
- if (ttParentViewController)
- parentViewController = ttParentViewController;
-#pragma clang diagnostic pop
- }
-
- return parentViewController;
-}
-
-- (void)showAlertController:(UIViewController *)alertController {
-
- // always execute this on the main thread
- dispatch_async(dispatch_get_main_queue(), ^{
- if (_presentAlert) {
- _presentAlert(alertController);
- } else {
- UIViewController *parentViewController = [self visibleWindowRootViewController];
-
- // as per documentation this only works if called from within viewWillAppear: or viewDidAppear:
- // in tests this also worked fine on iOS 6 and 7 but not on iOS 5 so we are still trying this
- if ([parentViewController isKindOfClass:NSClassFromString(@"UIAlertController")] || [parentViewController isBeingPresented]) {
- BITHockeyLogWarning(@"WARNING: There is already a view controller being presented onto the parentViewController. Delaying presenting the new view controller by 0.5s.");
- [self performSelector:@selector(showAlertController:) withObject:alertController afterDelay:0.5];
- return;
- }
-
- if (parentViewController) {
- [parentViewController presentViewController:alertController animated:YES completion:nil];
- }
- }
- });
-}
-
-- (void)showView:(UIViewController *)viewController {
- if (_presentView) {
- _presentView(viewController);
- return;
- }
-
- // if we compile Crash only, then BITHockeyBaseViewController is not included
- // in the headers and will cause a warning with the modulemap file
-#if HOCKEYSDK_FEATURE_AUTHENTICATOR || HOCKEYSDK_FEATURE_UPDATES || HOCKEYSDK_FEATURE_FEEDBACK
- UIViewController *parentViewController = [self visibleWindowRootViewController];
-
- // as per documentation this only works if called from within viewWillAppear: or viewDidAppear:
- // in tests this also worked fine on iOS 6 and 7 but not on iOS 5 so we are still trying this
- if ([parentViewController isBeingPresented]) {
- BITHockeyLogDebug(@"INFO: There is already a view controller being presented onto the parentViewController. Delaying presenting the new view controller by 0.5s.");
- [self performSelector:@selector(showView:) withObject:viewController afterDelay:0.5];
- return;
- }
-
- if (self.navController != nil) self.navController = nil;
-
- self.navController = [self customNavigationControllerWithRootViewController:viewController presentationStyle:self.modalPresentationStyle];
-
- if (parentViewController) {
- self.navController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
-
- // page sheet for the iPad
- if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
- self.navController.modalPresentationStyle = UIModalPresentationFormSheet;
- }
-
- if ([viewController isKindOfClass:[BITHockeyBaseViewController class]])
- [(BITHockeyBaseViewController *)viewController setModalAnimated:YES];
-
- [parentViewController presentViewController:self.navController animated:YES completion:nil];
- } else {
- // if not, we add a subview to the window. A bit hacky but should work in most circumstances.
- // Also, we don't get a nice animation for free, but hey, this is for beta not production users ;)
- UIWindow *visibleWindow = [self findVisibleWindow];
-
- BITHockeyLogDebug(@"INFO: No rootViewController found, using UIWindow-approach: %@", visibleWindow);
- if ([viewController isKindOfClass:[BITHockeyBaseViewController class]])
- [(BITHockeyBaseViewController *)viewController setModalAnimated:NO];
- [visibleWindow addSubview:self.navController.view];
- }
-#endif /* HOCKEYSDK_FEATURE_AUTHENTICATOR || HOCKEYSDK_FEATURE_UPDATES || HOCKEYSDK_FEATURE_FEEDBACK */
-}
-#endif // HOCKEYSDK_CONFIGURATION_ReleaseCrashOnlyExtensions && HOCKEYSDK_CONFIGURATION_RelaseCrashOnlyWatchOS
-
-
-- (BOOL)addStringValueToKeychain:(NSString *)stringValue forKey:(NSString *)key {
- if (!key || !stringValue)
- return NO;
-
- NSError *error = nil;
- return [BITKeychainUtils storeUsername:key
- andPassword:stringValue
- forServiceName:bit_keychainHockeySDKServiceName()
- updateExisting:YES
- error:&error];
-}
-
-- (BOOL)addStringValueToKeychainForThisDeviceOnly:(NSString *)stringValue forKey:(NSString *)key {
- if (!key || !stringValue)
- return NO;
-
- NSError *error = nil;
- return [BITKeychainUtils storeUsername:key
- andPassword:stringValue
- forServiceName:bit_keychainHockeySDKServiceName()
- updateExisting:YES
- accessibility:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
- error:&error];
-}
-
-- (NSString *)stringValueFromKeychainForKey:(NSString *)key {
- if (!key)
- return nil;
-
- NSError *error = nil;
- return [BITKeychainUtils getPasswordForUsername:key
- andServiceName:bit_keychainHockeySDKServiceName()
- error:&error];
-}
-
-- (BOOL)removeKeyFromKeychain:(NSString *)key {
- NSError *error = nil;
- return [BITKeychainUtils deleteItemForUsername:key
- andServiceName:bit_keychainHockeySDKServiceName()
- error:&error];
-}
-
-
-#pragma mark - Manager Control
-
-- (void)startManager {
-}
-
-#pragma mark - Helpers
-
-- (NSDate *)parseRFC3339Date:(NSString *)dateString {
- NSDate *date = nil;
- NSError *error = nil;
- if (![self.rfc3339Formatter getObjectValue:&date forString:dateString range:nil error:&error]) {
- BITHockeyLogWarning(@"WARNING: Invalid date '%@' string: %@", dateString, error);
- }
-
- return date;
-}
-
-+ (void)setPresentAlert:(void (^)(UIAlertController *))presentAlert {
- _presentAlert = [presentAlert copy];
-}
-
-+ (void)setPresentView:(void (^)(UIViewController *))presentView {
- _presentView = [presentView copy];
-}
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITHockeyBaseManagerPrivate.h b/submodules/HockeySDK-iOS/Classes/BITHockeyBaseManagerPrivate.h
deleted file mode 100644
index 2ddf12d92e..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITHockeyBaseManagerPrivate.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import
-#import
-#import "BITHockeyManager.h"
-
-@class BITHockeyBaseManager;
-@class BITHockeyBaseViewController;
-
-@interface BITHockeyBaseManager()
-
-@property (nonatomic, copy) NSString *appIdentifier;
-
-@property (nonatomic, assign, readonly) BITEnvironment appEnvironment;
-
-- (instancetype)initWithAppIdentifier:(NSString *)appIdentifier appEnvironment:(BITEnvironment)environment;
-
-- (void)startManager;
-
-/**
- * by default, just logs the message
- *
- * can be overridden by subclasses to do their own error handling,
- * e.g. to show UI
- *
- * @param error NSError
- */
-- (void)reportError:(NSError *)error;
-
-/** url encoded version of the appIdentifier
-
- where appIdentifier is either the value this object was initialized with,
- or the main bundles CFBundleIdentifier if appIdentifier is nil
- */
-- (NSString *)encodedAppIdentifier;
-
-// device / application helpers
-- (NSString *)getDevicePlatform;
-- (NSString *)executableUUID;
-
-#if !defined (HOCKEYSDK_CONFIGURATION_ReleaseCrashOnlyExtensions)
-// UI helpers
-- (UIWindow *)findVisibleWindow;
-- (UINavigationController *)customNavigationControllerWithRootViewController:(UIViewController *)viewController presentationStyle:(UIModalPresentationStyle)presentationStyle;
-
-/**
- * Present an UIAlertController on the visible root UIViewController.
- *
- * Uses `visibleWindowRootViewController` to find a controller on which to present the UIAlertController on.
- * This method is always dispatched on the main queue.
- *
- * @param alertController The UIAlertController to be presented.
- */
-- (void)showAlertController:(UIViewController *)alertController;
-
-- (void)showView:(UIViewController *)viewController;
-#endif
-
-// Date helpers
-- (NSDate *)parseRFC3339Date:(NSString *)dateString;
-
-// keychain helpers
-- (BOOL)addStringValueToKeychain:(NSString *)stringValue forKey:(NSString *)key;
-- (BOOL)addStringValueToKeychainForThisDeviceOnly:(NSString *)stringValue forKey:(NSString *)key;
-- (NSString *)stringValueFromKeychainForKey:(NSString *)key;
-- (BOOL)removeKeyFromKeychain:(NSString *)key;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITHockeyBaseViewController.h b/submodules/HockeySDK-iOS/Classes/BITHockeyBaseViewController.h
deleted file mode 100644
index d7701036be..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITHockeyBaseViewController.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import
-
-@interface BITHockeyBaseViewController : UITableViewController
-
-@property (nonatomic, readwrite) BOOL modalAnimated;
-
-- (instancetype)initWithModalStyle:(BOOL)modal;
-- (instancetype)initWithStyle:(UITableViewStyle)style modal:(BOOL)modal;
-
-@end
diff --git a/submodules/HockeySDK-iOS/Classes/BITHockeyBaseViewController.m b/submodules/HockeySDK-iOS/Classes/BITHockeyBaseViewController.m
deleted file mode 100644
index 1632c342ce..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITHockeyBaseViewController.m
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Author: Andreas Linde
- *
- * Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#import "HockeySDK.h"
-
-#if HOCKEYSDK_FEATURE_AUTHENTICATOR || HOCKEYSDK_FEATURE_UPDATES || HOCKEYSDK_FEATURE_FEEDBACK
-
-#import "BITHockeyBaseViewController.h"
-#import "HockeySDKPrivate.h"
-
-@interface BITHockeyBaseViewController ()
-
-@property (nonatomic) BOOL modal;
-
-@end
-
-@implementation BITHockeyBaseViewController
-
-
-- (instancetype)initWithStyle:(UITableViewStyle)style {
- self = [super initWithStyle:style];
- if (self) {
- _modalAnimated = YES;
- _modal = NO;
- }
- return self;
-}
-
-- (instancetype)initWithStyle:(UITableViewStyle)style modal:(BOOL)modal {
- self = [self initWithStyle:style];
- if (self) {
- _modal = modal;
-
- //might be better in viewDidLoad, but to workaround rdar://12214613 and as it doesn't
- //hurt, we do it here
- if (_modal) {
- self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
- target:self
- action:@selector(onDismissModal:)];
- }
- }
- return self;
-}
-
-- (instancetype)initWithModalStyle:(BOOL)modal {
- self = [self initWithStyle:UITableViewStylePlain modal:modal];
- return self;
-}
-
-
-#pragma mark - View lifecycle
-
-- (void)onDismissModal:(id) __unused sender {
- if (self.modal) {
- UIViewController *presentingViewController = [self presentingViewController];
-
- // If there is no presenting view controller just remove view
- if (presentingViewController && self.modalAnimated) {
- [presentingViewController dismissViewControllerAnimated:YES completion:nil];
- } else {
- [self.navigationController.view removeFromSuperview];
- }
- } else {
- [self.navigationController popViewControllerAnimated:YES];
- }
-}
-
-
-#pragma mark - Rotation
-
--(UIInterfaceOrientationMask)supportedInterfaceOrientations {
- if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
- return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscape);
- } else {
- return UIInterfaceOrientationMaskAll;
- }
-}
-
-#pragma mark - Modal presentation
-
-
-@end
-
-#endif /* HOCKEYSDK_FEATURE_AUTHENTICATOR || HOCKEYSDK_FEATURE_UPDATES || HOCKEYSDK_FEATURE_FEEDBACK */
diff --git a/submodules/HockeySDK-iOS/Classes/BITHockeyHelper+Application.h b/submodules/HockeySDK-iOS/Classes/BITHockeyHelper+Application.h
deleted file mode 100644
index e7397ba63a..0000000000
--- a/submodules/HockeySDK-iOS/Classes/BITHockeyHelper+Application.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#import
-#import