From f33313a78691ef024acfe659cbbdc5984970c0db Mon Sep 17 00:00:00 2001 From: Michael Cavallaro Date: Mon, 18 Dec 2023 10:08:43 -0700 Subject: [PATCH] Beautiful gradient animation, fixed loading spinner, made stars look like web --- .../CommandBarIOS.xcodeproj/project.pbxproj | 4 + Example/CommandBarIOS/App.swift | 1 + Example/CommandBarIOS/Views/Color.swift | 100 ++++ .../CommandBarIOS/Views/GradientView.swift | 107 ++-- Example/CommandBarIOS/Views/HomeView.swift | 43 +- Example/Podfile | 2 +- Example/Podfile.lock | 2 +- Example/Pods/Manifest.lock | 2 +- Example/Pods/Pods.xcodeproj/project.pbxproj | 529 +++++++++--------- README.md | 29 +- .../CommandBarIOS/CommandBar/Analytics.swift | 46 +- Sources/CommandBarIOS/Components/Image.swift | 2 +- .../CommandBarIOS/Components/Spinner.swift | 23 +- Sources/CommandBarIOS/Components/Video.swift | 2 +- Sources/CommandBarIOS/Helpers/Color.swift | 99 ++++ .../Nudges/Content/SurveyRatingBlock.swift | 40 +- .../Nudges/NudgeWindowManager.swift | 53 +- 17 files changed, 675 insertions(+), 409 deletions(-) create mode 100644 Example/CommandBarIOS/Views/Color.swift create mode 100644 Sources/CommandBarIOS/Helpers/Color.swift diff --git a/Example/CommandBarIOS.xcodeproj/project.pbxproj b/Example/CommandBarIOS.xcodeproj/project.pbxproj index d2061c9..47b1671 100644 --- a/Example/CommandBarIOS.xcodeproj/project.pbxproj +++ b/Example/CommandBarIOS.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ FF409B4A2B2F76C900D2A3CD /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF409B492B2F76C900D2A3CD /* GradientView.swift */; }; FF409B4C2B2F7B0800D2A3CD /* Toast.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF409B4B2B2F7B0800D2A3CD /* Toast.swift */; }; FF409B502B2FB49C00D2A3CD /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FF409B4F2B2FB49C00D2A3CD /* LaunchScreen.storyboard */; }; + FF409B522B30995800D2A3CD /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF409B512B30995800D2A3CD /* Color.swift */; }; FFB6A38B2B1BC93D0036D16F /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB6A38A2B1BC93D0036D16F /* App.swift */; }; FFB6A38D2B1E27850036D16F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB6A38C2B1E27850036D16F /* AppDelegate.swift */; }; FFB6A3902B1F98860036D16F /* ConfettiSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = FFB6A38F2B1F98860036D16F /* ConfettiSwiftUI */; }; @@ -57,6 +58,7 @@ FF409B492B2F76C900D2A3CD /* GradientView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradientView.swift; sourceTree = ""; }; FF409B4B2B2F7B0800D2A3CD /* Toast.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toast.swift; sourceTree = ""; }; FF409B4F2B2FB49C00D2A3CD /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; + FF409B512B30995800D2A3CD /* Color.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = ""; }; FFB6A38A2B1BC93D0036D16F /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = ""; }; FFB6A38C2B1E27850036D16F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -181,6 +183,7 @@ FF409B472B2F717200D2A3CD /* Button.swift */, FF409B492B2F76C900D2A3CD /* GradientView.swift */, FF409B4B2B2F7B0800D2A3CD /* Toast.swift */, + FF409B512B30995800D2A3CD /* Color.swift */, ); path = Views; sourceTree = ""; @@ -371,6 +374,7 @@ FF409B4C2B2F7B0800D2A3CD /* Toast.swift in Sources */, FFB6A38B2B1BC93D0036D16F /* App.swift in Sources */, FF409B412B2F6A7200D2A3CD /* SceneDelegate.swift in Sources */, + FF409B522B30995800D2A3CD /* Color.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Example/CommandBarIOS/App.swift b/Example/CommandBarIOS/App.swift index f521984..838422b 100644 --- a/Example/CommandBarIOS/App.swift +++ b/Example/CommandBarIOS/App.swift @@ -11,6 +11,7 @@ struct CommandBarIOSExampleApp: App { WindowGroup { HomeView() } + } } diff --git a/Example/CommandBarIOS/Views/Color.swift b/Example/CommandBarIOS/Views/Color.swift new file mode 100644 index 0000000..a7874be --- /dev/null +++ b/Example/CommandBarIOS/Views/Color.swift @@ -0,0 +1,100 @@ +import Foundation +import SwiftUI + +extension Color { + func uiColor() -> UIColor { + + if #available(iOS 14.0, *) { + return UIColor(self) + } + + let components = self.components() + return UIColor(red: components.r, green: components.g, blue: components.b, alpha: components.a) + } + + private func components() -> (r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat) { + + let scanner = Scanner(string: self.description.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)) + var hexNumber: UInt64 = 0 + var r: CGFloat = 0.0, g: CGFloat = 0.0, b: CGFloat = 0.0, a: CGFloat = 0.0 + + let result = scanner.scanHexInt64(&hexNumber) + if result { + r = CGFloat((hexNumber & 0xff000000) >> 24) / 255 + g = CGFloat((hexNumber & 0x00ff0000) >> 16) / 255 + b = CGFloat((hexNumber & 0x0000ff00) >> 8) / 255 + a = CGFloat(hexNumber & 0x000000ff) / 255 + } + return (r, g, b, a) + } + + static func random() -> Color { + let red = Double.random(in: 0..<1) + let green = Double.random(in: 0..<1) + let blue = Double.random(in: 0..<1) + return Color(red: red, green: green, blue: blue) + } + + init(uiColor: UIColor) { + self.init(red: Double(uiColor.components.red), + green: Double(uiColor.components.green), + blue: Double(uiColor.components.blue), + opacity: Double(uiColor.components.alpha)) + } + + func lighter(by percentage: CGFloat = 30.0) -> Color { + if let uiColor = self.uiColor().lighter(by: percentage) { + return Color(uiColor: uiColor) + } + return self + + } + + func darker(by percentage: CGFloat = 30.0) -> Color { + if let uiColor = self.uiColor().darker(by: percentage) { + return Color(uiColor: uiColor) + } + return self + + } + + func adjust(by percentage: CGFloat = 30.0) -> Color { + let components = self.components() + return Color(red: min(Double(components.r + percentage/100), 1.0), + green: min(Double(components.g + percentage/100), 1.0), + blue: min(Double(components.b + percentage/100), 1.0), + opacity: Double(components.a)) + } +} + + +extension UIColor { + var components: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) { + var red: CGFloat = 0 + var green: CGFloat = 0 + var blue: CGFloat = 0 + var alpha: CGFloat = 0 + getRed(&red, green: &green, blue: &blue, alpha: &alpha) + + return (red, green, blue, alpha) + } + func lighter(by percentage: CGFloat = 30.0) -> UIColor? { + return self.adjust(by: abs(percentage) ) + } + + func darker(by percentage: CGFloat = 30.0) -> UIColor? { + return self.adjust(by: -1 * abs(percentage) ) + } + + func adjust(by percentage: CGFloat = 30.0) -> UIColor? { + var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0 + if self.getRed(&red, green: &green, blue: &blue, alpha: &alpha) { + return UIColor(red: min(red + percentage/100, 1.0), + green: min(green + percentage/100, 1.0), + blue: min(blue + percentage/100, 1.0), + alpha: alpha) + } else { + return nil + } + } +} diff --git a/Example/CommandBarIOS/Views/GradientView.swift b/Example/CommandBarIOS/Views/GradientView.swift index 8f3f9e6..d32199a 100644 --- a/Example/CommandBarIOS/Views/GradientView.swift +++ b/Example/CommandBarIOS/Views/GradientView.swift @@ -2,61 +2,78 @@ import SwiftUI import UIKit struct GradientView: View { + + @State private var stage: Double = 0 + private let maxStages: Double = 10.0 + + private let startColor: Color = .purple + private let endColor: Color = .blue.darker(by: 2) + + private let timer = Timer.publish(every: 0.1, on: .main, in: .commonModes).autoconnect() // adjust as needed + var body: some View { ZStack { - RadialGradient( - gradient: Gradient(colors: [Color(hue: 198/360, saturation: 1, brightness: 0.8), Color.clear]), - center: .init(x: 0.82, y: 0.65), - startRadius: 0, - endRadius: 0.55 * UIScreen.main.bounds.width - ) - RadialGradient( - gradient: Gradient(colors: [Color(hue: 220/360, saturation: 0.37, brightness: 0.97), Color.clear]), - center: .init(x: 0.47, y: 0.33), - startRadius: 0, - endRadius: 0.59 * UIScreen.main.bounds.width - ) - - }.background( - LinearGradient(gradient: Gradient(colors: [.purple, .blue]), startPoint: .top, endPoint: .bottom).edgesIgnoringSafeArea(/*@START_MENU_TOKEN@*/.all/*@END_MENU_TOKEN@*/) - ) + ForEach(0..<(Int(maxStages)), id: \.self) { i in + gradient(for: i) + .opacity(opacity(for: i)) + .animation(.linear(duration: 0.4), value: self.stage) + + } + } + .edgesIgnoringSafeArea(.all) + .onAppear{ + Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { _ in + withAnimation { + self.stage = (self.stage + 1) + } + } + } } -} - -struct GradientBackgroundRepresentable: UIViewControllerRepresentable { + private func gradient(for index: Int) -> LinearGradient { + print(index) + let points = gradientPoints(for: index) + return LinearGradient( + gradient: Gradient(colors: [startColor, endColor]), + startPoint: points.0, + endPoint: points.1 + ) + } - func makeUIViewController(context: Context) -> UIViewController { - let hostingController = UIHostingController(rootView: GradientView()) - return hostingController + private func gradientPoints(for index: Int) -> (UnitPoint, UnitPoint) { + switch index { + case 0: + return (.topLeading, .bottomTrailing) + case 1: + return (.top, .bottom) + case 2: + return (.topTrailing, .bottomLeading) + case 3: + return (.trailing, .leading) + case 4: + return (.bottomTrailing, .topLeading) + case 5: + return (.bottom, .top) + case 6: + return (.bottomLeading, .topTrailing) + case 7: + return (.leading, .trailing) + case 8: + return (.topLeading, .bottomTrailing) + default: + return (.topLeading, .bottomTrailing) + } } - func updateUIViewController(_ uiViewController: UIViewController, context: Context) { - + private func opacity(for index: Int) -> Double { + let adjustedStage = (self.stage - Double(index)) / self.maxStages + return max(0, 0.5 * cos(2 * Double.pi * adjustedStage) + 0.5) } } -class GradientBackgroundViewController: UIViewController { - - override func viewDidLoad() { - super.viewDidLoad() - - let gradientBackgroundView = UIHostingController(rootView: GradientView()) - // Add as a child of the current view controller. - addChildViewController(gradientBackgroundView) - // Add the SwiftUI view to the view controller view hierarchy. - view.addSubview(gradientBackgroundView.view) - // Setup constraints to update the SwiftUI view boundaries. -// gradientBackgroundView.view.translatesAutoresizingMaskIntoConstraints = false -// NSLayoutConstraint.activate([ -// gradientBackgroundView.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), -// gradientBackgroundView.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), -// gradientBackgroundView.view.topAnchor.constraint(equalTo: view.topAnchor), -// gradientBackgroundView.view.bottomAnchor.constraint(equalTo: view.bottomAnchor) -// ]) -// -// // Notify the hosting controller that it has been moved to the current view controller. -// gradientBackgroundView.didMove(toParent: self) +struct GradientView_Previews: PreviewProvider { + static var previews: some View { + GradientView() } } diff --git a/Example/CommandBarIOS/Views/HomeView.swift b/Example/CommandBarIOS/Views/HomeView.swift index cce60ef..0b4496b 100644 --- a/Example/CommandBarIOS/Views/HomeView.swift +++ b/Example/CommandBarIOS/Views/HomeView.swift @@ -15,8 +15,24 @@ struct HomeView: View { VStack(alignment: .center) { ZStack { GradientView() - Main - + VStack { + Spacer() + VStack { + LogoView() + .shadow(color: Color.black.opacity(0.3), radius: 10, x: 0, y: 5) + Text("Welcome to CommandBar!") + .multilineTextAlignment(.center) + .font(.title) + } + Spacer() + VStack() { + CustomButton(title: "Trigger Test Event") { + // 3. Track Events + CommandBarSDK.shared.trackEvent(event: "test_event") + } + } + }.padding(.horizontal) + if ORG_ID == "" { VStack(alignment: .leading) { Toast(message: "Org ID not set.") @@ -33,27 +49,4 @@ struct HomeView: View { } } } - - var Main: some View { - VStack { - Spacer() - VStack { - LogoView() - .shadow(color: Color.black.opacity(0.3), radius: 10, x: 0, y: 5) - Text("Welcome to CommandBar!") - .multilineTextAlignment(.center) - .font(.title) - } - Spacer() - VStack() { - CustomButton(title: "Trigger Test Event") { - // 3. Track Events - CommandBarSDK.shared.trackEvent(event: "test_event") - } - CustomButton(title: "Open HelpHub") { - CommandBarSDK.shared.openHelpHub() - } - } - }.padding(.horizontal) - } } diff --git a/Example/Podfile b/Example/Podfile index 22e566b..c86530b 100644 --- a/Example/Podfile +++ b/Example/Podfile @@ -1,6 +1,6 @@ use_frameworks! -platform :ios, '15.0' +platform :ios, '13.0' target 'CommandBarIOS_Example' do pod 'CommandBarIOS', :path => '../' diff --git a/Example/Podfile.lock b/Example/Podfile.lock index e6acd6f..96c4487 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -11,6 +11,6 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: CommandBarIOS: 6c8489472ed8f1f033d36b095b44f2227f9115ec -PODFILE CHECKSUM: 3a5c97c63efc3c50665cd2b1d284e459972dc9db +PODFILE CHECKSUM: 6d9bb10e6d829f27934a51717623c1fd87cac734 COCOAPODS: 1.14.2 diff --git a/Example/Pods/Manifest.lock b/Example/Pods/Manifest.lock index e6acd6f..96c4487 100644 --- a/Example/Pods/Manifest.lock +++ b/Example/Pods/Manifest.lock @@ -11,6 +11,6 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: CommandBarIOS: 6c8489472ed8f1f033d36b095b44f2227f9115ec -PODFILE CHECKSUM: 3a5c97c63efc3c50665cd2b1d284e459972dc9db +PODFILE CHECKSUM: 6d9bb10e6d829f27934a51717623c1fd87cac734 COCOAPODS: 1.14.2 diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 7331368..5faad8f 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -7,48 +7,50 @@ objects = { /* Begin PBXBuildFile section */ - 00E2CC219BEBC6DC29256888B38F07E6 /* CommandBarIOS-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 11EE91A1FAC8C396C5EA7BC74AD05C11 /* CommandBarIOS-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 0A9B46A4F191B43E0A39B981540C3F3A /* InternalSDK.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0083A0EA4E9796593507DE7A099FBA7 /* InternalSDK.swift */; }; + 0EEA9D74EB1C0F4363924586E74E3921 /* Analytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F78AA6E11324C035F3C1FB09D21932D /* Analytics.swift */; }; + 2558A22F47C94E0FC15DBA90E535989D /* Rules.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E31CC77A6CDC8607AB4E1FBDC9DACE /* Rules.swift */; }; 271D9ACDEFF8DA9BE018220CA3EE381F /* Pods-CommandBarIOS_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 515BD9511ECA7252E62981CE3B475040 /* Pods-CommandBarIOS_Tests-dummy.m */; }; - 2EEE674D86C4A7F9C9D4EC90AAF30C62 /* Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52730176054C2A7716CA5179AE8264D0 /* Config.swift */; }; - 3180E1E519D1FD5B17426B439FEB5CF8 /* Video.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D8FAF6C3B2DA50D43148D759AEAEDBD /* Video.swift */; }; - 31F3019579FBB577A3ADADB7AF988E3B /* NudgeWindowManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC43501B1F359FAC7E98B5FC3A8740AC /* NudgeWindowManager.swift */; }; - 35606D6D05D456D47CBA097A57CBDEF8 /* SDK.swift in Sources */ = {isa = PBXBuildFile; fileRef = 293EB5ED7F7D2D8F68953B4FBE2ECF98 /* SDK.swift */; }; + 29E690C12E0440121F7656316CED778E /* SurveyRatingBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95431D89A687B3AE01BFC4F3B8033A84 /* SurveyRatingBlock.swift */; }; + 310BB6DDA0FFC640CAA4194117929186 /* CloseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B6229C7A0C408120570A27093162D37 /* CloseButton.swift */; }; + 363CFF288B0710A39477A600003BCC7E /* InternalSDK.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B349C7D66536CF7E1898EED21F24803 /* InternalSDK.swift */; }; 375A3570C873DC3BB5E444CC77533135 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; }; - 3833087BFB99FD46CA6947066BAB603D /* HelpHubWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD34A36DCAC1589099AC02BC46992CA6 /* HelpHubWebView.swift */; }; - 38EFF840EBC2ADC63CFED092C859821E /* Util.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCD3B9C4CA93C81305DDE05A838B874B /* Util.swift */; }; - 48B0C759056F3D5FA7E862B0A66B0801 /* Nudges.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C6EC731F4C20D3D46ED80208657599 /* Nudges.swift */; }; - 5D2F1533AB5ECCC0112D763824F041C8 /* HelpHubViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 479BEC531929D0D199418B6DFF67089E /* HelpHubViewController.swift */; }; + 3FC779F3D00883EF7C678ECF7BC2961C /* Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD0E5DA0C889B73D5C26A14CFD6C02D4 /* Config.swift */; }; + 4270250030C10424F5743C4F6D5D9CE2 /* CommandBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5EC8B65A81141F645EB7908FEE6E201F /* CommandBar.swift */; }; + 45215FB740DE6CB12F2A43CF64337E76 /* NudgeWindowManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CEBC9E66B038D4BDEF0457C5100D1A2 /* NudgeWindowManager.swift */; }; + 489C4865FD8FEF1E835ABE205BAB7E5E /* CommandBarIOS-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 0A107A2CB88EE02D3A7C29FD6B20AF41 /* CommandBarIOS-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 52D898099DD9C7C999BD3FBA44446BBD /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12B0DAE275088FAAE65F1AED0F540DC7 /* Color.swift */; }; 5E33BB68E15225681C221A7BCE83EF73 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; }; - 6B9B3D6E341C2FFCC7E9315AAB8C0551 /* Actions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A3C60D0B1CA36E7D3CF5F0F47245B49 /* Actions.swift */; }; - 748A2798A70ADA05C9BF8AE50F532745 /* CloseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DC00805C3903A9D5AE74C4BCA85CC0C /* CloseButton.swift */; }; - 83E83E0B944748DCA5E763BAB405FF02 /* NudgeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FFE22C182ABA4EB85DF581F0EE91370 /* NudgeView.swift */; }; - 96481D91A9F90C26C5C0D12F905F88E6 /* BottomSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B3AB1F909D1F5632A43F7E08F15459B /* BottomSheet.swift */; }; - 9B80E35836202E1D86A21AC15EAFC697 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4FB7C20B6741AFC889871F064270D7F /* Button.swift */; }; - A0463F5C7E630EAB65F42F63C2593899 /* Analytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 902869DFB6A35F06A25C08CB5CBEF140 /* Analytics.swift */; }; + 7858489A8AE99870C47F982E1139AE03 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = B90AB9501F6AACF424A013E505D08D33 /* Button.swift */; }; + 7C87871B1AF530BD40CFF40191C09C38 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 87343D0EEF929A8DB14EC1B063F86FE6 /* Images.xcassets */; }; + 828569FE1DBFD7405B017B5F8706AA24 /* HelpHubWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4062C79CC3ADE643DB28775FFCD13A58 /* HelpHubWebView.swift */; }; + 87A796FDCB4FF5509523673FCCA2F29C /* NudgeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 006EEE49BCB7DC3913B294717351AD07 /* NudgeView.swift */; }; + 9AA29F9FC10A356A1B5DADDF6B7331DE /* SDK.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC5AD508189E7828E62FDAC8528B6CE /* SDK.swift */; }; + 9E5FD5EAB70C5CDD9FEFE775116D7801 /* Nudges.swift in Sources */ = {isa = PBXBuildFile; fileRef = 369830509485106AF21471517DCD739C /* Nudges.swift */; }; + BA3A3E26036B0751ED3AA401F1FFD30B /* BottomSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F4428EC251715085EE078B44D8E3E7 /* BottomSheet.swift */; }; + BDEB8179C2E910AEF7DC3EBD3CD87616 /* Actions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8987A95212896656A03FA644E285C73D /* Actions.swift */; }; + CAF28B291579F05247B26ADDEF189F73 /* Video.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5949EC9255721E489559DFD43EB8FA2B /* Video.swift */; }; CB7D63194963AD3D7DCF1C50EC3A89DD /* Pods-CommandBarIOS_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E43CB0041A0E679ADCCC403A77DC49B /* Pods-CommandBarIOS_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D2865D0250E089603BECDFBB98E344DC /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = D457C40F4995C434948E08D2DCA43E5B /* Image.swift */; }; - D53B906D01C1E92AFF84B638C920ED33 /* CommandBarIOS-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A7AC95392781CAB963555DDED672495 /* CommandBarIOS-dummy.m */; }; - D8AAFECEB06CCCF715E02B14397D4061 /* CommandBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A500F2F4B16F59018A4E61A6273B9FE /* CommandBar.swift */; }; - DA41F620773154E997CBDEA169061241 /* ButtonGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648ADB053A0EA9735EB406521AA364D6 /* ButtonGroup.swift */; }; - DC717E3BBFBF6847C426F0742B0C9926 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; }; + CC23426C17360BB1849C100B437B4914 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; }; + CDA7BCAE089294C1A41B928C49F94C7C /* HelpHubViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D70367BF4EE0E9B321E760ED754A7021 /* HelpHubViewController.swift */; }; + CF485AFA4F6C289925875A0AAD1D5E7D /* Spinner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B21C1D7EAB3E4756229E75A4345812F /* Spinner.swift */; }; + D70E86B390E8DC47AC3C7B9949160FAE /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80A5E092FC5CA7BA7CFBC893706B9429 /* Image.swift */; }; DE8966D9DDC32BD5E1F32594D92F0B3B /* Pods-CommandBarIOS_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = AFFE2B6A0D4157DAE9916DDB711EDDB5 /* Pods-CommandBarIOS_Example-dummy.m */; }; - E14C453232EED132EE4359A569477F2E /* Rules.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5FBBBDEC376DB9C4128C389BB9340E2 /* Rules.swift */; }; + E421629DB6F15F755EE5D3C1D6C319BA /* CommandBarIOS-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9544B201AE62043CC6385614054D5CFC /* CommandBarIOS-dummy.m */; }; EBD4CDE6E5BC08A713742DA9B53A5BD6 /* Pods-CommandBarIOS_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 0335B849997FEDD72AD0635B88000E91 /* Pods-CommandBarIOS_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EE904484D7F9038286114D7113DCE04C /* ContentBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 185CBE78E3E3098663C2DB77FBC8CF54 /* ContentBlock.swift */; }; - F6ACE7022EF2AA85DB596E254BB31E97 /* SurveyRatingBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3438183E813E7BDD5B865CC372BA9FA /* SurveyRatingBlock.swift */; }; - FD100868498C918DA13D4F62E91FD27E /* Spinner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BC17810486DBB3FE3529A627384C90C /* Spinner.swift */; }; + ED8698162788E934CA60C0B19E40D6A9 /* Util.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DD3225B911C8B5156F98066215B3048 /* Util.swift */; }; + FA072BBB5A2EF522EA12BE49A7480A79 /* ButtonGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 296170C385E074CF91034815EC9D6B06 /* ButtonGroup.swift */; }; + FE4DF7CF9FECA50A5E0AFF8C5918B8C8 /* ContentBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDE9C65A3FACA596D7E4EF08B6A20335 /* ContentBlock.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 3D8F3E2F3839ABFA774EF36F15AC81D0 /* PBXContainerItemProxy */ = { + 1232CA79748B9CF6BFB5A77FD2348F4F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; remoteGlobalIDString = BEF9C21ABF8843AD6FC046F2A58B2B1D; remoteInfo = "Pods-CommandBarIOS_Example"; }; - 732A5AE8E3675E2B43784D86F914A540 /* PBXContainerItemProxy */ = { + BF9EC3FBB97B361D3C61688831C084D5 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; @@ -58,61 +60,63 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 006EEE49BCB7DC3913B294717351AD07 /* NudgeView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NudgeView.swift; sourceTree = ""; }; 0335B849997FEDD72AD0635B88000E91 /* Pods-CommandBarIOS_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-CommandBarIOS_Example-umbrella.h"; sourceTree = ""; }; 05463FACEB0440DF91273FE265F92F67 /* Pods-CommandBarIOS_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-CommandBarIOS_Tests.modulemap"; sourceTree = ""; }; 0560156DCF68BC126399FC40E13C8CCF /* Pods-CommandBarIOS_Example */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-CommandBarIOS_Example"; path = Pods_CommandBarIOS_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 0602D83F2A5B774AF60B67B9144875A2 /* CommandBarIOS.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = CommandBarIOS.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 0A107A2CB88EE02D3A7C29FD6B20AF41 /* CommandBarIOS-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "CommandBarIOS-umbrella.h"; sourceTree = ""; }; 10633049ABF6884985AD82B2E6D4B49F /* Pods-CommandBarIOS_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-CommandBarIOS_Example-frameworks.sh"; sourceTree = ""; }; - 11EE91A1FAC8C396C5EA7BC74AD05C11 /* CommandBarIOS-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "CommandBarIOS-umbrella.h"; sourceTree = ""; }; - 185CBE78E3E3098663C2DB77FBC8CF54 /* ContentBlock.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ContentBlock.swift; sourceTree = ""; }; - 1D8FAF6C3B2DA50D43148D759AEAEDBD /* Video.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Video.swift; sourceTree = ""; }; - 1FFE22C182ABA4EB85DF581F0EE91370 /* NudgeView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NudgeView.swift; sourceTree = ""; }; + 12B0DAE275088FAAE65F1AED0F540DC7 /* Color.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = ""; }; + 1B6229C7A0C408120570A27093162D37 /* CloseButton.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CloseButton.swift; sourceTree = ""; }; + 1CEBC9E66B038D4BDEF0457C5100D1A2 /* NudgeWindowManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NudgeWindowManager.swift; sourceTree = ""; }; 24C3F0AC5FD53EE187421A98F864CD9A /* CommandBarIOS */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = CommandBarIOS; path = CommandBarIOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 293EB5ED7F7D2D8F68953B4FBE2ECF98 /* SDK.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SDK.swift; sourceTree = ""; }; - 2A3C60D0B1CA36E7D3CF5F0F47245B49 /* Actions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Actions.swift; sourceTree = ""; }; + 296170C385E074CF91034815EC9D6B06 /* ButtonGroup.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ButtonGroup.swift; sourceTree = ""; }; 2BC933536484A6A526982634D8F81096 /* Pods-CommandBarIOS_Example-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-CommandBarIOS_Example-Info.plist"; sourceTree = ""; }; + 2C8E8007F3CC350015934A41AC689667 /* CommandBarIOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = CommandBarIOS.debug.xcconfig; sourceTree = ""; }; + 2DD3225B911C8B5156F98066215B3048 /* Util.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Util.swift; sourceTree = ""; }; 34834821C4E0424E5D67E57EE20156F7 /* Pods-CommandBarIOS_Tests */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-CommandBarIOS_Tests"; path = Pods_CommandBarIOS_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 369830509485106AF21471517DCD739C /* Nudges.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Nudges.swift; sourceTree = ""; }; 3CE81AB79FEBAB0C8FC662A559E23A3E /* Pods-CommandBarIOS_Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-CommandBarIOS_Tests-acknowledgements.markdown"; sourceTree = ""; }; - 3DC00805C3903A9D5AE74C4BCA85CC0C /* CloseButton.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CloseButton.swift; sourceTree = ""; }; - 479BEC531929D0D199418B6DFF67089E /* HelpHubViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HelpHubViewController.swift; sourceTree = ""; }; + 3F78AA6E11324C035F3C1FB09D21932D /* Analytics.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Analytics.swift; sourceTree = ""; }; + 4062C79CC3ADE643DB28775FFCD13A58 /* HelpHubWebView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HelpHubWebView.swift; sourceTree = ""; }; 4DF207E3341C6E9BE8D8E7EF8A73A7C5 /* Pods-CommandBarIOS_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-CommandBarIOS_Example-acknowledgements.markdown"; sourceTree = ""; }; 515BD9511ECA7252E62981CE3B475040 /* Pods-CommandBarIOS_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-CommandBarIOS_Tests-dummy.m"; sourceTree = ""; }; - 522CD18E7A86C97CA12945953FC5EF84 /* CommandBarIOS.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = CommandBarIOS.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 52730176054C2A7716CA5179AE8264D0 /* Config.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Config.swift; sourceTree = ""; }; - 5A7AC95392781CAB963555DDED672495 /* CommandBarIOS-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "CommandBarIOS-dummy.m"; sourceTree = ""; }; + 51F4428EC251715085EE078B44D8E3E7 /* BottomSheet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BottomSheet.swift; sourceTree = ""; }; + 5949EC9255721E489559DFD43EB8FA2B /* Video.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Video.swift; sourceTree = ""; }; + 5B349C7D66536CF7E1898EED21F24803 /* InternalSDK.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = InternalSDK.swift; sourceTree = ""; }; 5C3927EA1AE23CAE7644367F26683AAE /* Pods-CommandBarIOS_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-CommandBarIOS_Example-acknowledgements.plist"; sourceTree = ""; }; - 648ADB053A0EA9735EB406521AA364D6 /* ButtonGroup.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ButtonGroup.swift; sourceTree = ""; }; - 69B1D6DE8845D112FA0D4FCF17D7A954 /* CommandBarIOS-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "CommandBarIOS-prefix.pch"; sourceTree = ""; }; - 69FF3D3D1EBB63D6F42E401FE2C3414C /* CommandBar.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = CommandBar.png; path = docs/img/CommandBar.png; sourceTree = ""; }; - 6A500F2F4B16F59018A4E61A6273B9FE /* CommandBar.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CommandBar.swift; sourceTree = ""; }; - 703CE9475B3E0AE6A5C2DBFCF4AA9855 /* CommandBarIOS.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = CommandBarIOS.modulemap; sourceTree = ""; }; + 5EC8B65A81141F645EB7908FEE6E201F /* CommandBar.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CommandBar.swift; sourceTree = ""; }; + 64E31CC77A6CDC8607AB4E1FBDC9DACE /* Rules.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Rules.swift; sourceTree = ""; }; 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 755F5AE531BAFEDD3D888AA9686E758D /* CommandBar.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = CommandBar.png; path = docs/img/CommandBar.png; sourceTree = ""; }; + 80A5E092FC5CA7BA7CFBC893706B9429 /* Image.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Image.swift; sourceTree = ""; }; + 836E4FEC98C15BF31168508C56BE204A /* CommandBarIOS.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = CommandBarIOS.modulemap; sourceTree = ""; }; 842D42AB8A2A2ED88FF8117E26013859 /* Pods-CommandBarIOS_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-CommandBarIOS_Example.debug.xcconfig"; sourceTree = ""; }; - 8BC17810486DBB3FE3529A627384C90C /* Spinner.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Spinner.swift; sourceTree = ""; }; + 87343D0EEF929A8DB14EC1B063F86FE6 /* Images.xcassets */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Sources/CommandBarIOS/Resources/Images.xcassets; sourceTree = ""; }; + 8987A95212896656A03FA644E285C73D /* Actions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Actions.swift; sourceTree = ""; }; 8D6010A0F46B835115A6155B19217F7F /* Pods-CommandBarIOS_Tests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-CommandBarIOS_Tests-Info.plist"; sourceTree = ""; }; - 8E23E018260D9C7E8630F6B10DE124BA /* CommandBarIOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = CommandBarIOS.debug.xcconfig; sourceTree = ""; }; - 8FD17517097D70BA71CEA73DE26E66E9 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = ""; }; - 902869DFB6A35F06A25C08CB5CBEF140 /* Analytics.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Analytics.swift; sourceTree = ""; }; + 95431D89A687B3AE01BFC4F3B8033A84 /* SurveyRatingBlock.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SurveyRatingBlock.swift; sourceTree = ""; }; + 9544B201AE62043CC6385614054D5CFC /* CommandBarIOS-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "CommandBarIOS-dummy.m"; sourceTree = ""; }; 95CC59761A02B39CD10A5754E533418E /* Pods-CommandBarIOS_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-CommandBarIOS_Tests.debug.xcconfig"; sourceTree = ""; }; - 96C6EC731F4C20D3D46ED80208657599 /* Nudges.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Nudges.swift; sourceTree = ""; }; - 99DD131222A83C9FFC3C497324602F67 /* CommandBarIOS-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "CommandBarIOS-Info.plist"; sourceTree = ""; }; - 9B3AB1F909D1F5632A43F7E08F15459B /* BottomSheet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BottomSheet.swift; sourceTree = ""; }; + 9B21C1D7EAB3E4756229E75A4345812F /* Spinner.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Spinner.swift; sourceTree = ""; }; 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 9E43CB0041A0E679ADCCC403A77DC49B /* Pods-CommandBarIOS_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-CommandBarIOS_Tests-umbrella.h"; sourceTree = ""; }; 9E4E8584E88649AAFE86983BE725CD08 /* Pods-CommandBarIOS_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-CommandBarIOS_Tests-acknowledgements.plist"; sourceTree = ""; }; A1BFF639C3F37F0714D100DBBD4B2971 /* Pods-CommandBarIOS_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-CommandBarIOS_Example.modulemap"; sourceTree = ""; }; + A373FCBCFA059F6C3D77514C28BD14E9 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = ""; }; + AAC5AD508189E7828E62FDAC8528B6CE /* SDK.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SDK.swift; sourceTree = ""; }; AFFE2B6A0D4157DAE9916DDB711EDDB5 /* Pods-CommandBarIOS_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-CommandBarIOS_Example-dummy.m"; sourceTree = ""; }; B88F91FB460AFB11775FE964C05AB3CF /* Pods-CommandBarIOS_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-CommandBarIOS_Example.release.xcconfig"; sourceTree = ""; }; - BCD3B9C4CA93C81305DDE05A838B874B /* Util.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Util.swift; sourceTree = ""; }; - C0083A0EA4E9796593507DE7A099FBA7 /* InternalSDK.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = InternalSDK.swift; sourceTree = ""; }; - CD91A73B5330ABA6AF3FEE7C36AAB789 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = ""; }; - D457C40F4995C434948E08D2DCA43E5B /* Image.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Image.swift; sourceTree = ""; }; - D58FB4FC68BE017312FE119F90720A3C /* CommandBarIOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = CommandBarIOS.release.xcconfig; sourceTree = ""; }; - DD34A36DCAC1589099AC02BC46992CA6 /* HelpHubWebView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HelpHubWebView.swift; sourceTree = ""; }; - E3438183E813E7BDD5B865CC372BA9FA /* SurveyRatingBlock.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SurveyRatingBlock.swift; sourceTree = ""; }; - E4FB7C20B6741AFC889871F064270D7F /* Button.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = ""; }; - F5FBBBDEC376DB9C4128C389BB9340E2 /* Rules.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Rules.swift; sourceTree = ""; }; + B90AB9501F6AACF424A013E505D08D33 /* Button.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = ""; }; + C9EEE7EBCA220E432A4C282007BE9E0D /* CommandBarIOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = CommandBarIOS.release.xcconfig; sourceTree = ""; }; + D70367BF4EE0E9B321E760ED754A7021 /* HelpHubViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HelpHubViewController.swift; sourceTree = ""; }; + D7632EB7508EA0D68CBD84DD2B852BB8 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = ""; }; + DDE9C65A3FACA596D7E4EF08B6A20335 /* ContentBlock.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ContentBlock.swift; sourceTree = ""; }; + DEF3A91162B8325954F2B29D5884540C /* CommandBarIOS-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "CommandBarIOS-prefix.pch"; sourceTree = ""; }; FBA3F61958993B363D52C4934D7FF3B4 /* Pods-CommandBarIOS_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-CommandBarIOS_Tests.release.xcconfig"; sourceTree = ""; }; - FC43501B1F359FAC7E98B5FC3A8740AC /* NudgeWindowManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NudgeWindowManager.swift; sourceTree = ""; }; + FD0E5DA0C889B73D5C26A14CFD6C02D4 /* Config.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Config.swift; sourceTree = ""; }; + FEBFAF8A292C68FED3FC551559F12C54 /* CommandBarIOS-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "CommandBarIOS-Info.plist"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -124,11 +128,11 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 705AFF2412E21AA97E12E771B719A878 /* Frameworks */ = { + 5C14F7D168DB6A329DC2B0FC7C753B03 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - DC717E3BBFBF6847C426F0742B0C9926 /* Foundation.framework in Frameworks */, + CC23426C17360BB1849C100B437B4914 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -143,30 +147,53 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 1CC8612F0D36E13B5FBA6B88788AB7AC /* Types */ = { + 0450770A5684A155963DEAEB78281A3C /* Development Pods */ = { isa = PBXGroup; children = ( - 2A3C60D0B1CA36E7D3CF5F0F47245B49 /* Actions.swift */, - 52730176054C2A7716CA5179AE8264D0 /* Config.swift */, - 96C6EC731F4C20D3D46ED80208657599 /* Nudges.swift */, - F5FBBBDEC376DB9C4128C389BB9340E2 /* Rules.swift */, - BCD3B9C4CA93C81305DDE05A838B874B /* Util.swift */, + 07CD46F4AD748A24760C463176B39B28 /* CommandBarIOS */, ); - name = Types; - path = Sources/CommandBarIOS/Types; + name = "Development Pods"; sourceTree = ""; }; - 231073C669D13905ED8482CA027B8D25 /* Buttons */ = { + 07CD46F4AD748A24760C463176B39B28 /* CommandBarIOS */ = { isa = PBXGroup; children = ( - E4FB7C20B6741AFC889871F064270D7F /* Button.swift */, - 648ADB053A0EA9735EB406521AA364D6 /* ButtonGroup.swift */, - 3DC00805C3903A9D5AE74C4BCA85CC0C /* CloseButton.swift */, + 87343D0EEF929A8DB14EC1B063F86FE6 /* Images.xcassets */, + BD46014713C8E458FF6052D0096BDE21 /* CommandBar */, + E00BF7D518B78667665940DB7E0B1E63 /* Components */, + 730642F1262C80825A096C9116C4460F /* Helpers */, + C6A32BB345F9B1361400E732DF374072 /* HelpHub */, + FDD566C3D1A4AD2CE4ABF717400269EE /* Nudges */, + 4453F0EC5C02648F1D664B4A632C48DC /* Pod */, + F70D5B7D4B2D88C28F8F44B014ACC386 /* Support Files */, + C615D765F38EBF0DC418CBB97443CE04 /* Types */, + ); + name = CommandBarIOS; + path = ../..; + sourceTree = ""; + }; + 30FB0E68EABA289E18EB0E4FCAAC7B5C /* Buttons */ = { + isa = PBXGroup; + children = ( + B90AB9501F6AACF424A013E505D08D33 /* Button.swift */, + 296170C385E074CF91034815EC9D6B06 /* ButtonGroup.swift */, + 1B6229C7A0C408120570A27093162D37 /* CloseButton.swift */, ); name = Buttons; path = Buttons; sourceTree = ""; }; + 4453F0EC5C02648F1D664B4A632C48DC /* Pod */ = { + isa = PBXGroup; + children = ( + 755F5AE531BAFEDD3D888AA9686E758D /* CommandBar.png */, + 0602D83F2A5B774AF60B67B9144875A2 /* CommandBarIOS.podspec */, + A373FCBCFA059F6C3D77514C28BD14E9 /* LICENSE */, + D7632EB7508EA0D68CBD84DD2B852BB8 /* README.md */, + ); + name = Pod; + sourceTree = ""; + }; 537C51C83D7B3AFF6AC3238E0C1195AF /* Pods-CommandBarIOS_Example */ = { isa = PBXGroup; children = ( @@ -217,92 +244,75 @@ path = "Target Support Files/Pods-CommandBarIOS_Tests"; sourceTree = ""; }; - 69B5A878529C25DC68E3A661ABBA1AE4 /* CommandBarIOS */ = { + 730642F1262C80825A096C9116C4460F /* Helpers */ = { isa = PBXGroup; children = ( - 787259C7210A6E3E6438B48B47C28068 /* CommandBar */, - 7C48B38B1C8F3C46979226DAF73210F5 /* Components */, - 91E3263472165F62C513324730137F5A /* HelpHub */, - D5EC3D9221E6EB79FB5E56603AD4BA2E /* Nudges */, - 7889F9FF915E19471DC338FD61B739D6 /* Pod */, - D7D180E17BC31C9FE921834EF36C17BA /* Support Files */, - 1CC8612F0D36E13B5FBA6B88788AB7AC /* Types */, + 12B0DAE275088FAAE65F1AED0F540DC7 /* Color.swift */, ); - name = CommandBarIOS; - path = ../..; + name = Helpers; + path = Sources/CommandBarIOS/Helpers; sourceTree = ""; }; - 787259C7210A6E3E6438B48B47C28068 /* CommandBar */ = { + 8B33513770B852B27B488A85B3E1D2A1 /* Content */ = { isa = PBXGroup; children = ( - 902869DFB6A35F06A25C08CB5CBEF140 /* Analytics.swift */, - 6A500F2F4B16F59018A4E61A6273B9FE /* CommandBar.swift */, - C0083A0EA4E9796593507DE7A099FBA7 /* InternalSDK.swift */, - 293EB5ED7F7D2D8F68953B4FBE2ECF98 /* SDK.swift */, + DDE9C65A3FACA596D7E4EF08B6A20335 /* ContentBlock.swift */, + 95431D89A687B3AE01BFC4F3B8033A84 /* SurveyRatingBlock.swift */, ); - name = CommandBar; - path = Sources/CommandBarIOS/CommandBar; - sourceTree = ""; - }; - 7889F9FF915E19471DC338FD61B739D6 /* Pod */ = { - isa = PBXGroup; - children = ( - 69FF3D3D1EBB63D6F42E401FE2C3414C /* CommandBar.png */, - 522CD18E7A86C97CA12945953FC5EF84 /* CommandBarIOS.podspec */, - 8FD17517097D70BA71CEA73DE26E66E9 /* LICENSE */, - CD91A73B5330ABA6AF3FEE7C36AAB789 /* README.md */, - ); - name = Pod; + name = Content; + path = Content; sourceTree = ""; }; - 7C48B38B1C8F3C46979226DAF73210F5 /* Components */ = { + 939D723E41CDF8FE51E6A6A8595112F1 /* Products */ = { isa = PBXGroup; children = ( - 9B3AB1F909D1F5632A43F7E08F15459B /* BottomSheet.swift */, - D457C40F4995C434948E08D2DCA43E5B /* Image.swift */, - 8BC17810486DBB3FE3529A627384C90C /* Spinner.swift */, - 1D8FAF6C3B2DA50D43148D759AEAEDBD /* Video.swift */, - 231073C669D13905ED8482CA027B8D25 /* Buttons */, + 24C3F0AC5FD53EE187421A98F864CD9A /* CommandBarIOS */, + 0560156DCF68BC126399FC40E13C8CCF /* Pods-CommandBarIOS_Example */, + 34834821C4E0424E5D67E57EE20156F7 /* Pods-CommandBarIOS_Tests */, ); - name = Components; - path = Sources/CommandBarIOS/Components; + name = Products; sourceTree = ""; }; - 91E3263472165F62C513324730137F5A /* HelpHub */ = { + BD46014713C8E458FF6052D0096BDE21 /* CommandBar */ = { isa = PBXGroup; children = ( - 479BEC531929D0D199418B6DFF67089E /* HelpHubViewController.swift */, - DD34A36DCAC1589099AC02BC46992CA6 /* HelpHubWebView.swift */, + 3F78AA6E11324C035F3C1FB09D21932D /* Analytics.swift */, + 5EC8B65A81141F645EB7908FEE6E201F /* CommandBar.swift */, + 5B349C7D66536CF7E1898EED21F24803 /* InternalSDK.swift */, + AAC5AD508189E7828E62FDAC8528B6CE /* SDK.swift */, ); - name = HelpHub; - path = Sources/CommandBarIOS/HelpHub; + name = CommandBar; + path = Sources/CommandBarIOS/CommandBar; sourceTree = ""; }; - 939D723E41CDF8FE51E6A6A8595112F1 /* Products */ = { + C615D765F38EBF0DC418CBB97443CE04 /* Types */ = { isa = PBXGroup; children = ( - 24C3F0AC5FD53EE187421A98F864CD9A /* CommandBarIOS */, - 0560156DCF68BC126399FC40E13C8CCF /* Pods-CommandBarIOS_Example */, - 34834821C4E0424E5D67E57EE20156F7 /* Pods-CommandBarIOS_Tests */, + 8987A95212896656A03FA644E285C73D /* Actions.swift */, + FD0E5DA0C889B73D5C26A14CFD6C02D4 /* Config.swift */, + 369830509485106AF21471517DCD739C /* Nudges.swift */, + 64E31CC77A6CDC8607AB4E1FBDC9DACE /* Rules.swift */, + 2DD3225B911C8B5156F98066215B3048 /* Util.swift */, ); - name = Products; + name = Types; + path = Sources/CommandBarIOS/Types; sourceTree = ""; }; - ABB9E38466558B1379B660A5E6A9E108 /* Content */ = { + C6A32BB345F9B1361400E732DF374072 /* HelpHub */ = { isa = PBXGroup; children = ( - 185CBE78E3E3098663C2DB77FBC8CF54 /* ContentBlock.swift */, - E3438183E813E7BDD5B865CC372BA9FA /* SurveyRatingBlock.swift */, + D70367BF4EE0E9B321E760ED754A7021 /* HelpHubViewController.swift */, + 4062C79CC3ADE643DB28775FFCD13A58 /* HelpHubWebView.swift */, ); - name = Content; - path = Content; + name = HelpHub; + path = Sources/CommandBarIOS/HelpHub; sourceTree = ""; }; CF1408CF629C7361332E53B88F7BD30C = { isa = PBXGroup; children = ( 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, - E264804E7B4F2E48D4FE8C132BF9C7CB /* Development Pods */, + 0450770A5684A155963DEAEB78281A3C /* Development Pods */, D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */, 939D723E41CDF8FE51E6A6A8595112F1 /* Products */, 59EDB8EB103EA198433BB151018225CA /* Targets Support Files */, @@ -317,38 +327,43 @@ name = Frameworks; sourceTree = ""; }; - D5EC3D9221E6EB79FB5E56603AD4BA2E /* Nudges */ = { + E00BF7D518B78667665940DB7E0B1E63 /* Components */ = { isa = PBXGroup; children = ( - 1FFE22C182ABA4EB85DF581F0EE91370 /* NudgeView.swift */, - FC43501B1F359FAC7E98B5FC3A8740AC /* NudgeWindowManager.swift */, - ABB9E38466558B1379B660A5E6A9E108 /* Content */, + 51F4428EC251715085EE078B44D8E3E7 /* BottomSheet.swift */, + 80A5E092FC5CA7BA7CFBC893706B9429 /* Image.swift */, + 9B21C1D7EAB3E4756229E75A4345812F /* Spinner.swift */, + 5949EC9255721E489559DFD43EB8FA2B /* Video.swift */, + 30FB0E68EABA289E18EB0E4FCAAC7B5C /* Buttons */, ); - name = Nudges; - path = Sources/CommandBarIOS/Nudges; + name = Components; + path = Sources/CommandBarIOS/Components; sourceTree = ""; }; - D7D180E17BC31C9FE921834EF36C17BA /* Support Files */ = { + F70D5B7D4B2D88C28F8F44B014ACC386 /* Support Files */ = { isa = PBXGroup; children = ( - 703CE9475B3E0AE6A5C2DBFCF4AA9855 /* CommandBarIOS.modulemap */, - 5A7AC95392781CAB963555DDED672495 /* CommandBarIOS-dummy.m */, - 99DD131222A83C9FFC3C497324602F67 /* CommandBarIOS-Info.plist */, - 69B1D6DE8845D112FA0D4FCF17D7A954 /* CommandBarIOS-prefix.pch */, - 11EE91A1FAC8C396C5EA7BC74AD05C11 /* CommandBarIOS-umbrella.h */, - 8E23E018260D9C7E8630F6B10DE124BA /* CommandBarIOS.debug.xcconfig */, - D58FB4FC68BE017312FE119F90720A3C /* CommandBarIOS.release.xcconfig */, + 836E4FEC98C15BF31168508C56BE204A /* CommandBarIOS.modulemap */, + 9544B201AE62043CC6385614054D5CFC /* CommandBarIOS-dummy.m */, + FEBFAF8A292C68FED3FC551559F12C54 /* CommandBarIOS-Info.plist */, + DEF3A91162B8325954F2B29D5884540C /* CommandBarIOS-prefix.pch */, + 0A107A2CB88EE02D3A7C29FD6B20AF41 /* CommandBarIOS-umbrella.h */, + 2C8E8007F3CC350015934A41AC689667 /* CommandBarIOS.debug.xcconfig */, + C9EEE7EBCA220E432A4C282007BE9E0D /* CommandBarIOS.release.xcconfig */, ); name = "Support Files"; path = "Example/Pods/Target Support Files/CommandBarIOS"; sourceTree = ""; }; - E264804E7B4F2E48D4FE8C132BF9C7CB /* Development Pods */ = { + FDD566C3D1A4AD2CE4ABF717400269EE /* Nudges */ = { isa = PBXGroup; children = ( - 69B5A878529C25DC68E3A661ABBA1AE4 /* CommandBarIOS */, + 006EEE49BCB7DC3913B294717351AD07 /* NudgeView.swift */, + 1CEBC9E66B038D4BDEF0457C5100D1A2 /* NudgeWindowManager.swift */, + 8B33513770B852B27B488A85B3E1D2A1 /* Content */, ); - name = "Development Pods"; + name = Nudges; + path = Sources/CommandBarIOS/Nudges; sourceTree = ""; }; /* End PBXGroup section */ @@ -370,11 +385,11 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 98A9880AA4C5BFC7D0C582C88AA92793 /* Headers */ = { + 51DBBAE9ED6598B5F6FC83990E27992A /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 00E2CC219BEBC6DC29256888B38F07E6 /* CommandBarIOS-umbrella.h in Headers */, + 489C4865FD8FEF1E835ABE205BAB7E5E /* CommandBarIOS-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -383,12 +398,12 @@ /* Begin PBXNativeTarget section */ 1A5C426E3579F3BD712FDAB630F0FBA8 /* CommandBarIOS */ = { isa = PBXNativeTarget; - buildConfigurationList = 9FCBBE2B84C6E067FA9D2E4B9D42350A /* Build configuration list for PBXNativeTarget "CommandBarIOS" */; + buildConfigurationList = 8D9C39CCAB87D9C176BE9A04CF46CAB2 /* Build configuration list for PBXNativeTarget "CommandBarIOS" */; buildPhases = ( - 98A9880AA4C5BFC7D0C582C88AA92793 /* Headers */, - B239B1A382EDE7512EFC704D660E26C4 /* Sources */, - 705AFF2412E21AA97E12E771B719A878 /* Frameworks */, - ABAEAE81D2E37597F7900A467CE9CE6C /* Resources */, + 51DBBAE9ED6598B5F6FC83990E27992A /* Headers */, + 2160C1401EBBBDEB40C5422D06EE96A6 /* Sources */, + 5C14F7D168DB6A329DC2B0FC7C753B03 /* Frameworks */, + C44028E4F255A7F944327BD3AAEF0105 /* Resources */, ); buildRules = ( ); @@ -411,7 +426,7 @@ buildRules = ( ); dependencies = ( - C1E651CE0595A49A45F247C9A322B452 /* PBXTargetDependency */, + 54EEBABA1D1D31E80F87CEAD2CE2C014 /* PBXTargetDependency */, ); name = "Pods-CommandBarIOS_Tests"; productName = Pods_CommandBarIOS_Tests; @@ -430,7 +445,7 @@ buildRules = ( ); dependencies = ( - 1ED78B87388173278777876612BC685D /* PBXTargetDependency */, + 925297806CE80D4B9A9EE1893347AD23 /* PBXTargetDependency */, ); name = "Pods-CommandBarIOS_Example"; productName = Pods_CommandBarIOS_Example; @@ -474,90 +489,92 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - ABAEAE81D2E37597F7900A467CE9CE6C /* Resources */ = { + BED0F03111C88D077F5D74D3509870F4 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - BED0F03111C88D077F5D74D3509870F4 /* Resources */ = { + C44028E4F255A7F944327BD3AAEF0105 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 7C87871B1AF530BD40CFF40191C09C38 /* Images.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 6C3C43B1371FF1E486745C523ED029EC /* Sources */ = { + 2160C1401EBBBDEB40C5422D06EE96A6 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 271D9ACDEFF8DA9BE018220CA3EE381F /* Pods-CommandBarIOS_Tests-dummy.m in Sources */, + BDEB8179C2E910AEF7DC3EBD3CD87616 /* Actions.swift in Sources */, + 0EEA9D74EB1C0F4363924586E74E3921 /* Analytics.swift in Sources */, + BA3A3E26036B0751ED3AA401F1FFD30B /* BottomSheet.swift in Sources */, + 7858489A8AE99870C47F982E1139AE03 /* Button.swift in Sources */, + FA072BBB5A2EF522EA12BE49A7480A79 /* ButtonGroup.swift in Sources */, + 310BB6DDA0FFC640CAA4194117929186 /* CloseButton.swift in Sources */, + 52D898099DD9C7C999BD3FBA44446BBD /* Color.swift in Sources */, + 4270250030C10424F5743C4F6D5D9CE2 /* CommandBar.swift in Sources */, + E421629DB6F15F755EE5D3C1D6C319BA /* CommandBarIOS-dummy.m in Sources */, + 3FC779F3D00883EF7C678ECF7BC2961C /* Config.swift in Sources */, + FE4DF7CF9FECA50A5E0AFF8C5918B8C8 /* ContentBlock.swift in Sources */, + CDA7BCAE089294C1A41B928C49F94C7C /* HelpHubViewController.swift in Sources */, + 828569FE1DBFD7405B017B5F8706AA24 /* HelpHubWebView.swift in Sources */, + D70E86B390E8DC47AC3C7B9949160FAE /* Image.swift in Sources */, + 363CFF288B0710A39477A600003BCC7E /* InternalSDK.swift in Sources */, + 9E5FD5EAB70C5CDD9FEFE775116D7801 /* Nudges.swift in Sources */, + 87A796FDCB4FF5509523673FCCA2F29C /* NudgeView.swift in Sources */, + 45215FB740DE6CB12F2A43CF64337E76 /* NudgeWindowManager.swift in Sources */, + 2558A22F47C94E0FC15DBA90E535989D /* Rules.swift in Sources */, + 9AA29F9FC10A356A1B5DADDF6B7331DE /* SDK.swift in Sources */, + CF485AFA4F6C289925875A0AAD1D5E7D /* Spinner.swift in Sources */, + 29E690C12E0440121F7656316CED778E /* SurveyRatingBlock.swift in Sources */, + ED8698162788E934CA60C0B19E40D6A9 /* Util.swift in Sources */, + CAF28B291579F05247B26ADDEF189F73 /* Video.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 83F6C7BA6E37E2654199257FCE899208 /* Sources */ = { + 6C3C43B1371FF1E486745C523ED029EC /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - DE8966D9DDC32BD5E1F32594D92F0B3B /* Pods-CommandBarIOS_Example-dummy.m in Sources */, + 271D9ACDEFF8DA9BE018220CA3EE381F /* Pods-CommandBarIOS_Tests-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - B239B1A382EDE7512EFC704D660E26C4 /* Sources */ = { + 83F6C7BA6E37E2654199257FCE899208 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 6B9B3D6E341C2FFCC7E9315AAB8C0551 /* Actions.swift in Sources */, - A0463F5C7E630EAB65F42F63C2593899 /* Analytics.swift in Sources */, - 96481D91A9F90C26C5C0D12F905F88E6 /* BottomSheet.swift in Sources */, - 9B80E35836202E1D86A21AC15EAFC697 /* Button.swift in Sources */, - DA41F620773154E997CBDEA169061241 /* ButtonGroup.swift in Sources */, - 748A2798A70ADA05C9BF8AE50F532745 /* CloseButton.swift in Sources */, - D8AAFECEB06CCCF715E02B14397D4061 /* CommandBar.swift in Sources */, - D53B906D01C1E92AFF84B638C920ED33 /* CommandBarIOS-dummy.m in Sources */, - 2EEE674D86C4A7F9C9D4EC90AAF30C62 /* Config.swift in Sources */, - EE904484D7F9038286114D7113DCE04C /* ContentBlock.swift in Sources */, - 5D2F1533AB5ECCC0112D763824F041C8 /* HelpHubViewController.swift in Sources */, - 3833087BFB99FD46CA6947066BAB603D /* HelpHubWebView.swift in Sources */, - D2865D0250E089603BECDFBB98E344DC /* Image.swift in Sources */, - 0A9B46A4F191B43E0A39B981540C3F3A /* InternalSDK.swift in Sources */, - 48B0C759056F3D5FA7E862B0A66B0801 /* Nudges.swift in Sources */, - 83E83E0B944748DCA5E763BAB405FF02 /* NudgeView.swift in Sources */, - 31F3019579FBB577A3ADADB7AF988E3B /* NudgeWindowManager.swift in Sources */, - E14C453232EED132EE4359A569477F2E /* Rules.swift in Sources */, - 35606D6D05D456D47CBA097A57CBDEF8 /* SDK.swift in Sources */, - FD100868498C918DA13D4F62E91FD27E /* Spinner.swift in Sources */, - F6ACE7022EF2AA85DB596E254BB31E97 /* SurveyRatingBlock.swift in Sources */, - 38EFF840EBC2ADC63CFED092C859821E /* Util.swift in Sources */, - 3180E1E519D1FD5B17426B439FEB5CF8 /* Video.swift in Sources */, + DE8966D9DDC32BD5E1F32594D92F0B3B /* Pods-CommandBarIOS_Example-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 1ED78B87388173278777876612BC685D /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = CommandBarIOS; - target = 1A5C426E3579F3BD712FDAB630F0FBA8 /* CommandBarIOS */; - targetProxy = 732A5AE8E3675E2B43784D86F914A540 /* PBXContainerItemProxy */; - }; - C1E651CE0595A49A45F247C9A322B452 /* PBXTargetDependency */ = { + 54EEBABA1D1D31E80F87CEAD2CE2C014 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Pods-CommandBarIOS_Example"; target = BEF9C21ABF8843AD6FC046F2A58B2B1D /* Pods-CommandBarIOS_Example */; - targetProxy = 3D8F3E2F3839ABFA774EF36F15AC81D0 /* PBXContainerItemProxy */; + targetProxy = 1232CA79748B9CF6BFB5A77FD2348F4F /* PBXContainerItemProxy */; + }; + 925297806CE80D4B9A9EE1893347AD23 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = CommandBarIOS; + target = 1A5C426E3579F3BD712FDAB630F0FBA8 /* CommandBarIOS */; + targetProxy = BF9EC3FBB97B361D3C61688831C084D5 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 050033BD780CAF114A97B373137A8CCC /* Debug */ = { + 130859B9EA14964D816C0549DA291179 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 8E23E018260D9C7E8630F6B10DE124BA /* CommandBarIOS.debug.xcconfig */; + baseConfigurationReference = C9EEE7EBCA220E432A4C282007BE9E0D /* CommandBarIOS.release.xcconfig */; buildSettings = { CLANG_ENABLE_OBJC_WEAK = NO; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -585,14 +602,15 @@ SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Debug; + name = Release; }; - 0A85EA5B564EA9E575078568E11D7810 /* Release */ = { + 41C22AA2B6FF5FA2834A81E3AD216439 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = B88F91FB460AFB11775FE964C05AB3CF /* Pods-CommandBarIOS_Example.release.xcconfig */; + baseConfigurationReference = FBA3F61958993B363D52C4934D7FF3B4 /* Pods-CommandBarIOS_Tests.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CLANG_ENABLE_OBJC_WEAK = NO; @@ -604,16 +622,16 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-CommandBarIOS_Example/Pods-CommandBarIOS_Example-Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-CommandBarIOS_Tests/Pods-CommandBarIOS_Tests-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", ); MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-CommandBarIOS_Example/Pods-CommandBarIOS_Example.modulemap"; + MODULEMAP_FILE = "Target Support Files/Pods-CommandBarIOS_Tests/Pods-CommandBarIOS_Tests.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -628,9 +646,9 @@ }; name = Release; }; - 5C6E1FBCF29BC499580061DE50946CF2 /* Release */ = { + 43F27CB35D5565D2DDCB33618C89E1EF /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = FBA3F61958993B363D52C4934D7FF3B4 /* Pods-CommandBarIOS_Tests.release.xcconfig */; + baseConfigurationReference = 95CC59761A02B39CD10A5754E533418E /* Pods-CommandBarIOS_Tests.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CLANG_ENABLE_OBJC_WEAK = NO; @@ -644,7 +662,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "Target Support Files/Pods-CommandBarIOS_Tests/Pods-CommandBarIOS_Tests-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -660,13 +678,50 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 7EC7E594D5EB6228CE1F196B1C83F73F /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B88F91FB460AFB11775FE964C05AB3CF /* Pods-CommandBarIOS_Example.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-CommandBarIOS_Example/Pods-CommandBarIOS_Example-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-CommandBarIOS_Example/Pods-CommandBarIOS_Example.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; - 90D4D09BCB6A4660E43ACBE9ECB6FE9A /* Debug */ = { + 8DE5143C03248BB6CD542DE3963D6F3A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -719,7 +774,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -732,7 +787,7 @@ }; name = Debug; }; - 9553C89E183877A5CB2F3C6801BEC129 /* Release */ = { + 9E406C6AAF85E580207CD97B0044DEAB /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -782,7 +837,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -794,9 +849,9 @@ }; name = Release; }; - E2582BE33CECAF9A65C371B3E4F6224A /* Release */ = { + B515982921341965FCB5123AC6398A6A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D58FB4FC68BE017312FE119F90720A3C /* CommandBarIOS.release.xcconfig */; + baseConfigurationReference = 2C8E8007F3CC350015934A41AC689667 /* CommandBarIOS.debug.xcconfig */; buildSettings = { CLANG_ENABLE_OBJC_WEAK = NO; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -824,50 +879,12 @@ SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - F24DCCF7DEAD1CB8394E9ED4D19F9566 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 95CC59761A02B39CD10A5754E533418E /* Pods-CommandBarIOS_Tests.debug.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-CommandBarIOS_Tests/Pods-CommandBarIOS_Tests-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-CommandBarIOS_Tests/Pods-CommandBarIOS_Tests.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; - FD9EA87EDB1F8E8AC01AFA047AB51CDC /* Debug */ = { + FF39763F025F2AE03351DC56A0C387BE /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 842D42AB8A2A2ED88FF8117E26013859 /* Pods-CommandBarIOS_Example.debug.xcconfig */; buildSettings = { @@ -883,7 +900,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "Target Support Files/Pods-CommandBarIOS_Example/Pods-CommandBarIOS_Example-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -910,8 +927,8 @@ 1F2A00F7317381B3919D9459CBDCC0D8 /* Build configuration list for PBXNativeTarget "Pods-CommandBarIOS_Example" */ = { isa = XCConfigurationList; buildConfigurations = ( - FD9EA87EDB1F8E8AC01AFA047AB51CDC /* Debug */, - 0A85EA5B564EA9E575078568E11D7810 /* Release */, + FF39763F025F2AE03351DC56A0C387BE /* Debug */, + 7EC7E594D5EB6228CE1F196B1C83F73F /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -919,8 +936,8 @@ 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( - 90D4D09BCB6A4660E43ACBE9ECB6FE9A /* Debug */, - 9553C89E183877A5CB2F3C6801BEC129 /* Release */, + 8DE5143C03248BB6CD542DE3963D6F3A /* Debug */, + 9E406C6AAF85E580207CD97B0044DEAB /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -928,17 +945,17 @@ 502957DD10EE69D43E1C3A73BC787C4D /* Build configuration list for PBXNativeTarget "Pods-CommandBarIOS_Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( - F24DCCF7DEAD1CB8394E9ED4D19F9566 /* Debug */, - 5C6E1FBCF29BC499580061DE50946CF2 /* Release */, + 43F27CB35D5565D2DDCB33618C89E1EF /* Debug */, + 41C22AA2B6FF5FA2834A81E3AD216439 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 9FCBBE2B84C6E067FA9D2E4B9D42350A /* Build configuration list for PBXNativeTarget "CommandBarIOS" */ = { + 8D9C39CCAB87D9C176BE9A04CF46CAB2 /* Build configuration list for PBXNativeTarget "CommandBarIOS" */ = { isa = XCConfigurationList; buildConfigurations = ( - 050033BD780CAF114A97B373137A8CCC /* Debug */, - E2582BE33CECAF9A65C371B3E4F6224A /* Release */, + B515982921341965FCB5123AC6398A6A /* Debug */, + 130859B9EA14964D816C0549DA291179 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/README.md b/README.md index 50acd3b..f83c9c2 100644 --- a/README.md +++ b/README.md @@ -31,26 +31,27 @@ dependencies: [ ## Usage -### `CommandBar` +### `Nudges` -`init`: - -- `options` (required): An instance of the `CommandBarOptions` class that holds the options for the `HelpHubWebView``. - - `orgId` (required): Your Organization ID from [CommandBar](https://app.commandbar.com) - - `spinnerColor` (optional): Optionally specify a color to render the loading Spinner +``` +// 1. Import CommandBar SDK +import CommandBarIOS -`openHelpHub()`: Opens HelpHubWebView in a BottomSheet modal +class AppDelegate: UIResponder, UIApplicationDelegate { -`onFallbackAction`: If you need to handle fallback actions from the HelpHub web view, you can conform to `HelpHubWebViewDelegate` protocol and implement the `didReceiveFallbackAction(_:)` method. The `CommandBar` class itself is already conforming to this protocol and forwarding the callback to its own delegate which you can set on your instance of `CommandBar` like `commandbar.delegate = self` + var window: UIWindow? -### `HelpHubWebView` + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + // 2. Boot CommandBar as early as possible in your app with your org ID from https://app.commandbar.com + CommandBarSDK.shared.boot("") + return true + } +} -`init`: Loads HelpHub in a WebView. The WebView won't load its content until options are set via `helpHubWebView.options = CommandBarOptions()` -- `options` (optional): An instance of the `CommandBarOptions` class that holds the options for the `HelpHubWebView``. - - `orgId` (required): Your Organization ID from [CommandBar](https://app.commandbar.com) - - `spinnerColor` (optional): Optionally specify a color to render the loading Spinner -- `onFallbackAction` (optional): A callback function to receive an event when a Fallback CTA is interacted with +// (Optional) 3. Emit events to trigger nudges +CommandBarSDK.shared.trackEvent("some_event_name") +``` ## Example diff --git a/Sources/CommandBarIOS/CommandBar/Analytics.swift b/Sources/CommandBarIOS/CommandBar/Analytics.swift index fbc53b8..816c3a4 100644 --- a/Sources/CommandBarIOS/CommandBar/Analytics.swift +++ b/Sources/CommandBarIOS/CommandBar/Analytics.swift @@ -100,16 +100,31 @@ enum UserType: String, Codable { case admin, likelyAdmin = "likely-admin", endUser = "end_user" } -struct SurveyResponseEvent : EventData { - var type: EventType = .surveyResponse - let response: ResponseEvent - let nudge: Nudge - let status: Status +struct FormFactorConfig: Codable { + var type = "modal" +} + + +struct NudgeEvent: Codable { + struct NudgeStepEvent : Codable { + var id: String + var title: String + } + + var id: String + var trigger: PushTrigger + var template_source:String + var slug: String + var frequency_limit: String = "no_limit" + var step:NudgeStepEvent + var status: Status } struct EventAttributes: Codable { var type: AnalyticsType - var response: SurveyResponseEvent? + var response: ResponseEvent? + var nudge: NudgeEvent? + var formFactor = "modal" } struct EventPayload: Codable { @@ -180,11 +195,10 @@ class Analytics { private var serverQueue: [EventPayload] = [] - func log(eventName: EventName, data: EventData) { + func log(eventName: EventName, data: EventAttributes) { switch(eventName) { case .surveyResponse: - guard let data = data as? SurveyResponseEvent else {return } - self.addEventToServerQueue(type: .log, name: eventName, attrs: EventAttributes(type: .log, response: data)) + self.addEventToServerQueue(type: .log, name: eventName, attrs: data) // Always flush until full analytics is built out self.flushServerQueue() } @@ -236,8 +250,8 @@ class Analytics { search: nil, reportToSegment: false, fingerprint: nil, - clientEventTimestamp: "", - clientFlushedTimestamp: nil + clientEventTimestamp: Date().getCurrentTimeStamp(), + clientFlushedTimestamp: Date().getCurrentTimeStamp() ) return payload @@ -247,4 +261,14 @@ class Analytics { let enrichedEvent = self.enrichEvent(type: type, name: name, attrs: attrs); self.serverQueue.append(enrichedEvent); } + +} + +extension Date { + func getCurrentTimeStamp() -> String { + let formatter = DateFormatter() + formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSSS" + formatter.timeZone = TimeZone(abbreviation: "UTC") + return formatter.string(from: self) + } } diff --git a/Sources/CommandBarIOS/Components/Image.swift b/Sources/CommandBarIOS/Components/Image.swift index 6a6c82c..11bcb1d 100644 --- a/Sources/CommandBarIOS/Components/Image.swift +++ b/Sources/CommandBarIOS/Components/Image.swift @@ -22,7 +22,7 @@ struct AsyncImage: View { .aspectRatio(contentMode: .fit) } else { // Replace with whatever placeholder you want to use - Spinner().padding(.vertical) + ActivityIndicator(isAnimating: .constant(true)).padding(.vertical) } } } diff --git a/Sources/CommandBarIOS/Components/Spinner.swift b/Sources/CommandBarIOS/Components/Spinner.swift index 5d9deb2..26ffc1f 100644 --- a/Sources/CommandBarIOS/Components/Spinner.swift +++ b/Sources/CommandBarIOS/Components/Spinner.swift @@ -1,16 +1,15 @@ import SwiftUI -struct Spinner: View { - @State private var spinCircle = false - var body: some View { - Image(systemName: "circle.fill") - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: 60, height: 60) - .rotationEffect(.degrees(spinCircle ? 360 : 0)) - .animation(Animation.linear(duration: 2).repeatForever(autoreverses: false)) - .onAppear() { - self.spinCircle = true - } +struct ActivityIndicator: UIViewRepresentable { + + @Binding var isAnimating: Bool + var style: UIActivityIndicatorView.Style = .medium + + func makeUIView(context: UIViewRepresentableContext) -> UIActivityIndicatorView { + return UIActivityIndicatorView(style: style) + } + + func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext) { + isAnimating ? uiView.startAnimating() : uiView.stopAnimating() } } diff --git a/Sources/CommandBarIOS/Components/Video.swift b/Sources/CommandBarIOS/Components/Video.swift index c1f24a5..00bc16a 100644 --- a/Sources/CommandBarIOS/Components/Video.swift +++ b/Sources/CommandBarIOS/Components/Video.swift @@ -42,7 +42,7 @@ struct VideoPlayerView: View { var body: some View { ZStack { if videoLoader.loading { - Spinner() + ActivityIndicator(isAnimating: .constant(true)) } else { if #available(iOS 14.0, *) { VideoPlayer(player: player) diff --git a/Sources/CommandBarIOS/Helpers/Color.swift b/Sources/CommandBarIOS/Helpers/Color.swift new file mode 100644 index 0000000..403b941 --- /dev/null +++ b/Sources/CommandBarIOS/Helpers/Color.swift @@ -0,0 +1,99 @@ +import SwiftUI + +extension Color { + func uiColor() -> UIColor { + + if #available(iOS 14.0, *) { + return UIColor(self) + } + + let components = self.components() + return UIColor(red: components.r, green: components.g, blue: components.b, alpha: components.a) + } + + private func components() -> (r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat) { + + let scanner = Scanner(string: self.description.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)) + var hexNumber: UInt64 = 0 + var r: CGFloat = 0.0, g: CGFloat = 0.0, b: CGFloat = 0.0, a: CGFloat = 0.0 + + let result = scanner.scanHexInt64(&hexNumber) + if result { + r = CGFloat((hexNumber & 0xff000000) >> 24) / 255 + g = CGFloat((hexNumber & 0x00ff0000) >> 16) / 255 + b = CGFloat((hexNumber & 0x0000ff00) >> 8) / 255 + a = CGFloat(hexNumber & 0x000000ff) / 255 + } + return (r, g, b, a) + } + + static func random() -> Color { + let red = Double.random(in: 0..<1) + let green = Double.random(in: 0..<1) + let blue = Double.random(in: 0..<1) + return Color(red: red, green: green, blue: blue) + } + + init(uiColor: UIColor) { + self.init(red: Double(uiColor.components.red), + green: Double(uiColor.components.green), + blue: Double(uiColor.components.blue), + opacity: Double(uiColor.components.alpha)) + } + + func lighter(by percentage: CGFloat = 30.0) -> Color { + if let uiColor = self.uiColor().lighter(by: percentage) { + return Color(uiColor: uiColor) + } + return self + + } + + func darker(by percentage: CGFloat = 30.0) -> Color { + if let uiColor = self.uiColor().darker(by: percentage) { + return Color(uiColor: uiColor) + } + return self + + } + + func adjust(by percentage: CGFloat = 30.0) -> Color { + let components = self.components() + return Color(red: min(Double(components.r + percentage/100), 1.0), + green: min(Double(components.g + percentage/100), 1.0), + blue: min(Double(components.b + percentage/100), 1.0), + opacity: Double(components.a)) + } +} + + +extension UIColor { + var components: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) { + var red: CGFloat = 0 + var green: CGFloat = 0 + var blue: CGFloat = 0 + var alpha: CGFloat = 0 + getRed(&red, green: &green, blue: &blue, alpha: &alpha) + + return (red, green, blue, alpha) + } + func lighter(by percentage: CGFloat = 30.0) -> UIColor? { + return self.adjust(by: abs(percentage) ) + } + + func darker(by percentage: CGFloat = 30.0) -> UIColor? { + return self.adjust(by: -1 * abs(percentage) ) + } + + func adjust(by percentage: CGFloat = 30.0) -> UIColor? { + var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0 + if self.getRed(&red, green: &green, blue: &blue, alpha: &alpha) { + return UIColor(red: min(red + percentage/100, 1.0), + green: min(green + percentage/100, 1.0), + blue: min(blue + percentage/100, 1.0), + alpha: alpha) + } else { + return nil + } + } +} diff --git a/Sources/CommandBarIOS/Nudges/Content/SurveyRatingBlock.swift b/Sources/CommandBarIOS/Nudges/Content/SurveyRatingBlock.swift index 4c1e6d6..c1cd150 100644 --- a/Sources/CommandBarIOS/Nudges/Content/SurveyRatingBlock.swift +++ b/Sources/CommandBarIOS/Nudges/Content/SurveyRatingBlock.swift @@ -6,28 +6,40 @@ struct StarButtons: View { let action: () -> Void; let count: Int - + + let starColor: Color = Color(.sRGB, red: 66/255, green: 66/255, blue: 77/255, opacity: 0.24) + let activeStarColor: Color = Color(.sRGB, red: 221/255, green: 158/255, blue: 35/255, opacity: 1) let borderColor: Color = Color(.sRGB, red: 10/255, green: 10/255, blue: 15/255, opacity: 0.24) let backgroundColor: Color = Color.white let activeBorderColor: Color = Color(.sRGB, red: 255/255, green: 180/255, blue: 34/255) let activeBackgroundColor: Color = Color(.sRGB, red: 255/255, green: 242/255, blue: 217/255) var body: some View { - let stars = Array(repeating: "⭐", count: count) + let stars = Array(repeating: "", count: count) ButtonGroupView(variant: .inclusive, options: stars, selection: $selection) { option, isSelected in - // TODO: Replace with our star svg - Text(option) - .shadow(color: .init(.sRGB, red: 0, green: 0, blue: 0, opacity: isSelected ? 0.35 : 0), radius: 7, x: 0, y: 4) - .frame(maxWidth: .infinity) - .padding(.vertical, 8) - .background(isSelected ? activeBackgroundColor : backgroundColor) - .foregroundColor(.white) - .cornerRadius(4) - .overlay( - RoundedRectangle(cornerRadius: 4) - .stroke(isSelected ? activeBorderColor : borderColor, lineWidth: 1) - ) + ZStack { + Image(systemName: "star") + .resizable() + .scaledToFit() + .frame(width: 24, height: 24) + .foregroundColor(isSelected ? activeStarColor.darker(by: 20) : starColor) + .opacity(isSelected ? 1 : 0) + Image(systemName: isSelected ? "star.fill" : "star") + .resizable() + .scaledToFit() + .frame(width: isSelected ? 20 : 24, height: isSelected ? 20 : 24) // Original size + .foregroundColor(isSelected ? activeStarColor : starColor) + } + .frame(maxWidth: .infinity) + .padding(.vertical, 8) + .background(isSelected ? activeBackgroundColor : backgroundColor) + .foregroundColor(.white) + .cornerRadius(4) + .overlay( + RoundedRectangle(cornerRadius: 4) + .stroke(isSelected ? activeBorderColor : borderColor, lineWidth: 1) + ) } } } diff --git a/Sources/CommandBarIOS/Nudges/NudgeWindowManager.swift b/Sources/CommandBarIOS/Nudges/NudgeWindowManager.swift index 249a847..801ef34 100644 --- a/Sources/CommandBarIOS/Nudges/NudgeWindowManager.swift +++ b/Sources/CommandBarIOS/Nudges/NudgeWindowManager.swift @@ -69,6 +69,7 @@ class NudgeWindowManager { } return false }) { + self.currentStepIndex = 0 NudgeWindowManager.shared.showNudge(nudge) } else { return } case .stepBack(_): @@ -77,21 +78,23 @@ class NudgeWindowManager { NudgeWindowManager.shared.internalSDKDelegate?.didTriggerOpenChat(withType: openChatAction.meta.type) case .dismiss(_): NudgeWindowManager.shared.hideNudge() - NudgeWindowManager.shared.currentStepIndex = 0 case .goToNudgeStep(let nudgeStepAction): NudgeWindowManager.shared.goToNudgeStep(nudge, step: nudgeStepAction.value) case .none(_): - NudgeWindowManager.shared.goToNudgeStep(nudge) + NudgeWindowManager.shared.goToNudgeStep(nudge, step: self.currentStepIndex + 1) case .click(_): print("Unsupported") default: - NudgeWindowManager.shared.goToNudgeStep(nudge) + NudgeWindowManager.shared.goToNudgeStep(nudge, step: self.currentStepIndex + 1) } } } private func trackSurveyEvent(_ nudge: Nudge, _ step: NudgeStep, _ surveyValue: Int, _ surveyTextValue: String) { if let surveyContent = step.content.first(where: { return $0.type == .surveyRating || $0.type == .surveyText || $0.type == .surveyTextShort }) { + let nudgeStepEvent = NudgeEvent.NudgeStepEvent(id: String(step.id), title: step.title) + let nudgeEvent = NudgeEvent(id: nudge.id, trigger: nudge.trigger, template_source: nudge.template_source, slug: nudge.slug, step: nudgeStepEvent, status: .init(is_preview: false, is_live: true)) + switch(surveyContent.meta) { case .surveyRating(let meta): switch(meta.type) { @@ -99,55 +102,50 @@ class NudgeWindowManager { if let emojis = meta.emojis { let emoji = emojis[surveyValue] let responseEvent = NumberResponseEvent(value: surveyValue, max: meta.options ?? 0, emoji: emoji) - let eventData = SurveyResponseEvent(response: .number(responseEvent), nudge: nudge, status: .init(is_preview: false, is_live: true)) - Analytics.shared.log(eventName: .surveyResponse, data: eventData) + let attrs = EventAttributes(type: .log, response: .number(responseEvent), nudge: nudgeEvent) + Analytics.shared.log(eventName: .surveyResponse, data: attrs) } case "stars", "numbers": - let responseEvent = NumberResponseEvent(value: surveyValue, max: meta.options ?? 0, emoji: nil) - let eventData = SurveyResponseEvent(response: .number(responseEvent), nudge: nudge, status: .init(is_preview: false, is_live: true)) - Analytics.shared.log(eventName: .surveyResponse, data: eventData) + let responseEvent = StringResponseEvent(value: surveyTextValue) + let attrs = EventAttributes(type: .log, response: .string(responseEvent), nudge: nudgeEvent) + Analytics.shared.log(eventName: .surveyResponse, data: attrs) default: return } - case .surveyText(_): + case .surveyText(_), .surveyTextShort(_): let responseEvent = StringResponseEvent(value: surveyTextValue) - let eventData = SurveyResponseEvent(response: .string(responseEvent), nudge: nudge, status: .init(is_preview: false, is_live: true)) - Analytics.shared.log(eventName: .surveyResponse, data: eventData) + let attrs = EventAttributes(type: .log, response: .string(responseEvent), nudge: nudgeEvent) + Analytics.shared.log(eventName: .surveyResponse, data: attrs) default: return } } } - private func goToNudgeStep(_ nudge: Nudge, step: Int? = nil) { + private func goToNudgeStep(_ nudge: Nudge, step: Int) { DispatchQueue.main.async { NudgeWindowManager.shared.hideNudge() - if let stepIndex = step { - NudgeWindowManager.shared.hideNudge() - NudgeWindowManager.shared.currentStepIndex = stepIndex - NudgeWindowManager.shared.showNudge(nudge, step: stepIndex) - } else if self.currentStepIndex < nudge.steps.count { - NudgeWindowManager.shared.currentStepIndex += 1 - NudgeWindowManager.shared.showNudge(nudge) - } else { - NudgeWindowManager.shared.currentStepIndex = 0 - } + NudgeWindowManager.shared.currentStepIndex = step + NudgeWindowManager.shared.showNudge(nudge) } } - private func showNudge(_ nudge: Nudge, step: Int? = nil) { + private func showNudge(_ nudge: Nudge) { guard nudgeWindow == nil else { return } - guard currentStepIndex < nudge.steps.count else { return } - + guard NudgeWindowManager.shared.currentStepIndex < nudge.steps.count else { + NudgeWindowManager.shared.hideNudge() + NudgeWindowManager.shared.currentStepIndex = 0 + return + } - let currentStep = nudge.steps[step != nil ? step! : currentStepIndex] + let currentStep = nudge.steps[NudgeWindowManager.shared.currentStepIndex] NudgeWindowManager.shared.currentNudgeView = NudgeView( nudge: nudge, step: currentStep, - stepIndex: currentStepIndex, + stepIndex: NudgeWindowManager.shared.currentStepIndex, onCloseAction: { DispatchQueue.main.async { NudgeWindowManager.shared.hideNudge() @@ -180,6 +178,7 @@ class NudgeWindowManager { } private func hideNudge() { + NudgeWindowManager.shared.currentStepIndex = 0 if (nudgeWindow?.rootViewController) != nil { NudgeWindowManager.shared.nudgeWindow = nil NudgeWindowManager.shared.currentNudgeView = nil