SimpleChatbot iOS app.
This commit is contained in:
2
examples/simple-chatbot/examples/ios/.gitignore
vendored
Normal file
2
examples/simple-chatbot/examples/ios/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/SimpleChatbot.xcodeproj/xcuserdata/
|
||||
/SimpleChatbot.xcodeproj/project.xcworkspace/xcuserdata/
|
||||
18
examples/simple-chatbot/examples/ios/README.md
Normal file
18
examples/simple-chatbot/examples/ios/README.md
Normal file
@@ -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.
|
||||
|
||||
@@ -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 = "<group>"; };
|
||||
90031FA82C616EE700408370 /* PreJoinView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreJoinView.swift; sourceTree = "<group>"; };
|
||||
90031FAA2C616EE800408370 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
90031FAD2C616EE800408370 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
90031FC32C616EE900408370 /* SimpleChatbotUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleChatbotUITestsLaunchTests.swift; sourceTree = "<group>"; };
|
||||
90031FD62C63FD6A00408370 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||
90031FDB2C6D5DD700408370 /* ToastModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastModifier.swift; sourceTree = "<group>"; };
|
||||
90ABB98D2C735ED6000D9CC7 /* MeetingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeetingView.swift; sourceTree = "<group>"; };
|
||||
90ABB98F2C736A8B000D9CC7 /* WaveformView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaveformView.swift; sourceTree = "<group>"; };
|
||||
90ABB9922C73820D000D9CC7 /* MicrophoneView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MicrophoneView.swift; sourceTree = "<group>"; };
|
||||
90ABB9972C738356000D9CC7 /* CustomColors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomColors.swift; sourceTree = "<group>"; };
|
||||
90ABB9992C73A6A9000D9CC7 /* MockCallContainerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCallContainerModel.swift; sourceTree = "<group>"; };
|
||||
90ABB99C2C73C2D1000D9CC7 /* CallContainerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallContainerModel.swift; sourceTree = "<group>"; };
|
||||
90ABB9A22C74E1CE000D9CC7 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
|
||||
90ABB9A52C74EA8A000D9CC7 /* SettingsPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsPreference.swift; sourceTree = "<group>"; };
|
||||
90ABB9A72C74EAB1000D9CC7 /* SettingsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsManager.swift; sourceTree = "<group>"; };
|
||||
/* 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 = "<group>";
|
||||
};
|
||||
90031FA42C616EE700408370 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
90031FA32C616EE700408370 /* SimpleChatbot.app */,
|
||||
90031FB32C616EE900408370 /* SimpleChatbotTests.xctest */,
|
||||
90031FBD2C616EE900408370 /* SimpleChatbotUITests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
90031FA52C616EE700408370 /* SimpleChatbot */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
90ABB99B2C73C2C5000D9CC7 /* model */,
|
||||
90031FDD2C6D61E000408370 /* views */,
|
||||
90031FD62C63FD6A00408370 /* Info.plist */,
|
||||
90031FA62C616EE700408370 /* SimpleChatbotApp.swift */,
|
||||
90031FAA2C616EE800408370 /* Assets.xcassets */,
|
||||
90031FAC2C616EE800408370 /* Preview Content */,
|
||||
);
|
||||
path = SimpleChatbot;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
90031FAC2C616EE800408370 /* Preview Content */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
90031FAD2C616EE800408370 /* Preview Assets.xcassets */,
|
||||
);
|
||||
path = "Preview Content";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
90031FB62C616EE900408370 /* SimpleChatbotTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
90031FB72C616EE900408370 /* SimpleChatbotTests.swift */,
|
||||
);
|
||||
path = SimpleChatbotTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
90031FC02C616EE900408370 /* SimpleChatbotUITests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
90031FC12C616EE900408370 /* SimpleChatbotUITests.swift */,
|
||||
90031FC32C616EE900408370 /* SimpleChatbotUITestsLaunchTests.swift */,
|
||||
);
|
||||
path = SimpleChatbotUITests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
90031FDD2C6D61E000408370 /* views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
90ABB99E2C73C3A9000D9CC7 /* components */,
|
||||
90ABB9962C738346000D9CC7 /* extensions */,
|
||||
90ABB9A42C74EA52000D9CC7 /* settings */,
|
||||
90031FA82C616EE700408370 /* PreJoinView.swift */,
|
||||
90ABB98D2C735ED6000D9CC7 /* MeetingView.swift */,
|
||||
);
|
||||
path = views;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
90ABB9962C738346000D9CC7 /* extensions */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
90ABB9972C738356000D9CC7 /* CustomColors.swift */,
|
||||
);
|
||||
path = extensions;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
90ABB99B2C73C2C5000D9CC7 /* model */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
90ABB9992C73A6A9000D9CC7 /* MockCallContainerModel.swift */,
|
||||
90ABB99C2C73C2D1000D9CC7 /* CallContainerModel.swift */,
|
||||
);
|
||||
path = model;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
90ABB99E2C73C3A9000D9CC7 /* components */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
90ABB98F2C736A8B000D9CC7 /* WaveformView.swift */,
|
||||
90ABB9922C73820D000D9CC7 /* MicrophoneView.swift */,
|
||||
90031FDB2C6D5DD700408370 /* ToastModifier.swift */,
|
||||
);
|
||||
path = components;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
90ABB9A42C74EA52000D9CC7 /* settings */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
90ABB9A52C74EA8A000D9CC7 /* SettingsPreference.swift */,
|
||||
90ABB9A72C74EAB1000D9CC7 /* SettingsManager.swift */,
|
||||
90ABB9A22C74E1CE000D9CC7 /* SettingsView.swift */,
|
||||
);
|
||||
path = settings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* 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 */;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1540"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES"
|
||||
buildArchitectures = "Automatic">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "90031FA22C616EE700408370"
|
||||
BuildableName = "SimpleChatbot.app"
|
||||
BlueprintName = "SimpleChatbot"
|
||||
ReferencedContainer = "container:SimpleChatbot.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "90031FA22C616EE700408370"
|
||||
BuildableName = "SimpleChatbot.app"
|
||||
BlueprintName = "SimpleChatbot"
|
||||
ReferencedContainer = "container:SimpleChatbot.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "90031FA22C616EE700408370"
|
||||
BuildableName = "SimpleChatbot.app"
|
||||
BlueprintName = "SimpleChatbot"
|
||||
ReferencedContainer = "container:SimpleChatbot.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "appstore.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<svg width="450" height="450" viewBox="0 0 450 450" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="450" height="450" fill="white"/>
|
||||
<path d="M104.772 129.77C109.448 128.01 114.725 129.331 118.02 133.086L160.936 182H289.064L331.98 133.086C335.275 129.331 340.552 128.01 345.228 129.77C349.904 131.531 353 136.004 353 141V249H391V273H329V172.873L303.52 201.915C301.242 204.511 297.955 206 294.5 206H155.5C152.045 206 148.758 204.511 146.48 201.915L121 172.873V273H59V249H97V141C97 136.004 100.096 131.531 104.772 129.77Z" fill="black"/>
|
||||
<path d="M329 297H391V321H329V297Z" fill="black"/>
|
||||
<path d="M59 297H121V321H59V297Z" fill="black"/>
|
||||
<path d="M187 257C187 265.837 179.837 273 171 273C162.163 273 155 265.837 155 257C155 248.164 162.163 241 171 241C179.837 241 187 248.164 187 257Z" fill="black"/>
|
||||
<path d="M295 257C295 265.837 287.837 273 279 273C270.163 273 263 265.837 263 257C263 248.164 270.163 241 279 241C287.837 241 295 248.164 295 257Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 982 B |
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>voip</string>
|
||||
</array>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Camera is necessary for transmitting video in a call</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>Microphone is necessary for transmitting audio in a call</string>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsLocalNetworking</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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<CGSize> = .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()
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
@@ -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..<dotCount, id: \.self) { index in
|
||||
Rectangle()
|
||||
.fill(Color.white)
|
||||
.frame(height: CGFloat(audioLevels[index]) * (geometry.size.height))
|
||||
.cornerRadius(12)
|
||||
.animation(.easeInOut(duration: 0.2), value: audioLevels[index])
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.horizontal, 5)
|
||||
}
|
||||
.frame(width: geometry.size.width * 0.5, height: geometry.size.width * 0.5)
|
||||
.mask(Circle().frame(width: geometry.size.width * 0.82, height: geometry.size.width * 0.82))
|
||||
} else {
|
||||
// Dots inside the circle
|
||||
HStack(spacing: 10) {
|
||||
ForEach(0..<dotCount, id: \.self) { _ in
|
||||
Circle()
|
||||
.fill(Color.white)
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
.frame(width: geometry.size.width * 0.5, height: geometry.size.height * 0.5)
|
||||
}
|
||||
} else {
|
||||
// Gray circle with loading icon when not connected
|
||||
VStack {
|
||||
ProgressView()
|
||||
.progressViewStyle(CircularProgressViewStyle(tint: .white))
|
||||
.scaleEffect(2) // Adjust size of the loading spinner
|
||||
.padding()
|
||||
Text(voiceClientStatus)
|
||||
.foregroundColor(.white)
|
||||
.font(.headline)
|
||||
}
|
||||
}
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
.onChange(of: audioLevel) { oldLevel, newLevel in
|
||||
// The audio level that we receive from the bot is usually too low
|
||||
// so just increasing it so we can see a better graph but
|
||||
// making sure that it is not higher than the maximum 1
|
||||
var audioLevel = audioLevel + 0.4
|
||||
if(audioLevel > 1) {
|
||||
audioLevel = 1
|
||||
}
|
||||
// Update the array and shift values
|
||||
audioLevels.removeFirst()
|
||||
audioLevels.append(newLevel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
WaveformView(audioLevel: 0, isBotReady: false, voiceClientStatus: "idle")
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import Foundation
|
||||
|
||||
struct SettingsPreference: Codable {
|
||||
var selectedMic: String?
|
||||
var enableMic: Bool
|
||||
var backendURL: String
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user