diff --git a/examples/simple-chatbot/examples/ios/.gitignore b/examples/simple-chatbot/examples/ios/.gitignore new file mode 100644 index 000000000..f89982e48 --- /dev/null +++ b/examples/simple-chatbot/examples/ios/.gitignore @@ -0,0 +1,2 @@ +/SimpleChatbot.xcodeproj/xcuserdata/ +/SimpleChatbot.xcodeproj/project.xcworkspace/xcuserdata/ diff --git a/examples/simple-chatbot/examples/ios/README.md b/examples/simple-chatbot/examples/ios/README.md new file mode 100644 index 000000000..2568871f0 --- /dev/null +++ b/examples/simple-chatbot/examples/ios/README.md @@ -0,0 +1,18 @@ +# iOS implementation + +Basic implementation using the [Pipecat iOS SDK](https://docs.pipecat.ai/client/ios/introduction). + +## Prerequisites + +1. Run the bot server. See the [server README](../../README). +2. Install [Xcode 15](https://developer.apple.com/xcode/), and set up your device [to run your own applications](https://developer.apple.com/documentation/xcode/distributing-your-app-to-registered-devices). + +## Running locally + +1. Clone this repository locally. +2. Open the SimpleChatbot.xcodeproj in Xcode. +3. Tell Xcode to update its Package Dependencies by clicking File -> Packages -> Update to Latest Package Versions. +4. Build the project. +5. Run the project on your device. +6. Connect to the URL you are testing. + diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot.xcodeproj/project.pbxproj b/examples/simple-chatbot/examples/ios/SimpleChatbot.xcodeproj/project.pbxproj new file mode 100644 index 000000000..97b30d26f --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot.xcodeproj/project.pbxproj @@ -0,0 +1,704 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + 90031FA72C616EE700408370 /* SimpleChatbotApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90031FA62C616EE700408370 /* SimpleChatbotApp.swift */; }; + 90031FA92C616EE700408370 /* PreJoinView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90031FA82C616EE700408370 /* PreJoinView.swift */; }; + 90031FAB2C616EE800408370 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 90031FAA2C616EE800408370 /* Assets.xcassets */; }; + 90031FAE2C616EE800408370 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 90031FAD2C616EE800408370 /* Preview Assets.xcassets */; }; + 90031FB82C616EE900408370 /* SimpleChatbotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90031FB72C616EE900408370 /* SimpleChatbotTests.swift */; }; + 90031FC22C616EE900408370 /* SimpleChatbotUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90031FC12C616EE900408370 /* SimpleChatbotUITests.swift */; }; + 90031FC42C616EE900408370 /* SimpleChatbotUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90031FC32C616EE900408370 /* SimpleChatbotUITestsLaunchTests.swift */; }; + 90031FDC2C6D5DD700408370 /* ToastModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90031FDB2C6D5DD700408370 /* ToastModifier.swift */; }; + 90ABB98E2C735ED6000D9CC7 /* MeetingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90ABB98D2C735ED6000D9CC7 /* MeetingView.swift */; }; + 90ABB9902C736A8B000D9CC7 /* WaveformView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90ABB98F2C736A8B000D9CC7 /* WaveformView.swift */; }; + 90ABB9932C73820D000D9CC7 /* MicrophoneView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90ABB9922C73820D000D9CC7 /* MicrophoneView.swift */; }; + 90ABB9982C738356000D9CC7 /* CustomColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90ABB9972C738356000D9CC7 /* CustomColors.swift */; }; + 90ABB99A2C73A6A9000D9CC7 /* MockCallContainerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90ABB9992C73A6A9000D9CC7 /* MockCallContainerModel.swift */; }; + 90ABB99D2C73C2D1000D9CC7 /* CallContainerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90ABB99C2C73C2D1000D9CC7 /* CallContainerModel.swift */; }; + 90ABB9A32C74E1CE000D9CC7 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90ABB9A22C74E1CE000D9CC7 /* SettingsView.swift */; }; + 90ABB9A62C74EA8A000D9CC7 /* SettingsPreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90ABB9A52C74EA8A000D9CC7 /* SettingsPreference.swift */; }; + 90ABB9A82C74EAB1000D9CC7 /* SettingsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90ABB9A72C74EAB1000D9CC7 /* SettingsManager.swift */; }; + 90B6AB312D1359ED00DFF1D9 /* PipecatClientIOSDaily in Frameworks */ = {isa = PBXBuildFile; productRef = 90B6AB302D1359ED00DFF1D9 /* PipecatClientIOSDaily */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 90031FB42C616EE900408370 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 90031F9B2C616EE700408370 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 90031FA22C616EE700408370; + remoteInfo = SimpleChatbot; + }; + 90031FBE2C616EE900408370 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 90031F9B2C616EE700408370 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 90031FA22C616EE700408370; + remoteInfo = SimpleChatbot; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 90031FA32C616EE700408370 /* SimpleChatbot.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SimpleChatbot.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 90031FA62C616EE700408370 /* SimpleChatbotApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleChatbotApp.swift; sourceTree = ""; }; + 90031FA82C616EE700408370 /* PreJoinView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreJoinView.swift; sourceTree = ""; }; + 90031FAA2C616EE800408370 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 90031FAD2C616EE800408370 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 90031FB32C616EE900408370 /* SimpleChatbotTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SimpleChatbotTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 90031FB72C616EE900408370 /* SimpleChatbotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleChatbotTests.swift; sourceTree = ""; }; + 90031FBD2C616EE900408370 /* SimpleChatbotUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SimpleChatbotUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 90031FC12C616EE900408370 /* SimpleChatbotUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleChatbotUITests.swift; sourceTree = ""; }; + 90031FC32C616EE900408370 /* SimpleChatbotUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleChatbotUITestsLaunchTests.swift; sourceTree = ""; }; + 90031FD62C63FD6A00408370 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 90031FDB2C6D5DD700408370 /* ToastModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastModifier.swift; sourceTree = ""; }; + 90ABB98D2C735ED6000D9CC7 /* MeetingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeetingView.swift; sourceTree = ""; }; + 90ABB98F2C736A8B000D9CC7 /* WaveformView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaveformView.swift; sourceTree = ""; }; + 90ABB9922C73820D000D9CC7 /* MicrophoneView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MicrophoneView.swift; sourceTree = ""; }; + 90ABB9972C738356000D9CC7 /* CustomColors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomColors.swift; sourceTree = ""; }; + 90ABB9992C73A6A9000D9CC7 /* MockCallContainerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCallContainerModel.swift; sourceTree = ""; }; + 90ABB99C2C73C2D1000D9CC7 /* CallContainerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallContainerModel.swift; sourceTree = ""; }; + 90ABB9A22C74E1CE000D9CC7 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; }; + 90ABB9A52C74EA8A000D9CC7 /* SettingsPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsPreference.swift; sourceTree = ""; }; + 90ABB9A72C74EAB1000D9CC7 /* SettingsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsManager.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 90031FA02C616EE700408370 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 90B6AB312D1359ED00DFF1D9 /* PipecatClientIOSDaily in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 90031FB02C616EE900408370 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 90031FBA2C616EE900408370 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 90031F9A2C616EE700408370 = { + isa = PBXGroup; + children = ( + 90031FA52C616EE700408370 /* SimpleChatbot */, + 90031FB62C616EE900408370 /* SimpleChatbotTests */, + 90031FC02C616EE900408370 /* SimpleChatbotUITests */, + 90031FA42C616EE700408370 /* Products */, + ); + sourceTree = ""; + }; + 90031FA42C616EE700408370 /* Products */ = { + isa = PBXGroup; + children = ( + 90031FA32C616EE700408370 /* SimpleChatbot.app */, + 90031FB32C616EE900408370 /* SimpleChatbotTests.xctest */, + 90031FBD2C616EE900408370 /* SimpleChatbotUITests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 90031FA52C616EE700408370 /* SimpleChatbot */ = { + isa = PBXGroup; + children = ( + 90ABB99B2C73C2C5000D9CC7 /* model */, + 90031FDD2C6D61E000408370 /* views */, + 90031FD62C63FD6A00408370 /* Info.plist */, + 90031FA62C616EE700408370 /* SimpleChatbotApp.swift */, + 90031FAA2C616EE800408370 /* Assets.xcassets */, + 90031FAC2C616EE800408370 /* Preview Content */, + ); + path = SimpleChatbot; + sourceTree = ""; + }; + 90031FAC2C616EE800408370 /* Preview Content */ = { + isa = PBXGroup; + children = ( + 90031FAD2C616EE800408370 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + 90031FB62C616EE900408370 /* SimpleChatbotTests */ = { + isa = PBXGroup; + children = ( + 90031FB72C616EE900408370 /* SimpleChatbotTests.swift */, + ); + path = SimpleChatbotTests; + sourceTree = ""; + }; + 90031FC02C616EE900408370 /* SimpleChatbotUITests */ = { + isa = PBXGroup; + children = ( + 90031FC12C616EE900408370 /* SimpleChatbotUITests.swift */, + 90031FC32C616EE900408370 /* SimpleChatbotUITestsLaunchTests.swift */, + ); + path = SimpleChatbotUITests; + sourceTree = ""; + }; + 90031FDD2C6D61E000408370 /* views */ = { + isa = PBXGroup; + children = ( + 90ABB99E2C73C3A9000D9CC7 /* components */, + 90ABB9962C738346000D9CC7 /* extensions */, + 90ABB9A42C74EA52000D9CC7 /* settings */, + 90031FA82C616EE700408370 /* PreJoinView.swift */, + 90ABB98D2C735ED6000D9CC7 /* MeetingView.swift */, + ); + path = views; + sourceTree = ""; + }; + 90ABB9962C738346000D9CC7 /* extensions */ = { + isa = PBXGroup; + children = ( + 90ABB9972C738356000D9CC7 /* CustomColors.swift */, + ); + path = extensions; + sourceTree = ""; + }; + 90ABB99B2C73C2C5000D9CC7 /* model */ = { + isa = PBXGroup; + children = ( + 90ABB9992C73A6A9000D9CC7 /* MockCallContainerModel.swift */, + 90ABB99C2C73C2D1000D9CC7 /* CallContainerModel.swift */, + ); + path = model; + sourceTree = ""; + }; + 90ABB99E2C73C3A9000D9CC7 /* components */ = { + isa = PBXGroup; + children = ( + 90ABB98F2C736A8B000D9CC7 /* WaveformView.swift */, + 90ABB9922C73820D000D9CC7 /* MicrophoneView.swift */, + 90031FDB2C6D5DD700408370 /* ToastModifier.swift */, + ); + path = components; + sourceTree = ""; + }; + 90ABB9A42C74EA52000D9CC7 /* settings */ = { + isa = PBXGroup; + children = ( + 90ABB9A52C74EA8A000D9CC7 /* SettingsPreference.swift */, + 90ABB9A72C74EAB1000D9CC7 /* SettingsManager.swift */, + 90ABB9A22C74E1CE000D9CC7 /* SettingsView.swift */, + ); + path = settings; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 90031FA22C616EE700408370 /* SimpleChatbot */ = { + isa = PBXNativeTarget; + buildConfigurationList = 90031FC72C616EE900408370 /* Build configuration list for PBXNativeTarget "SimpleChatbot" */; + buildPhases = ( + 90031F9F2C616EE700408370 /* Sources */, + 90031FA02C616EE700408370 /* Frameworks */, + 90031FA12C616EE700408370 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SimpleChatbot; + packageProductDependencies = ( + 90B6AB302D1359ED00DFF1D9 /* PipecatClientIOSDaily */, + ); + productName = SimpleChatbot; + productReference = 90031FA32C616EE700408370 /* SimpleChatbot.app */; + productType = "com.apple.product-type.application"; + }; + 90031FB22C616EE900408370 /* SimpleChatbotTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 90031FCA2C616EE900408370 /* Build configuration list for PBXNativeTarget "SimpleChatbotTests" */; + buildPhases = ( + 90031FAF2C616EE900408370 /* Sources */, + 90031FB02C616EE900408370 /* Frameworks */, + 90031FB12C616EE900408370 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 90031FB52C616EE900408370 /* PBXTargetDependency */, + ); + name = SimpleChatbotTests; + productName = SimpleChatbotTests; + productReference = 90031FB32C616EE900408370 /* SimpleChatbotTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 90031FBC2C616EE900408370 /* SimpleChatbotUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 90031FCD2C616EE900408370 /* Build configuration list for PBXNativeTarget "SimpleChatbotUITests" */; + buildPhases = ( + 90031FB92C616EE900408370 /* Sources */, + 90031FBA2C616EE900408370 /* Frameworks */, + 90031FBB2C616EE900408370 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 90031FBF2C616EE900408370 /* PBXTargetDependency */, + ); + name = SimpleChatbotUITests; + productName = SimpleChatbotUITests; + productReference = 90031FBD2C616EE900408370 /* SimpleChatbotUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 90031F9B2C616EE700408370 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1540; + LastUpgradeCheck = 1540; + TargetAttributes = { + 90031FA22C616EE700408370 = { + CreatedOnToolsVersion = 15.4; + }; + 90031FB22C616EE900408370 = { + CreatedOnToolsVersion = 15.4; + TestTargetID = 90031FA22C616EE700408370; + }; + 90031FBC2C616EE900408370 = { + CreatedOnToolsVersion = 15.4; + TestTargetID = 90031FA22C616EE700408370; + }; + }; + }; + buildConfigurationList = 90031F9E2C616EE700408370 /* Build configuration list for PBXProject "SimpleChatbot" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 90031F9A2C616EE700408370; + packageReferences = ( + 90B6AB2F2D1359ED00DFF1D9 /* XCRemoteSwiftPackageReference "pipecat-client-ios-daily" */, + ); + productRefGroup = 90031FA42C616EE700408370 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 90031FA22C616EE700408370 /* SimpleChatbot */, + 90031FB22C616EE900408370 /* SimpleChatbotTests */, + 90031FBC2C616EE900408370 /* SimpleChatbotUITests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 90031FA12C616EE700408370 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 90031FAE2C616EE800408370 /* Preview Assets.xcassets in Resources */, + 90031FAB2C616EE800408370 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 90031FB12C616EE900408370 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 90031FBB2C616EE900408370 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 90031F9F2C616EE700408370 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 90ABB99D2C73C2D1000D9CC7 /* CallContainerModel.swift in Sources */, + 90ABB9A62C74EA8A000D9CC7 /* SettingsPreference.swift in Sources */, + 90ABB99A2C73A6A9000D9CC7 /* MockCallContainerModel.swift in Sources */, + 90031FA92C616EE700408370 /* PreJoinView.swift in Sources */, + 90ABB9982C738356000D9CC7 /* CustomColors.swift in Sources */, + 90ABB98E2C735ED6000D9CC7 /* MeetingView.swift in Sources */, + 90ABB9A32C74E1CE000D9CC7 /* SettingsView.swift in Sources */, + 90ABB9932C73820D000D9CC7 /* MicrophoneView.swift in Sources */, + 90ABB9A82C74EAB1000D9CC7 /* SettingsManager.swift in Sources */, + 90031FDC2C6D5DD700408370 /* ToastModifier.swift in Sources */, + 90031FA72C616EE700408370 /* SimpleChatbotApp.swift in Sources */, + 90ABB9902C736A8B000D9CC7 /* WaveformView.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 90031FAF2C616EE900408370 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 90031FB82C616EE900408370 /* SimpleChatbotTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 90031FB92C616EE900408370 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 90031FC42C616EE900408370 /* SimpleChatbotUITestsLaunchTests.swift in Sources */, + 90031FC22C616EE900408370 /* SimpleChatbotUITests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 90031FB52C616EE900408370 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 90031FA22C616EE700408370 /* SimpleChatbot */; + targetProxy = 90031FB42C616EE900408370 /* PBXContainerItemProxy */; + }; + 90031FBF2C616EE900408370 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 90031FA22C616EE700408370 /* SimpleChatbot */; + targetProxy = 90031FBE2C616EE900408370 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 90031FC52C616EE900408370 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.5; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 90031FC62C616EE900408370 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.5; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 90031FC82C616EE900408370 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"SimpleChatbot/Preview Content\""; + DEVELOPMENT_TEAM = EEBGKV9N3N; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = SimpleChatbot/Info.plist; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = co.daily.SimpleChatbot; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 90031FC92C616EE900408370 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"SimpleChatbot/Preview Content\""; + DEVELOPMENT_TEAM = EEBGKV9N3N; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = SimpleChatbot/Info.plist; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = co.daily.SimpleChatbot; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 90031FCB2C616EE900408370 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = EEBGKV9N3N; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.5; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = co.daily.SimpleChatbotTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SimpleChatbot.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/SimpleChatbot"; + }; + name = Debug; + }; + 90031FCC2C616EE900408370 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = EEBGKV9N3N; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.5; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = co.daily.SimpleChatbotTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SimpleChatbot.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/SimpleChatbot"; + }; + name = Release; + }; + 90031FCE2C616EE900408370 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = EEBGKV9N3N; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = co.daily.SimpleChatbotUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = SimpleChatbot; + }; + name = Debug; + }; + 90031FCF2C616EE900408370 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = EEBGKV9N3N; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = co.daily.SimpleChatbotUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = SimpleChatbot; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 90031F9E2C616EE700408370 /* Build configuration list for PBXProject "SimpleChatbot" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 90031FC52C616EE900408370 /* Debug */, + 90031FC62C616EE900408370 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 90031FC72C616EE900408370 /* Build configuration list for PBXNativeTarget "SimpleChatbot" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 90031FC82C616EE900408370 /* Debug */, + 90031FC92C616EE900408370 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 90031FCA2C616EE900408370 /* Build configuration list for PBXNativeTarget "SimpleChatbotTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 90031FCB2C616EE900408370 /* Debug */, + 90031FCC2C616EE900408370 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 90031FCD2C616EE900408370 /* Build configuration list for PBXNativeTarget "SimpleChatbotUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 90031FCE2C616EE900408370 /* Debug */, + 90031FCF2C616EE900408370 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 90B6AB2F2D1359ED00DFF1D9 /* XCRemoteSwiftPackageReference "pipecat-client-ios-daily" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/pipecat-ai/pipecat-client-ios-daily/"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 0.3.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 90B6AB302D1359ED00DFF1D9 /* PipecatClientIOSDaily */ = { + isa = XCSwiftPackageProductDependency; + package = 90B6AB2F2D1359ED00DFF1D9 /* XCRemoteSwiftPackageReference "pipecat-client-ios-daily" */; + productName = PipecatClientIOSDaily; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 90031F9B2C616EE700408370 /* Project object */; +} diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/examples/simple-chatbot/examples/ios/SimpleChatbot.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/examples/simple-chatbot/examples/ios/SimpleChatbot.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/examples/simple-chatbot/examples/ios/SimpleChatbot.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..08de0be8d --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded + + + diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/examples/simple-chatbot/examples/ios/SimpleChatbot.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 000000000..a80596523 --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,33 @@ +{ + "originHash" : "cc17f08b06def9570d775e9c6f7a8dc10d1588b98127e977c47d052abac659b7", + "pins" : [ + { + "identity" : "daily-client-ios", + "kind" : "remoteSourceControl", + "location" : "https://github.com/daily-co/daily-client-ios.git", + "state" : { + "revision" : "15804ce495780da3ec2d05ab99736315f7bfbd24", + "version" : "0.28.0" + } + }, + { + "identity" : "pipecat-client-ios", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pipecat-ai/pipecat-client-ios.git", + "state" : { + "revision" : "fd8418559b6f885af7662b78fabdb0e2f08fbb1a", + "version" : "0.3.0" + } + }, + { + "identity" : "pipecat-client-ios-daily", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pipecat-ai/pipecat-client-ios-daily/", + "state" : { + "revision" : "03e1d1da973fb1aab65ac0c8267664f334a74c50", + "version" : "0.3.0" + } + } + ], + "version" : 3 +} diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot.xcodeproj/xcshareddata/xcschemes/SimpleChatbot.xcscheme b/examples/simple-chatbot/examples/ios/SimpleChatbot.xcodeproj/xcshareddata/xcschemes/SimpleChatbot.xcscheme new file mode 100644 index 000000000..632ae199d --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot.xcodeproj/xcshareddata/xcschemes/SimpleChatbot.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/simple-chatbot/examples/ios/SimpleChatbot/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..44ac9cc28 --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,14 @@ +{ + "images" : [ + { + "filename" : "appstore.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot/Assets.xcassets/AppIcon.appiconset/appstore.png b/examples/simple-chatbot/examples/ios/SimpleChatbot/Assets.xcassets/AppIcon.appiconset/appstore.png new file mode 100644 index 000000000..e6e615ad2 Binary files /dev/null and b/examples/simple-chatbot/examples/ios/SimpleChatbot/Assets.xcassets/AppIcon.appiconset/appstore.png differ diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot/Assets.xcassets/Contents.json b/examples/simple-chatbot/examples/ios/SimpleChatbot/Assets.xcassets/Contents.json new file mode 100644 index 000000000..73c00596a --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot/Assets.xcassets/pipecat.imageset/Contents.json b/examples/simple-chatbot/examples/ios/SimpleChatbot/Assets.xcassets/pipecat.imageset/Contents.json new file mode 100644 index 000000000..6e1102089 --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot/Assets.xcassets/pipecat.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Square Black.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot/Assets.xcassets/pipecat.imageset/Square Black.svg b/examples/simple-chatbot/examples/ios/SimpleChatbot/Assets.xcassets/pipecat.imageset/Square Black.svg new file mode 100644 index 000000000..0db9a0f64 --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot/Assets.xcassets/pipecat.imageset/Square Black.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot/Info.plist b/examples/simple-chatbot/examples/ios/SimpleChatbot/Info.plist new file mode 100644 index 000000000..c5a7b5685 --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot/Info.plist @@ -0,0 +1,19 @@ + + + + + UIBackgroundModes + + voip + + NSCameraUsageDescription + Camera is necessary for transmitting video in a call + NSMicrophoneUsageDescription + Microphone is necessary for transmitting audio in a call + NSAppTransportSecurity + + NSAllowsLocalNetworking + + + + diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot/Preview Content/Preview Assets.xcassets/Contents.json b/examples/simple-chatbot/examples/ios/SimpleChatbot/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 000000000..73c00596a --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot/SimpleChatbotApp.swift b/examples/simple-chatbot/examples/ios/SimpleChatbot/SimpleChatbotApp.swift new file mode 100644 index 000000000..7b1e78703 --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot/SimpleChatbotApp.swift @@ -0,0 +1,18 @@ +import SwiftUI + +@main +struct SimpleChatbotApp: App { + + @StateObject var callContainerModel = CallContainerModel() + + var body: some Scene { + WindowGroup { + if (!callContainerModel.isInCall) { + PreJoinView().environmentObject(callContainerModel) + } else { + MeetingView().environmentObject(callContainerModel) + } + } + } + +} diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot/model/CallContainerModel.swift b/examples/simple-chatbot/examples/ios/SimpleChatbot/model/CallContainerModel.swift new file mode 100644 index 000000000..608cc3ff4 --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot/model/CallContainerModel.swift @@ -0,0 +1,181 @@ +import SwiftUI + +import RTVIClientIOSDaily +import RTVIClientIOS + +class CallContainerModel: ObservableObject { + + @Published var voiceClientStatus: String = TransportState.disconnected.description + @Published var isInCall: Bool = false + @Published var isBotReady: Bool = false + @Published var timerCount = 0 + + @Published var isMicEnabled: Bool = false + + @Published var toastMessage: String? = nil + @Published var showToast: Bool = false + + @Published + var remoteAudioLevel: Float = 0 + @Published + var localAudioLevel: Float = 0 + + private var meetingTimer: Timer? + + var rtviClientIOS: RTVIClient? + + init() { + // Changing the log level + RTVIClientIOS.setLogLevel(.warn) + } + + @MainActor + func connect(backendURL: String) { + let baseUrl = backendURL.trimmingCharacters(in: .whitespacesAndNewlines) + if(baseUrl.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty){ + self.showError(message: "Need to fill the backendURL. For more info visit: https://bots.daily.co") + return + } + + let currentSettings = SettingsManager.getSettings() + let rtviClientOptions = RTVIClientOptions.init( + enableMic: currentSettings.enableMic, + enableCam: false, + params: RTVIClientParams( + baseUrl: baseUrl, + endpoints: RTVIURLEndpoints(connect: "/connect") + ) + ) + self.rtviClientIOS = RTVIClient.init( + transport: DailyTransport.init(options: rtviClientOptions), + options: rtviClientOptions + ) + self.rtviClientIOS?.delegate = self + self.rtviClientIOS?.start() { result in + if case .failure(let error) = result { + self.showError(message: error.localizedDescription) + self.rtviClientIOS = nil + } + } + // Selecting the mic based on the preferences + if let selectedMic = currentSettings.selectedMic { + self.rtviClientIOS?.updateMic(micId: MediaDeviceId(id:selectedMic), completion: nil) + } + self.saveCredentials(backendURL: baseUrl) + } + + @MainActor + func disconnect() { + self.rtviClientIOS?.disconnect(completion: nil) + } + + func showError(message: String) { + self.toastMessage = message + self.showToast = true + // Hide the toast after 5 seconds + DispatchQueue.main.asyncAfter(deadline: .now() + 5) { + self.showToast = false + self.toastMessage = nil + } + } + + @MainActor + func toggleMicInput() { + self.rtviClientIOS?.enableMic(enable: !self.isMicEnabled) { result in + switch result { + case .success(): + self.isMicEnabled = self.rtviClientIOS?.isMicEnabled ?? false + case .failure(let error): + self.showError(message: error.localizedDescription) + } + } + } + + private func startTimer(withExpirationTime expirationTime: Int) { + let currentTime = Int(Date().timeIntervalSince1970) + self.timerCount = expirationTime - currentTime + self.meetingTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in + DispatchQueue.main.async { + self.timerCount -= 1 + } + } + } + + private func stopTimer() { + self.meetingTimer?.invalidate() + self.meetingTimer = nil + self.timerCount = 0 + } + + func saveCredentials(backendURL: String) { + var currentSettings = SettingsManager.getSettings() + currentSettings.backendURL = backendURL + // Saving the settings + SettingsManager.updateSettings(settings: currentSettings) + } + +} + +extension CallContainerModel:RTVIClientDelegate, LLMHelperDelegate { + + private func handleEvent(eventName: String, eventValue: Any? = nil) { + if let value = eventValue { + print("RTVI Demo, received event:\(eventName), value:\(value)") + } else { + print("RTVI Demo, received event: \(eventName)") + } + } + + func onTransportStateChanged(state: TransportState) { + self.handleEvent(eventName: "onTransportStateChanged", eventValue: state) + self.voiceClientStatus = state.description + self.isInCall = ( state == .connecting || state == .connected || state == .ready || state == .authenticating ) + } + + @MainActor + func onBotReady(botReadyData: BotReadyData) { + self.handleEvent(eventName: "onBotReady.") + self.isBotReady = true + if let expirationTime = self.rtviClientIOS?.expiry() { + self.startTimer(withExpirationTime: expirationTime) + } + } + + @MainActor + func onConnected() { + self.isMicEnabled = self.rtviClientIOS?.isMicEnabled ?? false + } + + func onDisconnected() { + self.stopTimer() + self.isBotReady = false + } + + func onRemoteAudioLevel(level: Float, participant: Participant) { + self.remoteAudioLevel = level + } + + func onUserAudioLevel(level: Float) { + self.localAudioLevel = level + } + + func onUserTranscript(data: Transcript) { + if (data.final ?? false) { + self.handleEvent(eventName: "onUserTranscript", eventValue: data.text) + } + } + + func onBotTranscript(data: String) { + self.handleEvent(eventName: "onBotTranscript", eventValue: data) + } + + func onError(message: String) { + self.handleEvent(eventName: "onError", eventValue: message) + self.showError(message: message) + } + + func onTracksUpdated(tracks: Tracks) { + self.handleEvent(eventName: "onTracksUpdated", eventValue: tracks) + } + +} diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot/model/MockCallContainerModel.swift b/examples/simple-chatbot/examples/ios/SimpleChatbot/model/MockCallContainerModel.swift new file mode 100644 index 000000000..c148f9a2c --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot/model/MockCallContainerModel.swift @@ -0,0 +1,35 @@ +import SwiftUI +import RTVIClientIOS + +class MockCallContainerModel: CallContainerModel { + + override init() { + } + + override func connect(backendURL: String) { + print("connect") + } + + override func disconnect() { + print("disconnect") + } + + override func showError(message: String) { + self.toastMessage = message + self.showToast = true + // Hide the toast after 5 seconds + DispatchQueue.main.asyncAfter(deadline: .now() + 5) { + self.showToast = false + self.toastMessage = nil + } + } + + func startAudioLevelSimulation() { + // Simulate audio level changes + Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { _ in + let newLevel = Float.random(in: 0...1) + self.remoteAudioLevel = newLevel + self.localAudioLevel = newLevel + } + } +} diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot/views/MeetingView.swift b/examples/simple-chatbot/examples/ios/SimpleChatbot/views/MeetingView.swift new file mode 100644 index 000000000..2bbc9673f --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot/views/MeetingView.swift @@ -0,0 +1,107 @@ +import SwiftUI + +struct MeetingView: View { + + @State private var showingSettings = false + @EnvironmentObject private var model: CallContainerModel + + var body: some View { + VStack { + // Header Toolbar + HStack { + Image("dailyBot") + .resizable() + .frame(width: 48, height: 48) + Spacer() + HStack { + Image(systemName: "stopwatch") + .resizable() + .frame(width: 24, height: 24) + Text(timerString(from: self.model.timerCount)) + .font(.headline) + }.padding() + .background(Color.timer) + .cornerRadius(12) + } + .padding() + + // Main Panel + VStack { + VStack { + WaveformView(audioLevel: model.remoteAudioLevel, isBotReady: model.isBotReady, voiceClientStatus: model.voiceClientStatus) + } + .frame(maxHeight: .infinity) + VStack { + HStack { + MicrophoneView(audioLevel: model.localAudioLevel, isMuted: !self.model.isMicEnabled) + .frame(width: 160, height: 160) + .onTapGesture { + self.model.toggleMicInput() + } + } + } + .frame(height: 120) + } + .frame(maxHeight: .infinity) + .padding() + + // Bottom Panel + VStack { + HStack { + Button(action: { + self.showingSettings = true + }) { + HStack { + Image(systemName: "gearshape") + .resizable() + .frame(width: 24, height: 24) + Text("Settings") + } + .frame(maxWidth: .infinity) + .padding() + .sheet(isPresented: $showingSettings) { + SettingsView(showingSettings: $showingSettings).environmentObject(self.model) + } + } + .border(Color.buttonsBorder, width: 1) + .cornerRadius(12) + } + .foregroundColor(.black) + .padding([.top, .horizontal]) + + Button(action: { + self.model.disconnect() + }) { + HStack { + Image(systemName: "rectangle.portrait.and.arrow.right") + .resizable() + .frame(width: 24, height: 24) + Text("End") + } + .frame(maxWidth: .infinity) + .padding() + } + .foregroundColor(.white) + .background(Color.black) + .cornerRadius(12) + .padding([.bottom, .horizontal]) + } + } + .background(Color.backgroundApp) + .toast(message: model.toastMessage, isShowing: model.showToast) + } + + func timerString(from count: Int) -> String { + let hours = count / 3600 + let minutes = (count % 3600) / 60 + let seconds = count % 60 + return String(format: "%02d:%02d:%02d", hours, minutes, seconds) + } +} + +#Preview { + let mockModel = MockCallContainerModel() + let result = MeetingView().environmentObject(mockModel as CallContainerModel) + mockModel.startAudioLevelSimulation() + return result +} diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot/views/PreJoinView.swift b/examples/simple-chatbot/examples/ios/SimpleChatbot/views/PreJoinView.swift new file mode 100644 index 000000000..fb2390817 --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot/views/PreJoinView.swift @@ -0,0 +1,42 @@ +import SwiftUI + +struct PreJoinView: View { + + @State var backendURL: String + + @EnvironmentObject private var model: CallContainerModel + + init() { + let currentSettings = SettingsManager.getSettings() + self.backendURL = currentSettings.backendURL + } + + var body: some View { + VStack(spacing: 20) { + Image("pipecat") + .resizable() + .frame(width: 80, height: 80) + Text("Pipecat Client iOS.") + .font(.headline) + TextField("Server URL", text: $backendURL) + .textFieldStyle(RoundedBorderTextFieldStyle()) + .frame(maxWidth: .infinity) + .padding([.bottom, .horizontal]) + Button("Connect") { + self.model.connect(backendURL: self.backendURL) + } + .padding() + .background(Color.black) + .foregroundColor(.white) + .cornerRadius(8) + } + .padding() + .frame(maxHeight: .infinity) + .background(Color.backgroundApp) + .toast(message: model.toastMessage, isShowing: model.showToast) + } +} + +#Preview { + PreJoinView().environmentObject(MockCallContainerModel() as CallContainerModel) +} diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot/views/components/DailyVideoView.swift b/examples/simple-chatbot/examples/ios/SimpleChatbot/views/components/DailyVideoView.swift new file mode 100644 index 000000000..64bfe0eca --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot/views/components/DailyVideoView.swift @@ -0,0 +1,69 @@ +import SwiftUI + +import Daily +import RTVIClientIOS +import RTVIClientIOSDaily + + +/// A wrapper for `VoiceClientVideoView` that exposes the video size via a `@Binding`. +struct DailyVideoView: UIViewRepresentable { + + /// The current size of the video being rendered by this view. + @Binding private(set) var videoSize: CGSize + + private let voiceClientTrack: MediaTrackId? + private let videoScaleMode: VoiceClientVideoView.VideoScaleMode + + init( + voiceClientTrack: MediaTrackId? = nil, + videoScaleMode: VoiceClientVideoView.VideoScaleMode = .fill, + videoSize: Binding = .constant(.zero) + ) { + self.voiceClientTrack = voiceClientTrack + self.videoScaleMode = videoScaleMode + self._videoSize = videoSize + } + + func makeUIView(context: Context) -> VoiceClientVideoView { + let videoView = VoiceClientVideoView() + videoView.delegate = context.coordinator + return videoView + } + + func updateUIView(_ videoView: VoiceClientVideoView, context: Context) { + context.coordinator.dailyVideoView = self + + if videoView.voiceClientTrack != voiceClientTrack { + videoView.voiceClientTrack = voiceClientTrack + } + + if videoView.videoScaleMode != videoScaleMode { + videoView.videoScaleMode = videoScaleMode + } + } +} + +extension DailyVideoView { + final class Coordinator: VideoViewDelegate { + fileprivate var dailyVideoView: DailyVideoView + + init(_ dailyVideoView: DailyVideoView) { + self.dailyVideoView = dailyVideoView + } + + func videoView(_ videoView: Daily.VideoView, didChangeVideoSize size: CGSize) { + // Update the `videoSize` binding with the current `size` value. + DispatchQueue.main.async { + self.dailyVideoView.videoSize = size + } + } + } + + func makeCoordinator() -> Coordinator { + Coordinator(self) + } +} + +#Preview { + VideoView() +} diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot/views/components/MicrophoneView.swift b/examples/simple-chatbot/examples/ios/SimpleChatbot/views/components/MicrophoneView.swift new file mode 100644 index 000000000..7cdaf1e80 --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot/views/components/MicrophoneView.swift @@ -0,0 +1,44 @@ +import SwiftUI + +struct MicrophoneView: View { + var audioLevel: Float // Current audio level + var isMuted: Bool // Muted state + + var body: some View { + GeometryReader { geometry in + let width = geometry.size.width + let circleSize = width * 0.9 + let innerCircleSize = width * 0.82 + let audioCircleSize = CGFloat(audioLevel) * (width * 0.95) + + ZStack { + Circle() + .stroke(Color.gray, lineWidth: 1) + .frame(width: circleSize) + + Circle() + .fill(isMuted ? Color.disabledMic : Color.backgroundCircle) + .frame(width: innerCircleSize) + + if !isMuted { + Circle() + .fill(Color.micVolume) + .opacity(0.5) + .frame(width: audioCircleSize) + .animation(.easeInOut(duration: 0.2), value: audioLevel) + } + + Image(systemName: isMuted ? "mic.slash.fill" : "mic.fill") + .resizable() + .scaledToFit() + .frame(width: width * 0.2) + .foregroundColor(.white) + } + .frame(maxWidth: .infinity, maxHeight: .infinity) // Ensures the ZStack is centered + } + } +} + +#Preview { + MicrophoneView(audioLevel: 1, isMuted: false) +} diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot/views/components/ToastModifier.swift b/examples/simple-chatbot/examples/ios/SimpleChatbot/views/components/ToastModifier.swift new file mode 100644 index 000000000..9e36125eb --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot/views/components/ToastModifier.swift @@ -0,0 +1,31 @@ +import SwiftUI + +struct ToastModifier: ViewModifier { + var message: String? + var isShowing: Bool + + func body(content: Content) -> some View { + ZStack { + content + if isShowing, let message = message { + VStack { + Text(message) + .padding() + .background(Color.black.opacity(0.7)) + .foregroundColor(.white) + .cornerRadius(8) + .transition(.slide) + .padding(.top, 50) + Spacer() + } + .animation(.easeInOut(duration: 0.5), value: isShowing) + } + } + } +} + +extension View { + func toast(message: String?, isShowing: Bool) -> some View { + self.modifier(ToastModifier(message: message, isShowing: isShowing)) + } +} diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot/views/components/WaveformView.swift b/examples/simple-chatbot/examples/ios/SimpleChatbot/views/components/WaveformView.swift new file mode 100644 index 000000000..f98d1cb86 --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot/views/components/WaveformView.swift @@ -0,0 +1,93 @@ +import SwiftUI + +struct WaveformView: View { + + var audioLevel: Float + var isBotReady: Bool + var voiceClientStatus: String + + @State + private var audioLevels: [Float] = Array(repeating: 0, count: 5) + private let dotCount = 5 + + var body: some View { + GeometryReader { geometry in + VStack { + Spacer() + HStack { + Spacer() + ZStack { + // Outer gray border + Circle() + .stroke(Color.gray, lineWidth: 1) + .frame(width: geometry.size.width * 0.9, height: geometry.size.width * 0.9) + + // Gray middle + Circle() + .fill(isBotReady ? Color.backgroundCircle : Color.backgroundCircleNotConnected) + .frame(width: geometry.size.width * 0.82, height: geometry.size.width * 0.82) + + if isBotReady { + if audioLevel > 0 { + // Waveform bars inside the circle + HStack(spacing: 10) { + ForEach(0.. 1) { + audioLevel = 1 + } + // Update the array and shift values + audioLevels.removeFirst() + audioLevels.append(newLevel) + } + } +} + +#Preview { + WaveformView(audioLevel: 0, isBotReady: false, voiceClientStatus: "idle") +} diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot/views/extensions/CustomColors.swift b/examples/simple-chatbot/examples/ios/SimpleChatbot/views/extensions/CustomColors.swift new file mode 100644 index 000000000..d200537d6 --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot/views/extensions/CustomColors.swift @@ -0,0 +1,27 @@ +import SwiftUI + +public extension Color { + + static let backgroundCircle = Color(hex: "#374151") + static let backgroundCircleNotConnected = Color(hex: "#D1D5DB") + static let backgroundApp = Color(hex: "#F9FAFB") + static let buttonsBorder = Color(hex: "#E5E7EB") + static let micVolume = Color(hex: "#86EFAC") + static let timer = Color(hex: "#E5E7EB") + static let disabledMic = Color(hex: "#ee6b6e") + static let disabledVision = Color(hex: "#BBF7D0") + + init(hex: String) { + let scanner = Scanner(string: hex) + _ = scanner.scanString("#") + + var rgb: UInt64 = 0 + scanner.scanHexInt64(&rgb) + + let red = Double((rgb >> 16) & 0xFF) / 255.0 + let green = Double((rgb >> 8) & 0xFF) / 255.0 + let blue = Double(rgb & 0xFF) / 255.0 + + self.init(red: red, green: green, blue: blue) + } +} diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot/views/settings/SettingsManager.swift b/examples/simple-chatbot/examples/ios/SimpleChatbot/views/settings/SettingsManager.swift new file mode 100644 index 000000000..bfd5034f7 --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot/views/settings/SettingsManager.swift @@ -0,0 +1,21 @@ +import Foundation + +class SettingsManager { + private static let preferencesKey = "settingsPreference" + + static func getSettings() -> SettingsPreference { + if let data = UserDefaults.standard.data(forKey: preferencesKey), + let settings = try? JSONDecoder().decode(SettingsPreference.self, from: data) { + return settings + } else { + // default values in case we don't have any settings + return SettingsPreference(enableMic: true, backendURL: "http://YOUR_IP:7860") + } + } + + static func updateSettings(settings: SettingsPreference) { + if let data = try? JSONEncoder().encode(settings) { + UserDefaults.standard.set(data, forKey: preferencesKey) + } + } +} diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot/views/settings/SettingsPreference.swift b/examples/simple-chatbot/examples/ios/SimpleChatbot/views/settings/SettingsPreference.swift new file mode 100644 index 000000000..b53c4eca9 --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot/views/settings/SettingsPreference.swift @@ -0,0 +1,8 @@ +import Foundation + +struct SettingsPreference: Codable { + var selectedMic: String? + var enableMic: Bool + var backendURL: String +} + diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbot/views/settings/SettingsView.swift b/examples/simple-chatbot/examples/ios/SimpleChatbot/views/settings/SettingsView.swift new file mode 100644 index 000000000..d161b2c55 --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbot/views/settings/SettingsView.swift @@ -0,0 +1,87 @@ +import SwiftUI +import RTVIClientIOS + +struct SettingsView: View { + + @EnvironmentObject private var model: CallContainerModel + + @Binding var showingSettings: Bool + + @State private var selectedMic: MediaDeviceId? = nil + @State private var isMicEnabled: Bool = true + @State private var backendURL: String = "" + + var body: some View { + let microphones = self.model.rtviClientIOS?.getAllMics() ?? [] + NavigationView { + Form { + Section(header: Text("Audio Settings")) { + List(microphones, id: \.self.id.id) { mic in + Button(action: { + self.selectMic(mic.id) + }) { + HStack { + Text(mic.name) + Spacer() + if mic.id == self.selectedMic { + Image(systemName: "checkmark") + } + } + } + } + } + Section(header: Text("Start options")) { + Toggle("Enable Microphone", isOn: $isMicEnabled) + } + Section(header: Text("Server")) { + TextField("Backend URL", text: $backendURL) + .keyboardType(.URL) + } + } + .navigationTitle("Settings") + .toolbar { + ToolbarItem(placement: .cancellationAction) { + Button("Close") { + self.saveSettings() + self.showingSettings = false + } + } + } + .onAppear { + self.loadSettings() + } + } + } + + private func selectMic(_ mic: MediaDeviceId) { + self.selectedMic = mic + self.model.rtviClientIOS?.updateMic(micId: mic, completion: nil) + } + + private func saveSettings() { + let newSettings = SettingsPreference( + selectedMic: selectedMic?.id, + enableMic: isMicEnabled, + backendURL: backendURL + ) + SettingsManager.updateSettings(settings: newSettings) + } + + private func loadSettings() { + let savedSettings = SettingsManager.getSettings() + if let selectedMic = savedSettings.selectedMic { + self.selectedMic = MediaDeviceId(id: selectedMic) + } else { + self.selectedMic = nil + } + self.isMicEnabled = savedSettings.enableMic + self.backendURL = savedSettings.backendURL + } +} + +#Preview { + let mockModel = MockCallContainerModel() + let result = SettingsView(showingSettings: .constant(true)).environmentObject(mockModel as CallContainerModel) + mockModel.startAudioLevelSimulation() + return result +} diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbotTests/SimpleChatbotTests.swift b/examples/simple-chatbot/examples/ios/SimpleChatbotTests/SimpleChatbotTests.swift new file mode 100644 index 000000000..8fcb737d7 --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbotTests/SimpleChatbotTests.swift @@ -0,0 +1,29 @@ +import XCTest +@testable import SimpleChatbot + +final class SimpleChatbotTests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbotUITests/SimpleChatbotUITests.swift b/examples/simple-chatbot/examples/ios/SimpleChatbotUITests/SimpleChatbotUITests.swift new file mode 100644 index 000000000..3a4d61916 --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbotUITests/SimpleChatbotUITests.swift @@ -0,0 +1,34 @@ +import XCTest + +final class SimpleChatbotUITests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = false + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // UI tests must launch the application that they test. + let app = XCUIApplication() + app.launch() + + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testLaunchPerformance() throws { + if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { + // This measures how long it takes to launch your application. + measure(metrics: [XCTApplicationLaunchMetric()]) { + XCUIApplication().launch() + } + } + } +} diff --git a/examples/simple-chatbot/examples/ios/SimpleChatbotUITests/SimpleChatbotUITestsLaunchTests.swift b/examples/simple-chatbot/examples/ios/SimpleChatbotUITests/SimpleChatbotUITestsLaunchTests.swift new file mode 100644 index 000000000..87d03195d --- /dev/null +++ b/examples/simple-chatbot/examples/ios/SimpleChatbotUITests/SimpleChatbotUITestsLaunchTests.swift @@ -0,0 +1,25 @@ +import XCTest + +final class SimpleChatbotUITestsLaunchTests: XCTestCase { + + override class var runsForEachTargetApplicationUIConfiguration: Bool { + true + } + + override func setUpWithError() throws { + continueAfterFailure = false + } + + func testLaunch() throws { + let app = XCUIApplication() + app.launch() + + // Insert steps here to perform after app launch but before taking a screenshot, + // such as logging into a test account or navigating somewhere in the app + + let attachment = XCTAttachment(screenshot: app.screenshot()) + attachment.name = "Launch Screen" + attachment.lifetime = .keepAlways + add(attachment) + } +}