diff --git a/Podfile b/Podfile index cf0527243e..852a290049 100644 --- a/Podfile +++ b/Podfile @@ -51,6 +51,7 @@ def all_pods pod 'Atributika', '~> 4.0' pod 'DeviceKit', '~> 1.0' pod 'lottie-ios' + pod 'EasyTipView', :git => 'https://github.com/igorkislyuk/EasyTipView.git' end def testing_pods diff --git a/Stepic.xcodeproj/project.pbxproj b/Stepic.xcodeproj/project.pbxproj index a361700710..7be44a672b 100644 --- a/Stepic.xcodeproj/project.pbxproj +++ b/Stepic.xcodeproj/project.pbxproj @@ -549,6 +549,22 @@ 086BE2B71F93A21B00B4BE56 /* LoadingCourseWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086BE2B11F93A21B00B4BE56 /* LoadingCourseWidgetView.swift */; }; 086BE2B81F93A21B00B4BE56 /* LoadingCourseWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086BE2B11F93A21B00B4BE56 /* LoadingCourseWidgetView.swift */; }; 086BE2B91F93A21B00B4BE56 /* LoadingCourseWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086BE2B11F93A21B00B4BE56 /* LoadingCourseWidgetView.swift */; }; + 086D5B3F20127A25000F7715 /* Tooltip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086D5B3E20127A25000F7715 /* Tooltip.swift */; }; + 086D5B4020127A25000F7715 /* Tooltip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086D5B3E20127A25000F7715 /* Tooltip.swift */; }; + 086D5B4120127A25000F7715 /* Tooltip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086D5B3E20127A25000F7715 /* Tooltip.swift */; }; + 086D5B4220127A25000F7715 /* Tooltip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086D5B3E20127A25000F7715 /* Tooltip.swift */; }; + 086D5B4320127A25000F7715 /* Tooltip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086D5B3E20127A25000F7715 /* Tooltip.swift */; }; + 086D5B4420127A25000F7715 /* Tooltip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086D5B3E20127A25000F7715 /* Tooltip.swift */; }; + 086D5B4520127A25000F7715 /* Tooltip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086D5B3E20127A25000F7715 /* Tooltip.swift */; }; + 086D5B4620127A25000F7715 /* Tooltip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086D5B3E20127A25000F7715 /* Tooltip.swift */; }; + 086D5B52201283C2000F7715 /* TooltipFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086D5B51201283C2000F7715 /* TooltipFactory.swift */; }; + 086D5B53201283C2000F7715 /* TooltipFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086D5B51201283C2000F7715 /* TooltipFactory.swift */; }; + 086D5B54201283C2000F7715 /* TooltipFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086D5B51201283C2000F7715 /* TooltipFactory.swift */; }; + 086D5B55201283C2000F7715 /* TooltipFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086D5B51201283C2000F7715 /* TooltipFactory.swift */; }; + 086D5B56201283C2000F7715 /* TooltipFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086D5B51201283C2000F7715 /* TooltipFactory.swift */; }; + 086D5B57201283C2000F7715 /* TooltipFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086D5B51201283C2000F7715 /* TooltipFactory.swift */; }; + 086D5B58201283C2000F7715 /* TooltipFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086D5B51201283C2000F7715 /* TooltipFactory.swift */; }; + 086D5B59201283C2000F7715 /* TooltipFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086D5B51201283C2000F7715 /* TooltipFactory.swift */; }; 086E965E1BF6683800AB952D /* VideoDownloadView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 086E965D1BF6683800AB952D /* VideoDownloadView.xib */; }; 086E96601BF66A1800AB952D /* VideoDownloadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086E965F1BF66A1800AB952D /* VideoDownloadView.swift */; }; 086FC6A01FE046C100C7DFF4 /* NotificationStatusesAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86624A721FC76578008E7E6C /* NotificationStatusesAPI.swift */; }; @@ -568,6 +584,14 @@ 086FC6AF1FE04DBD00C7DFF4 /* RangeExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086FC6A71FE04DBD00C7DFF4 /* RangeExtension.swift */; }; 087039301CD7413D00B6571B /* NotificationAlertConstructor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0870392F1CD7413D00B6571B /* NotificationAlertConstructor.swift */; }; 087039311CD7413D00B6571B /* NotificationAlertConstructor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0870392F1CD7413D00B6571B /* NotificationAlertConstructor.swift */; }; + 087296DC20168FF2009F9256 /* TooltipDefaultsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 087296DB20168FF2009F9256 /* TooltipDefaultsManager.swift */; }; + 087296DD20168FF2009F9256 /* TooltipDefaultsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 087296DB20168FF2009F9256 /* TooltipDefaultsManager.swift */; }; + 087296DE20168FF2009F9256 /* TooltipDefaultsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 087296DB20168FF2009F9256 /* TooltipDefaultsManager.swift */; }; + 087296DF20168FF2009F9256 /* TooltipDefaultsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 087296DB20168FF2009F9256 /* TooltipDefaultsManager.swift */; }; + 087296E020168FF2009F9256 /* TooltipDefaultsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 087296DB20168FF2009F9256 /* TooltipDefaultsManager.swift */; }; + 087296E120168FF2009F9256 /* TooltipDefaultsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 087296DB20168FF2009F9256 /* TooltipDefaultsManager.swift */; }; + 087296E220168FF2009F9256 /* TooltipDefaultsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 087296DB20168FF2009F9256 /* TooltipDefaultsManager.swift */; }; + 087296E320168FF2009F9256 /* TooltipDefaultsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 087296DB20168FF2009F9256 /* TooltipDefaultsManager.swift */; }; 087387D81BB9A4BD003CFAD1 /* CoreDataHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 087387D71BB9A4BD003CFAD1 /* CoreDataHelper.swift */; }; 087387DA1BB9B768003CFAD1 /* ErrorEnums.swift in Sources */ = {isa = PBXBuildFile; fileRef = 087387D91BB9B768003CFAD1 /* ErrorEnums.swift */; }; 087585A31FB50D640047A269 /* CourseListsAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 087585A21FB50D640047A269 /* CourseListsAPI.swift */; }; @@ -4710,10 +4734,13 @@ 086BE2841F901CCF00B4BE56 /* LastStepRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LastStepRouter.swift; sourceTree = ""; }; 086BE2A81F93A20B00B4BE56 /* LoadingCourseWidgetView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LoadingCourseWidgetView.xib; sourceTree = ""; }; 086BE2B11F93A21B00B4BE56 /* LoadingCourseWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingCourseWidgetView.swift; sourceTree = ""; }; + 086D5B3E20127A25000F7715 /* Tooltip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tooltip.swift; sourceTree = ""; }; + 086D5B51201283C2000F7715 /* TooltipFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TooltipFactory.swift; sourceTree = ""; }; 086E965D1BF6683800AB952D /* VideoDownloadView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = VideoDownloadView.xib; sourceTree = ""; }; 086E965F1BF66A1800AB952D /* VideoDownloadView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoDownloadView.swift; sourceTree = ""; }; 086FC6A71FE04DBD00C7DFF4 /* RangeExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RangeExtension.swift; sourceTree = ""; }; 0870392F1CD7413D00B6571B /* NotificationAlertConstructor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationAlertConstructor.swift; sourceTree = ""; }; + 087296DB20168FF2009F9256 /* TooltipDefaultsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TooltipDefaultsManager.swift; sourceTree = ""; }; 087387D71BB9A4BD003CFAD1 /* CoreDataHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataHelper.swift; sourceTree = ""; }; 087387D91BB9B768003CFAD1 /* ErrorEnums.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErrorEnums.swift; sourceTree = ""; }; 087585A21FB50D640047A269 /* CourseListsAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseListsAPI.swift; sourceTree = ""; }; @@ -6248,6 +6275,16 @@ name = Generic; sourceTree = ""; }; + 086D5B4720128398000F7715 /* Tooltip */ = { + isa = PBXGroup; + children = ( + 086D5B3E20127A25000F7715 /* Tooltip.swift */, + 086D5B51201283C2000F7715 /* TooltipFactory.swift */, + 087296DB20168FF2009F9256 /* TooltipDefaultsManager.swift */, + ); + name = Tooltip; + sourceTree = ""; + }; 086E965C1BF6682000AB952D /* Views */ = { isa = PBXGroup; children = ( @@ -6930,6 +6967,7 @@ 081566231F69C39A0082B359 /* Search Bar */, 08DF78D11F64059900AEEA85 /* StepikLabel.swift */, 08EDD6291F7C6785005203E4 /* StepikButton.swift */, + 086D5B4720128398000F7715 /* Tooltip */, ); name = "UI Elements"; sourceTree = ""; @@ -9572,6 +9610,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-Adaptive 3067/Pods-Adaptive 3067-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/AMPopTip/AMPopTip.framework", "${BUILT_PRODUCTS_DIR}/Agrume/Agrume.framework", "${BUILT_PRODUCTS_DIR}/Alamofire-iOS/Alamofire.framework", "${BUILT_PRODUCTS_DIR}/Atributika/Atributika.framework", @@ -9582,6 +9621,7 @@ "${BUILT_PRODUCTS_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework", "${BUILT_PRODUCTS_DIR}/DeviceKit/DeviceKit.framework", "${BUILT_PRODUCTS_DIR}/DownloadButton/DownloadButton.framework", + "${BUILT_PRODUCTS_DIR}/EasyTipView/EasyTipView.framework", "${BUILT_PRODUCTS_DIR}/FBSDKCoreKit/FBSDKCoreKit.framework", "${BUILT_PRODUCTS_DIR}/FBSDKLoginKit/FBSDKLoginKit.framework", "${BUILT_PRODUCTS_DIR}/FLKAutoLayout/FLKAutoLayout.framework", @@ -9615,6 +9655,7 @@ ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AMPopTip.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Agrume.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Atributika.framework", @@ -9625,6 +9666,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DZNEmptyDataSet.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DeviceKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DownloadButton.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/EasyTipView.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKCoreKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKLoginKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FLKAutoLayout.framework", @@ -9755,6 +9797,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-Adaptive 3150/Pods-Adaptive 3150-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/AMPopTip/AMPopTip.framework", "${BUILT_PRODUCTS_DIR}/Agrume/Agrume.framework", "${BUILT_PRODUCTS_DIR}/Alamofire-iOS/Alamofire.framework", "${BUILT_PRODUCTS_DIR}/Atributika/Atributika.framework", @@ -9765,6 +9808,7 @@ "${BUILT_PRODUCTS_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework", "${BUILT_PRODUCTS_DIR}/DeviceKit/DeviceKit.framework", "${BUILT_PRODUCTS_DIR}/DownloadButton/DownloadButton.framework", + "${BUILT_PRODUCTS_DIR}/EasyTipView/EasyTipView.framework", "${BUILT_PRODUCTS_DIR}/FBSDKCoreKit/FBSDKCoreKit.framework", "${BUILT_PRODUCTS_DIR}/FBSDKLoginKit/FBSDKLoginKit.framework", "${BUILT_PRODUCTS_DIR}/FLKAutoLayout/FLKAutoLayout.framework", @@ -9798,6 +9842,7 @@ ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AMPopTip.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Agrume.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Atributika.framework", @@ -9808,6 +9853,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DZNEmptyDataSet.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DeviceKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DownloadButton.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/EasyTipView.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKCoreKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKLoginKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FLKAutoLayout.framework", @@ -9869,6 +9915,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-Adaptive 1838/Pods-Adaptive 1838-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/AMPopTip/AMPopTip.framework", "${BUILT_PRODUCTS_DIR}/Agrume/Agrume.framework", "${BUILT_PRODUCTS_DIR}/Alamofire-iOS/Alamofire.framework", "${BUILT_PRODUCTS_DIR}/Atributika/Atributika.framework", @@ -9879,6 +9926,7 @@ "${BUILT_PRODUCTS_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework", "${BUILT_PRODUCTS_DIR}/DeviceKit/DeviceKit.framework", "${BUILT_PRODUCTS_DIR}/DownloadButton/DownloadButton.framework", + "${BUILT_PRODUCTS_DIR}/EasyTipView/EasyTipView.framework", "${BUILT_PRODUCTS_DIR}/FBSDKCoreKit/FBSDKCoreKit.framework", "${BUILT_PRODUCTS_DIR}/FBSDKLoginKit/FBSDKLoginKit.framework", "${BUILT_PRODUCTS_DIR}/FLKAutoLayout/FLKAutoLayout.framework", @@ -9912,6 +9960,7 @@ ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AMPopTip.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Agrume.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Atributika.framework", @@ -9922,6 +9971,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DZNEmptyDataSet.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DeviceKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DownloadButton.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/EasyTipView.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKCoreKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKLoginKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FLKAutoLayout.framework", @@ -10137,6 +10187,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-SberbankUniversity/Pods-SberbankUniversity-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/AMPopTip/AMPopTip.framework", "${BUILT_PRODUCTS_DIR}/Agrume/Agrume.framework", "${BUILT_PRODUCTS_DIR}/Alamofire-iOS/Alamofire.framework", "${BUILT_PRODUCTS_DIR}/Atributika/Atributika.framework", @@ -10147,6 +10198,7 @@ "${BUILT_PRODUCTS_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework", "${BUILT_PRODUCTS_DIR}/DeviceKit/DeviceKit.framework", "${BUILT_PRODUCTS_DIR}/DownloadButton/DownloadButton.framework", + "${BUILT_PRODUCTS_DIR}/EasyTipView/EasyTipView.framework", "${BUILT_PRODUCTS_DIR}/FBSDKCoreKit/FBSDKCoreKit.framework", "${BUILT_PRODUCTS_DIR}/FBSDKLoginKit/FBSDKLoginKit.framework", "${BUILT_PRODUCTS_DIR}/FLKAutoLayout/FLKAutoLayout.framework", @@ -10173,6 +10225,7 @@ ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AMPopTip.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Agrume.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Atributika.framework", @@ -10183,6 +10236,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DZNEmptyDataSet.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DeviceKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DownloadButton.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/EasyTipView.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKCoreKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKLoginKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FLKAutoLayout.framework", @@ -10237,6 +10291,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-Adaptive 1906/Pods-Adaptive 1906-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/AMPopTip/AMPopTip.framework", "${BUILT_PRODUCTS_DIR}/Agrume/Agrume.framework", "${BUILT_PRODUCTS_DIR}/Alamofire-iOS/Alamofire.framework", "${BUILT_PRODUCTS_DIR}/Atributika/Atributika.framework", @@ -10247,6 +10302,7 @@ "${BUILT_PRODUCTS_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework", "${BUILT_PRODUCTS_DIR}/DeviceKit/DeviceKit.framework", "${BUILT_PRODUCTS_DIR}/DownloadButton/DownloadButton.framework", + "${BUILT_PRODUCTS_DIR}/EasyTipView/EasyTipView.framework", "${BUILT_PRODUCTS_DIR}/FBSDKCoreKit/FBSDKCoreKit.framework", "${BUILT_PRODUCTS_DIR}/FBSDKLoginKit/FBSDKLoginKit.framework", "${BUILT_PRODUCTS_DIR}/FLKAutoLayout/FLKAutoLayout.framework", @@ -10280,6 +10336,7 @@ ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AMPopTip.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Agrume.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Atributika.framework", @@ -10290,6 +10347,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DZNEmptyDataSet.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DeviceKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DownloadButton.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/EasyTipView.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKCoreKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKLoginKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FLKAutoLayout.framework", @@ -10736,6 +10794,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-Adaptive 3149/Pods-Adaptive 3149-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/AMPopTip/AMPopTip.framework", "${BUILT_PRODUCTS_DIR}/Agrume/Agrume.framework", "${BUILT_PRODUCTS_DIR}/Alamofire-iOS/Alamofire.framework", "${BUILT_PRODUCTS_DIR}/Atributika/Atributika.framework", @@ -10746,6 +10805,7 @@ "${BUILT_PRODUCTS_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework", "${BUILT_PRODUCTS_DIR}/DeviceKit/DeviceKit.framework", "${BUILT_PRODUCTS_DIR}/DownloadButton/DownloadButton.framework", + "${BUILT_PRODUCTS_DIR}/EasyTipView/EasyTipView.framework", "${BUILT_PRODUCTS_DIR}/FBSDKCoreKit/FBSDKCoreKit.framework", "${BUILT_PRODUCTS_DIR}/FBSDKLoginKit/FBSDKLoginKit.framework", "${BUILT_PRODUCTS_DIR}/FLKAutoLayout/FLKAutoLayout.framework", @@ -10779,6 +10839,7 @@ ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AMPopTip.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Agrume.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Atributika.framework", @@ -10789,6 +10850,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DZNEmptyDataSet.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DeviceKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DownloadButton.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/EasyTipView.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKCoreKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKLoginKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FLKAutoLayout.framework", @@ -10865,6 +10927,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-Adaptive 3124/Pods-Adaptive 3124-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/AMPopTip/AMPopTip.framework", "${BUILT_PRODUCTS_DIR}/Agrume/Agrume.framework", "${BUILT_PRODUCTS_DIR}/Alamofire-iOS/Alamofire.framework", "${BUILT_PRODUCTS_DIR}/Atributika/Atributika.framework", @@ -10875,6 +10938,7 @@ "${BUILT_PRODUCTS_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework", "${BUILT_PRODUCTS_DIR}/DeviceKit/DeviceKit.framework", "${BUILT_PRODUCTS_DIR}/DownloadButton/DownloadButton.framework", + "${BUILT_PRODUCTS_DIR}/EasyTipView/EasyTipView.framework", "${BUILT_PRODUCTS_DIR}/FBSDKCoreKit/FBSDKCoreKit.framework", "${BUILT_PRODUCTS_DIR}/FBSDKLoginKit/FBSDKLoginKit.framework", "${BUILT_PRODUCTS_DIR}/FLKAutoLayout/FLKAutoLayout.framework", @@ -10908,6 +10972,7 @@ ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AMPopTip.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Agrume.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Atributika.framework", @@ -10918,6 +10983,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DZNEmptyDataSet.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DeviceKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DownloadButton.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/EasyTipView.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKCoreKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKLoginKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FLKAutoLayout.framework", @@ -11012,6 +11078,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-Stepic/Pods-Stepic-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/AMPopTip/AMPopTip.framework", "${BUILT_PRODUCTS_DIR}/Agrume/Agrume.framework", "${BUILT_PRODUCTS_DIR}/Alamofire-iOS/Alamofire.framework", "${BUILT_PRODUCTS_DIR}/Atributika/Atributika.framework", @@ -11022,6 +11089,7 @@ "${BUILT_PRODUCTS_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework", "${BUILT_PRODUCTS_DIR}/DeviceKit/DeviceKit.framework", "${BUILT_PRODUCTS_DIR}/DownloadButton/DownloadButton.framework", + "${BUILT_PRODUCTS_DIR}/EasyTipView/EasyTipView.framework", "${BUILT_PRODUCTS_DIR}/FBSDKCoreKit/FBSDKCoreKit.framework", "${BUILT_PRODUCTS_DIR}/FBSDKLoginKit/FBSDKLoginKit.framework", "${BUILT_PRODUCTS_DIR}/FLKAutoLayout/FLKAutoLayout.framework", @@ -11048,6 +11116,7 @@ ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AMPopTip.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Agrume.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Atributika.framework", @@ -11058,6 +11127,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DZNEmptyDataSet.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DeviceKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DownloadButton.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/EasyTipView.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKCoreKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKLoginKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FLKAutoLayout.framework", @@ -11160,6 +11230,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-StepicTests/Pods-StepicTests-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/AMPopTip/AMPopTip.framework", "${BUILT_PRODUCTS_DIR}/Agrume/Agrume.framework", "${BUILT_PRODUCTS_DIR}/Alamofire-iOS/Alamofire.framework", "${BUILT_PRODUCTS_DIR}/Atributika/Atributika.framework", @@ -11170,6 +11241,7 @@ "${BUILT_PRODUCTS_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework", "${BUILT_PRODUCTS_DIR}/DeviceKit/DeviceKit.framework", "${BUILT_PRODUCTS_DIR}/DownloadButton/DownloadButton.framework", + "${BUILT_PRODUCTS_DIR}/EasyTipView/EasyTipView.framework", "${BUILT_PRODUCTS_DIR}/FBSDKCoreKit/FBSDKCoreKit.framework", "${BUILT_PRODUCTS_DIR}/FBSDKLoginKit/FBSDKLoginKit.framework", "${BUILT_PRODUCTS_DIR}/FLKAutoLayout/FLKAutoLayout.framework", @@ -11198,6 +11270,7 @@ ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AMPopTip.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Agrume.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Atributika.framework", @@ -11208,6 +11281,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DZNEmptyDataSet.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DeviceKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DownloadButton.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/EasyTipView.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKCoreKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKLoginKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FLKAutoLayout.framework", @@ -11417,6 +11491,7 @@ 0860D9161F10EA690087D61B /* InputAccessoryBuilder.swift in Sources */, 08DB8CBA1D0BECF000A6D079 /* DiscussionTableViewCell.swift in Sources */, 08D1209C1C937B2200A54ABC /* ControllerHelper.swift in Sources */, + 087296DD20168FF2009F9256 /* TooltipDefaultsManager.swift in Sources */, 085C4FF71D8C835600B27C95 /* StepsControllerDeepLinkRouter.swift in Sources */, 08E6BB691DC8DF59006622EC /* UserActivitiesAPI.swift in Sources */, 08CB0D4E1FB63F83001A1E02 /* ContentLanguagesView.swift in Sources */, @@ -11553,6 +11628,7 @@ 08D120D51C937B2200A54ABC /* NumberQuizViewController.swift in Sources */, 08D120D61C937B2200A54ABC /* GCDThings.swift in Sources */, 08D120D81C937B2200A54ABC /* Block.swift in Sources */, + 086D5B4020127A25000F7715 /* Tooltip.swift in Sources */, 084472071D05918E00197166 /* ChoiceQuizTableViewCell.swift in Sources */, 08BC470A1CD9FE10009A1D25 /* PersistentTaskManagerProtocol.swift in Sources */, 083056D21DBFB4BE00F1F2A4 /* DiscussionWebTableViewCell.swift in Sources */, @@ -11656,6 +11732,7 @@ 083267A71CDCE64F002F7B5A /* PersistentTaskRecoveryManager.swift in Sources */, 08ECC4481DB8D3D60005D401 /* StyledNavigationViewController.swift in Sources */, 08AC21461CDD493A00FBB9CD /* PersistentRecoveryManager.swift in Sources */, + 086D5B53201283C2000F7715 /* TooltipFactory.swift in Sources */, 085C4FF41D89C86F00B27C95 /* UnitsAPI.swift in Sources */, 08CB0D291FB5CD5E001A1E02 /* CourseListsCache.swift in Sources */, 080CE1441E955D300089A27F /* CoursesAPI.swift in Sources */, @@ -11889,6 +11966,7 @@ 0857AA211BECDA640044B505 /* VideoDownload.swift in Sources */, 08AC21451CDD493A00FBB9CD /* PersistentRecoveryManager.swift in Sources */, 08F4859C1C5786DE000165AA /* StringQuizViewController.swift in Sources */, + 087296DC20168FF2009F9256 /* TooltipDefaultsManager.swift in Sources */, 080CE1431E955D300089A27F /* CoursesAPI.swift in Sources */, 08F485A51C57AF2E000165AA /* FreeAnswerReply.swift in Sources */, 08C1BF311FBA0CA1008F342F /* SearchResultsViewController.swift in Sources */, @@ -11910,6 +11988,7 @@ 2CC3518A1F682A02004255B6 /* SocialAuthCollectionViewCell.swift in Sources */, 08DF789E1F5DE64300AEEA85 /* ArtView.swift in Sources */, 08D2AE461C04BA6100BD8C3D /* Time.swift in Sources */, + 086D5B52201283C2000F7715 /* TooltipFactory.swift in Sources */, 0813EEA61BFE5A5400DB4B83 /* Assignment+CoreDataProperties.swift in Sources */, 080C5E7B1EFC13ED0036EB3D /* CodeSample.swift in Sources */, 9F9C71561E076B3E00EC8DA3 /* DataConvertable.swift in Sources */, @@ -12035,6 +12114,7 @@ 08F4859A1C57868E000165AA /* TextReply.swift in Sources */, 0828FF831BC800C0000AFEA7 /* JSONInitializable.swift in Sources */, 08CA59F41BC020E3008DC44D /* UIImageViewExtension.swift in Sources */, + 086D5B3F20127A25000F7715 /* Tooltip.swift in Sources */, 0837492A1DE5AF8A00144C14 /* StreaksAlertManager.swift in Sources */, 0828FF801BC7FD24000AFEA7 /* Lesson+CoreDataProperties.swift in Sources */, 080CE1491E9562430089A27F /* LessonsAPI.swift in Sources */, @@ -12361,10 +12441,12 @@ 2C1B61861F4C4AEF00236804 /* AnalyticsHelper.swift in Sources */, 2C1B61871F4C4AEF00236804 /* ControllerHelper.swift in Sources */, 2C1B61881F4C4AEF00236804 /* GCDThings.swift in Sources */, + 086D5B4520127A25000F7715 /* Tooltip.swift in Sources */, 2C1B61891F4C4AEF00236804 /* GlobalFunctions.swift in Sources */, 2C1B618A1F4C4AEF00236804 /* CongratulationViewController.swift in Sources */, 2C1B618B1F4C4AEF00236804 /* RatingHelper.swift in Sources */, 2C1B618C1F4C4AEF00236804 /* TimeFormatHelper.swift in Sources */, + 087296E220168FF2009F9256 /* TooltipDefaultsManager.swift in Sources */, 084490061F5CE15200D01940 /* SettingsPresenter.swift in Sources */, 2C1B618D1F4C4AEF00236804 /* WebViewHorizontalScrollHelper.swift in Sources */, 0897009C1F6B2A830041C24E /* NibInitializableView.swift in Sources */, @@ -12536,6 +12618,7 @@ 2C1B62191F4C4AEF00236804 /* VotesAPI.swift in Sources */, 2C1B621A1F4C4AEF00236804 /* CodeQuizToolbarView.swift in Sources */, 2C1B621B1F4C4AEF00236804 /* StepicsAPI.swift in Sources */, + 086D5B58201283C2000F7715 /* TooltipFactory.swift in Sources */, 2C1B621C1F4C4AEF00236804 /* UnitsAPI.swift in Sources */, 2C1B621D1F4C4AEF00236804 /* UserActivitiesAPI.swift in Sources */, 2C1B621F1F4C4AEF00236804 /* AdaptiveOnboardingViewController.swift in Sources */, @@ -12814,10 +12897,12 @@ 2C1B63971F4C590700236804 /* AnalyticsHelper.swift in Sources */, 2C1B63981F4C590700236804 /* ControllerHelper.swift in Sources */, 2C1B63991F4C590700236804 /* GCDThings.swift in Sources */, + 086D5B4620127A25000F7715 /* Tooltip.swift in Sources */, 2C1B639A1F4C590700236804 /* GlobalFunctions.swift in Sources */, 2C1B639B1F4C590700236804 /* CongratulationViewController.swift in Sources */, 2C1B639C1F4C590700236804 /* RatingHelper.swift in Sources */, 2C1B639D1F4C590700236804 /* TimeFormatHelper.swift in Sources */, + 087296E320168FF2009F9256 /* TooltipDefaultsManager.swift in Sources */, 084490071F5CE15200D01940 /* SettingsPresenter.swift in Sources */, 2C1B639E1F4C590700236804 /* WebViewHorizontalScrollHelper.swift in Sources */, 0897009D1F6B2A830041C24E /* NibInitializableView.swift in Sources */, @@ -12989,6 +13074,7 @@ 2C1B642A1F4C590700236804 /* VotesAPI.swift in Sources */, 2C1B642B1F4C590700236804 /* CodeQuizToolbarView.swift in Sources */, 2C1B642C1F4C590700236804 /* StepicsAPI.swift in Sources */, + 086D5B59201283C2000F7715 /* TooltipFactory.swift in Sources */, 2C1B642D1F4C590700236804 /* UnitsAPI.swift in Sources */, 2C1B642E1F4C590700236804 /* UserActivitiesAPI.swift in Sources */, 2C1B64301F4C590700236804 /* AdaptiveOnboardingViewController.swift in Sources */, @@ -13267,10 +13353,12 @@ 2C8653341F4B33DE00D51654 /* AnalyticsHelper.swift in Sources */, 2C8653351F4B33DE00D51654 /* ControllerHelper.swift in Sources */, 2C8653361F4B33DE00D51654 /* GCDThings.swift in Sources */, + 086D5B4220127A25000F7715 /* Tooltip.swift in Sources */, 2C8653371F4B33DE00D51654 /* GlobalFunctions.swift in Sources */, 2C8653381F4B33DE00D51654 /* CongratulationViewController.swift in Sources */, 2C8653391F4B33DE00D51654 /* RatingHelper.swift in Sources */, 2C86533A1F4B33DE00D51654 /* TimeFormatHelper.swift in Sources */, + 087296DF20168FF2009F9256 /* TooltipDefaultsManager.swift in Sources */, 084490031F5CE15200D01940 /* SettingsPresenter.swift in Sources */, 2C86533B1F4B33DE00D51654 /* WebViewHorizontalScrollHelper.swift in Sources */, 089700991F6B2A830041C24E /* NibInitializableView.swift in Sources */, @@ -13442,6 +13530,7 @@ 2C8653C71F4B33DE00D51654 /* VotesAPI.swift in Sources */, 2C8653C81F4B33DE00D51654 /* CodeQuizToolbarView.swift in Sources */, 2C8653C91F4B33DE00D51654 /* StepicsAPI.swift in Sources */, + 086D5B55201283C2000F7715 /* TooltipFactory.swift in Sources */, 2C8653CA1F4B33DE00D51654 /* UnitsAPI.swift in Sources */, 2C8653CB1F4B33DE00D51654 /* UserActivitiesAPI.swift in Sources */, 2C8653CD1F4B33DE00D51654 /* AdaptiveOnboardingViewController.swift in Sources */, @@ -13718,6 +13807,7 @@ 2C89AA1A1F4C289900227C3B /* AnalyticsHelper.swift in Sources */, 2C89AA1B1F4C289900227C3B /* ControllerHelper.swift in Sources */, 2C89AA1C1F4C289900227C3B /* GCDThings.swift in Sources */, + 087296E020168FF2009F9256 /* TooltipDefaultsManager.swift in Sources */, 08A9F7071FC37DD000640F1F /* CourseTagsView.swift in Sources */, 2C89AA1D1F4C289900227C3B /* GlobalFunctions.swift in Sources */, 2C89AA1E1F4C289900227C3B /* CongratulationViewController.swift in Sources */, @@ -13744,6 +13834,7 @@ 2C89AA2D1F4C289900227C3B /* DiscussionProxy.swift in Sources */, 2C89AA2E1F4C289900227C3B /* Comment.swift in Sources */, 2C89AA2F1F4C289900227C3B /* Vote.swift in Sources */, + 086D5B4320127A25000F7715 /* Tooltip.swift in Sources */, 2C89AA301F4C289900227C3B /* CodePlaygroundManager.swift in Sources */, 2C89AA311F4C289900227C3B /* Scripts.swift in Sources */, 085EDCB41F9945CD00AB3278 /* Notification+FetchMethods.swift in Sources */, @@ -13914,6 +14005,7 @@ 2C89AAC01F4C289900227C3B /* QuizPresenter.swift in Sources */, 2C89AAC11F4C289900227C3B /* StreaksStepikAlertManager.swift in Sources */, 2C89AAC21F4C289900227C3B /* InputAccessoryBuilder.swift in Sources */, + 086D5B56201283C2000F7715 /* TooltipFactory.swift in Sources */, 2C89AAC31F4C289900227C3B /* AlertManager.swift in Sources */, 08D5F5711F7DA6BB007C1634 /* CourseReviewSummary.swift in Sources */, 080217871F55B1B200186245 /* Menu.swift in Sources */, @@ -14172,10 +14264,12 @@ 2C9731CE1F4C38F600AC9301 /* AnalyticsHelper.swift in Sources */, 2C9731CF1F4C38F600AC9301 /* ControllerHelper.swift in Sources */, 2C9731D01F4C38F600AC9301 /* GCDThings.swift in Sources */, + 086D5B4420127A25000F7715 /* Tooltip.swift in Sources */, 2C9731D11F4C38F600AC9301 /* GlobalFunctions.swift in Sources */, 2C9731D21F4C38F600AC9301 /* CongratulationViewController.swift in Sources */, 2C9731D31F4C38F600AC9301 /* RatingHelper.swift in Sources */, 2C9731D41F4C38F600AC9301 /* TimeFormatHelper.swift in Sources */, + 087296E120168FF2009F9256 /* TooltipDefaultsManager.swift in Sources */, 084490051F5CE15200D01940 /* SettingsPresenter.swift in Sources */, 2C9731D51F4C38F600AC9301 /* WebViewHorizontalScrollHelper.swift in Sources */, 0897009B1F6B2A830041C24E /* NibInitializableView.swift in Sources */, @@ -14347,6 +14441,7 @@ 2C9732611F4C38F600AC9301 /* VotesAPI.swift in Sources */, 2C9732621F4C38F600AC9301 /* CodeQuizToolbarView.swift in Sources */, 2C9732631F4C38F600AC9301 /* StepicsAPI.swift in Sources */, + 086D5B57201283C2000F7715 /* TooltipFactory.swift in Sources */, 2C9732641F4C38F600AC9301 /* UnitsAPI.swift in Sources */, 2C9732651F4C38F600AC9301 /* UserActivitiesAPI.swift in Sources */, 2C9732671F4C38F600AC9301 /* AdaptiveOnboardingViewController.swift in Sources */, @@ -14679,10 +14774,12 @@ 864D66981E83DE03001E8D9E /* AnalyticsHelper.swift in Sources */, 864D66991E83DE03001E8D9E /* ControllerHelper.swift in Sources */, 864D669A1E83DE03001E8D9E /* GCDThings.swift in Sources */, + 086D5B4120127A25000F7715 /* Tooltip.swift in Sources */, 864D669B1E83DE03001E8D9E /* GlobalFunctions.swift in Sources */, 2C5F6BA91F20B2A900C251D3 /* CongratulationViewController.swift in Sources */, 2CEDA3601F336FEC005F4A5D /* RatingHelper.swift in Sources */, 864D669C1E83DE03001E8D9E /* TimeFormatHelper.swift in Sources */, + 087296DE20168FF2009F9256 /* TooltipDefaultsManager.swift in Sources */, 084490021F5CE15200D01940 /* SettingsPresenter.swift in Sources */, 864D669D1E83DE03001E8D9E /* WebViewHorizontalScrollHelper.swift in Sources */, 089700981F6B2A830041C24E /* NibInitializableView.swift in Sources */, @@ -14854,6 +14951,7 @@ 864D67101E83DE03001E8D9E /* VotesAPI.swift in Sources */, 080C5E791EFC09730036EB3D /* CodeQuizToolbarView.swift in Sources */, 864D67111E83DE03001E8D9E /* StepicsAPI.swift in Sources */, + 086D5B54201283C2000F7715 /* TooltipFactory.swift in Sources */, 864D67121E83DE03001E8D9E /* UnitsAPI.swift in Sources */, 864D67131E83DE03001E8D9E /* UserActivitiesAPI.swift in Sources */, 2CA50BA01F0FE79E00418E7D /* AdaptiveOnboardingViewController.swift in Sources */, diff --git a/Stepic.xcodeproj/xcuserdata/Ostrenkiy.xcuserdatad/xcschemes/xcschememanagement.plist b/Stepic.xcodeproj/xcuserdata/Ostrenkiy.xcuserdatad/xcschemes/xcschememanagement.plist index 6b0b17e480..3b2235ce1e 100644 --- a/Stepic.xcodeproj/xcuserdata/Ostrenkiy.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Stepic.xcodeproj/xcuserdata/Ostrenkiy.xcuserdatad/xcschemes/xcschememanagement.plist @@ -122,7 +122,7 @@ StepikTV.xcscheme orderHint - 90 + 92 StickerPackExtension.xcscheme diff --git a/Stepic/CourseListPresenter.swift b/Stepic/CourseListPresenter.swift index ebc998d5e6..dd38734d21 100644 --- a/Stepic/CourseListPresenter.swift +++ b/Stepic/CourseListPresenter.swift @@ -181,7 +181,7 @@ class CourseListPresenter { [weak self] course -> Void in self?.view?.finishProgressHUD(success: true, message: "") - if let controller = self?.getSectionsController(for: course) { + if let controller = self?.getSectionsController(for: course, didSubscribe: true) { self?.view?.show(controller: controller) } }.catch { @@ -536,12 +536,13 @@ class CourseListPresenter { } } - private func getSectionsController(for course: Course, sourceView: UIView? = nil) -> UIViewController? { + private func getSectionsController(for course: Course, sourceView: UIView? = nil, didSubscribe: Bool = false) -> UIViewController? { guard let courseVC = ControllerHelper.instantiateViewController(identifier: "SectionsViewController") as? SectionsViewController else { return nil } AnalyticsReporter.reportEvent(AnalyticsEvents.PeekNPop.Course.peeked) courseVC.course = course + courseVC.shouldShowShareTooltip = didSubscribe courseVC.parentShareBlock = { [weak self] shareVC in diff --git a/Stepic/CoursePreviewViewController.swift b/Stepic/CoursePreviewViewController.swift index 6e991fa184..503cd2206c 100644 --- a/Stepic/CoursePreviewViewController.swift +++ b/Stepic/CoursePreviewViewController.swift @@ -352,6 +352,7 @@ class CoursePreviewViewController: UIViewController, ShareableController { if segue.identifier == "showSections" { let dvc = segue.destination as! SectionsViewController dvc.course = course + dvc.shouldShowShareTooltip = true } } diff --git a/Stepic/CourseSubscriptionManager.swift b/Stepic/CourseSubscriptionManager.swift index de85fc75d6..9441cff23f 100644 --- a/Stepic/CourseSubscriptionManager.swift +++ b/Stepic/CourseSubscriptionManager.swift @@ -16,7 +16,6 @@ class CourseSubscriptionManager: NSObject { let courseUnsubscribedNotificationName = NSNotification.Name(rawValue: "CourseUnsubscribedNotification") var handleUpdatesBlock: (() -> Void)? - override init() {} func startObservingOtherSubscriptionManagers() { diff --git a/Stepic/HomeScreenViewController.swift b/Stepic/HomeScreenViewController.swift index 3501cff9c9..a7cb2514ee 100644 --- a/Stepic/HomeScreenViewController.swift +++ b/Stepic/HomeScreenViewController.swift @@ -26,6 +26,8 @@ class HomeScreenViewController: UIViewController, HomeScreenView { private let streaksWidgetBackgroundView = UIView() private var streaksWidgetView: UserActivityHomeView? + private var continueLearningTooltip: Tooltip? + override func viewDidLoad() { super.viewDidLoad() self.presenter = HomeScreenPresenter(view: self, userActivitiesAPI: UserActivitiesAPI()) @@ -42,6 +44,11 @@ class HomeScreenViewController: UIViewController, HomeScreenView { presenter?.checkStreaks() } + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + continueLearningTooltip?.dismiss() + } + private func setupStackView() { scrollView.translatesAutoresizingMaskIntoConstraints = false self.view.addSubview(scrollView) @@ -143,9 +150,16 @@ class HomeScreenViewController: UIViewController, HomeScreenView { stackView.insertArrangedSubview(widgetBackgroundView, at: streaksWidgetView == nil ? 0 : 1) widgetBackgroundView.alignLeading("0", trailing: "0", toView: self.view) - UIView.animate(withDuration: 0.15) { + UIView.animate(withDuration: 0.15, animations: { self.widgetBackgroundView.isHidden = false - } + }, completion: { + _ in + if TooltipDefaultsManager.shared.shouldShowOnHomeContinueLearning { + self.continueLearningTooltip = TooltipFactory.continueLearningWidget + self.continueLearningTooltip?.show(direction: .up, in: nil, from: self.continueLearningWidget.continueLearningButton) + TooltipDefaultsManager.shared.didShowOnHomeContinueLearning = true + } + }) if !isContinueLearningWidgetPresented { isContinueLearningWidgetPresented = true @@ -155,6 +169,7 @@ class HomeScreenViewController: UIViewController, HomeScreenView { func hideCountinueLearningWidget() { isContinueLearningWidgetPresented = false stackView.removeArrangedSubview(widgetBackgroundView) + continueLearningTooltip?.dismiss() UIView.animate(withDuration: 0.15) { self.widgetBackgroundView.isHidden = true } diff --git a/Stepic/Menu.swift b/Stepic/Menu.swift index 546fd55475..6ac7145a3a 100644 --- a/Stepic/Menu.swift +++ b/Stepic/Menu.swift @@ -16,6 +16,12 @@ class Menu { self.blocks = blocks } + func getBlockIndex(id: String) -> Int? { + return blocks.index(where: { + $0.id == id + }) + } + func getBlock(id: String) -> MenuBlock? { return blocks.first(where: { $0.id == id diff --git a/Stepic/ProfilePresenter.swift b/Stepic/ProfilePresenter.swift index ff87beeca8..245eb79666 100644 --- a/Stepic/ProfilePresenter.swift +++ b/Stepic/ProfilePresenter.swift @@ -41,7 +41,7 @@ class ProfilePresenter { // MARK: - Menu initialization - private let notificationsSwitchBlockId = "notifications_switch" + let notificationsSwitchBlockId = "notifications_switch" private let notificationsTimeSelectionBlockId = "notifications_time_selection" private let infoBlockId = "info" private let settingsBlockId = "settings" diff --git a/Stepic/ProfileViewController.swift b/Stepic/ProfileViewController.swift index 189bb0d845..048255f4df 100644 --- a/Stepic/ProfileViewController.swift +++ b/Stepic/ProfileViewController.swift @@ -97,8 +97,42 @@ class ProfileViewController: MenuViewController, ProfileView { self.streaks = streaks } + var streaksTooltip: Tooltip? + func set(menu: Menu) { self.menu = menu + + guard let presenter = presenter else { + return + } + + guard let blockIndex = menu.getBlockIndex(id: presenter.notificationsSwitchBlockId), + let block = menu.getBlock(id: presenter.notificationsSwitchBlockId) as? SwitchMenuBlock else { + return + } + + if TooltipDefaultsManager.shared.shouldShowOnStreaksSwitchInProfile { + delay(0.1) { + [weak self] in + guard let s = self else { + return + } + if let cell = s.tableView.cellForRow(at: IndexPath(row: blockIndex, section: 0)) as? SwitchMenuBlockTableViewCell { + if !cell.blockSwitch.isOn { + let oldOnSwitch = block.onSwitch + block.onSwitch = { + [weak self] + isOn in + self?.streaksTooltip?.dismiss() + oldOnSwitch?(isOn) + } + s.streaksTooltip = TooltipFactory.streaksTooltip + s.streaksTooltip?.show(direction: .up, in: s.tableView, from: cell.blockSwitch) + TooltipDefaultsManager.shared.didShowOnStreaksSwitchInProfile = true + } + } + } + } } func showNotificationSettingsAlert(completion: (() -> Void)?) { @@ -164,6 +198,11 @@ class ProfileViewController: MenuViewController, ProfileView { super.viewWillAppear(animated) onAppear() } + + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + streaksTooltip?.dismiss() + } } extension ProfileViewController : DZNEmptyDataSetDelegate { diff --git a/Stepic/SectionsViewController.swift b/Stepic/SectionsViewController.swift index 9b39ac6ab9..6695523849 100644 --- a/Stepic/SectionsViewController.swift +++ b/Stepic/SectionsViewController.swift @@ -17,9 +17,11 @@ class SectionsViewController: UIViewController, ShareableController, UIViewContr let refreshControl = UIRefreshControl() var didRefresh = false var course: Course! - var moduleId: Int? var parentShareBlock: ((UIActivityViewController) -> Void)? + private var shareBarButtonItem: UIBarButtonItem! + private var shareTooltip: Tooltip? + var shouldShowShareTooltip: Bool = false override func viewDidLoad() { super.viewDidLoad() @@ -30,7 +32,7 @@ class SectionsViewController: UIViewController, ShareableController, UIViewContr tableView.tableFooterView = UIView() self.navigationItem.backBarButtonItem?.title = " " - let shareBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.action, target: self, action: #selector(SectionsViewController.shareButtonPressed(_:))) + shareBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.action, target: self, action: #selector(SectionsViewController.shareButtonPressed(_:))) let infoBtn = UIButton(type: UIButtonType.infoDark) infoBtn.addTarget(self, action: #selector(SectionsViewController.infoButtonPressed(_:)), for: UIControlEvents.touchUpInside) let infoBarButtonItem = UIBarButtonItem(customView: infoBtn) @@ -97,6 +99,20 @@ class SectionsViewController: UIViewController, ShareableController, UIViewContr } } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + if shouldShowShareTooltip { + shareTooltip = TooltipFactory.streaksTooltip + shareTooltip?.show(direction: .up, in: nil, from: shareBarButtonItem) + shouldShowShareTooltip = false + } + } + + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + shareTooltip?.dismiss() + } + var emptyDatasetState: EmptyDatasetState = .empty { didSet { UIThread.performUI { @@ -201,7 +217,7 @@ class SectionsViewController: UIViewController, ShareableController, UIViewContr AnalyticsReporter.reportEvent(AnalyticsEvents.Syllabus.shared, parameters: nil) let shareBlock: ((UIActivityViewController) -> Void)? = parentShareBlock let url = self.url - + shareTooltip?.dismiss() DispatchQueue.global(qos: .background).async { [weak self] in diff --git a/Stepic/Tooltip.swift b/Stepic/Tooltip.swift new file mode 100644 index 0000000000..85c8e8f18d --- /dev/null +++ b/Stepic/Tooltip.swift @@ -0,0 +1,122 @@ +// +// Tooltip.swift +// Stepic +// +// Created by Ostrenkiy on 19.01.2018. +// Copyright © 2018 Alex Karpov. All rights reserved. +// + +import Foundation +import EasyTipView + +protocol Tooltip { + init(text: String, shouldDismissAfterTime: Bool, color: TooltipColor) + func show(direction: TooltipDirection, in inView: UIView?, from fromView: UIView) + func show(direction: TooltipDirection, in inView: UIView?, from fromItem: UIBarButtonItem) + func dismiss() +} + +enum TooltipColor { + case light, dark, standard + + var textColor: UIColor { + switch self { + case .light: + return UIColor.mainDark + case .dark: + return UIColor.mainLight + case .standard: + return UIColor.white + } + } + + var borderColor: UIColor { + switch self { + case .light: + return UIColor.mainDark + case .dark: + return UIColor.mainLight + case .standard: + return UIColor.thirdColor + } + } + + var backgroundColor: UIColor { + switch self { + case .light: + return UIColor.mainLight + case .dark: + return UIColor.mainDark + case .standard: + return UIColor.thirdColor + } + } +} + +class EasyTipTooltip: Tooltip { + private var easyTip: EasyTipView = EasyTipView(text: "") + private var preferences: EasyTipView.Preferences + let dismissesAfter: TimeInterval = 7.5 + + var text: String + var shouldDismissAfterTime: Bool + + private func easyTipDirectionFromTooltipDirection(direction: TooltipDirection) -> EasyTipView.ArrowPosition { + switch direction { + case .up: + return EasyTipView.ArrowPosition.top + case .left: + return EasyTipView.ArrowPosition.left + case .right: + return EasyTipView.ArrowPosition.right + case .down: + return EasyTipView.ArrowPosition.bottom + } + } + + required init(text: String, shouldDismissAfterTime: Bool, color: TooltipColor) { + self.text = text + self.shouldDismissAfterTime = shouldDismissAfterTime + preferences = EasyTipView.Preferences() + preferences.drawing.font = UIFont.systemFont(ofSize: 14) + preferences.drawing.foregroundColor = color.textColor + preferences.drawing.backgroundColor = color.backgroundColor + preferences.drawing.borderWidth = 1.0 + preferences.drawing.borderColor = color.borderColor + } + + private func setupTooltip(direction: TooltipDirection) { + preferences.drawing.arrowPosition = easyTipDirectionFromTooltipDirection(direction: direction) + easyTip = EasyTipView(text: text, preferences: preferences, delegate: nil) + } + + private func setupDisappear() { + guard shouldDismissAfterTime else { + return + } + delay(dismissesAfter) { + [weak self] in + self?.dismiss() + } + } + + func show(direction: TooltipDirection, in inView: UIView?, from fromView: UIView) { + setupTooltip(direction: direction) + easyTip.show(forView: fromView, withinSuperview: inView) + setupDisappear() + } + + func show(direction: TooltipDirection, in inView: UIView?, from fromItem: UIBarButtonItem) { + setupTooltip(direction: direction) + easyTip.show(forItem: fromItem, withinSuperView: inView) + setupDisappear() + } + + func dismiss() { + easyTip.dismiss() + } +} + +enum TooltipDirection { + case left, up, right, down +} diff --git a/Stepic/TooltipDefaultsManager.swift b/Stepic/TooltipDefaultsManager.swift new file mode 100644 index 0000000000..50ae4637d6 --- /dev/null +++ b/Stepic/TooltipDefaultsManager.swift @@ -0,0 +1,62 @@ +// +// TooltipDefaultsManager.swift +// Stepic +// +// Created by Ostrenkiy on 23.01.2018. +// Copyright © 2018 Alex Karpov. All rights reserved. +// + +import Foundation + +class TooltipDefaultsManager { + static let shared = TooltipDefaultsManager() + private init() {} + + private let defaults = UserDefaults.standard + + private let didShowOnLessonDownloadsKey = "didShowOnLessonDownloadsKey" + private let didShowOnHomeContinueLearningKey = "didShowOnHomeContinueLearningKey" + private let didShowOnStreaksSwitchInProfileKey = "didShowOnStreaksSwitchInProfileKey" + + var didShowOnLessonDownloads: Bool { + set(value) { + defaults.set(value, forKey: didShowOnLessonDownloadsKey) + } + + get { + return defaults.value(forKey: didShowOnLessonDownloadsKey) as? Bool ?? false + } + } + + var didShowOnHomeContinueLearning: Bool { + set(value) { + defaults.set(value, forKey: didShowOnHomeContinueLearningKey) + } + + get { + return defaults.value(forKey: didShowOnHomeContinueLearningKey) as? Bool ?? false + } + } + + var didShowOnStreaksSwitchInProfile: Bool { + set(value) { + defaults.set(value, forKey: didShowOnStreaksSwitchInProfileKey) + } + + get { + return defaults.value(forKey: didShowOnStreaksSwitchInProfileKey) as? Bool ?? false + } + } + + var shouldShowOnHomeContinueLearning: Bool { + return !didShowOnHomeContinueLearning + } + + var shouldShowLessonDownloadsTooltip: Bool { + return !didShowOnLessonDownloads + } + + var shouldShowOnStreaksSwitchInProfile: Bool { + return !didShowOnStreaksSwitchInProfile + } +} diff --git a/Stepic/TooltipFactory.swift b/Stepic/TooltipFactory.swift new file mode 100644 index 0000000000..8dfb75a6ea --- /dev/null +++ b/Stepic/TooltipFactory.swift @@ -0,0 +1,27 @@ +// +// TooltipFactory.swift +// Stepic +// +// Created by Ostrenkiy on 19.01.2018. +// Copyright © 2018 Alex Karpov. All rights reserved. +// + +import Foundation + +struct TooltipFactory { + static var sharingCourse: Tooltip { + return EasyTipTooltip(text: NSLocalizedString("ShareCourseTooltip", comment: ""), shouldDismissAfterTime: true, color: .standard) + } + + static var lessonDownload: Tooltip { + return EasyTipTooltip(text: NSLocalizedString("LessonDownloadTooltip", comment: ""), shouldDismissAfterTime: true, color: .standard) + } + + static var continueLearningWidget: Tooltip { + return EasyTipTooltip(text: NSLocalizedString("ContinueLearningWidgetTooltip", comment: ""), shouldDismissAfterTime: true, color: .standard) + } + + static var streaksTooltip: Tooltip { + return EasyTipTooltip(text: NSLocalizedString("StreaksSwitchTooltip", comment: ""), shouldDismissAfterTime: true, color: .standard) + } +} diff --git a/Stepic/UIColorExtensions.swift b/Stepic/UIColorExtensions.swift index 5275ac7133..8981fb7cb6 100644 --- a/Stepic/UIColorExtensions.swift +++ b/Stepic/UIColorExtensions.swift @@ -44,6 +44,7 @@ extension UIColor { static let mainLight: UIColor = UIColor(hex: 0xf6f6f6) static let mainDark: UIColor = StepicApplicationsInfo.Colors.mainDark static let mainText: UIColor = StepicApplicationsInfo.Colors.mainText + static let thirdColor: UIColor = UIColor(hex: 0x54a2ff) static let correctQuizBackground: UIColor = UIColor(hex: 0xE9F9E9) static let wrongQuizBackground: UIColor = UIColor(hex: 0xF5EBF2) diff --git a/Stepic/UnitsViewController.swift b/Stepic/UnitsViewController.swift index b3cfcec635..24adeb2827 100644 --- a/Stepic/UnitsViewController.swift +++ b/Stepic/UnitsViewController.swift @@ -27,6 +27,8 @@ class UnitsViewController: UIViewController, ShareableController, UIViewControll var parentShareBlock: ((UIActivityViewController) -> Void)? + var downloadTooltip: Tooltip? + fileprivate func updateTitle() { self.navigationItem.title = section?.title ?? NSLocalizedString("Module", comment: "") } @@ -179,6 +181,11 @@ class UnitsViewController: UIViewController, ShareableController, UIViewControll }) } + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + downloadTooltip?.dismiss() + } + override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.navigationItem.backBarButtonItem?.title = " " @@ -530,6 +537,19 @@ extension UnitsViewController : UITableViewDataSource { cell.initWithUnit(section.units[(indexPath as NSIndexPath).row], delegate: self) + if indexPath.row == 0 && TooltipDefaultsManager.shared.shouldShowLessonDownloadsTooltip { + //Delay here to fight some layout issues + delay(0.1) { + [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.downloadTooltip = TooltipFactory.lessonDownload + strongSelf.downloadTooltip?.show(direction: .up, in: strongSelf.tableView, from: cell.downloadButton) + TooltipDefaultsManager.shared.didShowOnLessonDownloads = true + } + } + return cell } } diff --git a/Stepic/en.lproj/Localizable.strings b/Stepic/en.lproj/Localizable.strings index dd4e604382..3aaa7ca7bf 100644 --- a/Stepic/en.lproj/Localizable.strings +++ b/Stepic/en.lproj/Localizable.strings @@ -373,5 +373,11 @@ OnboardingStartButton = "Start"; StreakAlertMessageNoStreak = "Solve quizzes every day and improve your streak! Would you like to be notified about streaks to learn every day? You can always change this option in preferences."; +/* Tooltips */ +ShareCourseTooltip = "Share the link with your friends to learn together"; +LessonDownloadTooltip = "Download lesson "; +ContinueLearningWidgetTooltip = "Tap to continue from where you finished last time"; +StreaksSwitchTooltip = "Turn on to get new portion of knowledge every day"; + /* Arts */ ArtCustomizeLearningProcess = "art_customize_learning_process_en"; diff --git a/Stepic/ru.lproj/Localizable.strings b/Stepic/ru.lproj/Localizable.strings index 6930406022..3214e39112 100644 --- a/Stepic/ru.lproj/Localizable.strings +++ b/Stepic/ru.lproj/Localizable.strings @@ -374,5 +374,11 @@ OnboardingStartButton = "Начать"; StreakAlertMessageNoStreak = "Решайте задачи каждый день и улучшайте личный рекорд! Хотели бы Вы получать уведомления, чтобы не забывать учиться каждый день? Эту опцию можно изменить в настройках."; +/* Tooltips */ +ShareCourseTooltip = "Поделитесь ссылкой с друзьями, чтобы проходить курс вместе"; +LessonDownloadTooltip = "Загрузите урок, чтобы смотреть видео оффлайн"; +ContinueLearningWidgetTooltip = "Нажмите, чтобы перейти к тому месту, где закончили в прошлый раз"; +StreaksSwitchTooltip = "Включите, чтобы получать новую порцию знаний каждый день"; + /* Arts */ ArtCustomizeLearningProcess = "art_customize_learning_process_ru";