Skip to content

Commit db28c4e

Browse files
committed
Extract logic
1 parent 88e54cb commit db28c4e

30 files changed

+184
-1191
lines changed

VoiceAgent.xcodeproj/project.pbxproj

Lines changed: 0 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,6 @@
2323
remoteGlobalIDString = ACAEBA572DE6EE970072E93E;
2424
remoteInfo = BroadcastExtension;
2525
};
26-
ACC2802B2DEDDA1D0023C137 /* PBXContainerItemProxy */ = {
27-
isa = PBXContainerItemProxy;
28-
containerPortal = B5B5E3AA2D124AE00099C9BE /* Project object */;
29-
proxyType = 1;
30-
remoteGlobalIDString = B5B5E3B12D124AE00099C9BE;
31-
remoteInfo = VoiceAgent;
32-
};
3326
/* End PBXContainerItemProxy section */
3427

3528
/* Begin PBXCopyFilesBuildPhase section */
@@ -49,7 +42,6 @@
4942
/* Begin PBXFileReference section */
5043
ACAEBA582DE6EE970072E93E /* BroadcastExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = BroadcastExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
5144
ACAEBA5A2DE6EE970072E93E /* ReplayKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReplayKit.framework; path = System/Library/Frameworks/ReplayKit.framework; sourceTree = SDKROOT; };
52-
ACC280272DEDDA1D0023C137 /* VoiceAgentTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = VoiceAgentTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
5345
B5B5E3B22D124AE00099C9BE /* VoiceAgent.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = VoiceAgent.app; sourceTree = BUILT_PRODUCTS_DIR; };
5446
/* End PBXFileReference section */
5547

@@ -82,11 +74,6 @@
8274
path = BroadcastExtension;
8375
sourceTree = "<group>";
8476
};
85-
ACC280282DEDDA1D0023C137 /* VoiceAgentTests */ = {
86-
isa = PBXFileSystemSynchronizedRootGroup;
87-
path = VoiceAgentTests;
88-
sourceTree = "<group>";
89-
};
9077
B5B5E3B42D124AE00099C9BE /* VoiceAgent */ = {
9178
isa = PBXFileSystemSynchronizedRootGroup;
9279
exceptions = (
@@ -107,13 +94,6 @@
10794
);
10895
runOnlyForDeploymentPostprocessing = 0;
10996
};
110-
ACC280242DEDDA1D0023C137 /* Frameworks */ = {
111-
isa = PBXFrameworksBuildPhase;
112-
buildActionMask = 2147483647;
113-
files = (
114-
);
115-
runOnlyForDeploymentPostprocessing = 0;
116-
};
11797
B5B5E3AF2D124AE00099C9BE /* Frameworks */ = {
11898
isa = PBXFrameworksBuildPhase;
11999
buildActionMask = 2147483647;
@@ -140,7 +120,6 @@
140120
children = (
141121
B5B5E3B42D124AE00099C9BE /* VoiceAgent */,
142122
ACAEBA5C2DE6EE970072E93E /* BroadcastExtension */,
143-
ACC280282DEDDA1D0023C137 /* VoiceAgentTests */,
144123
ACAEBA592DE6EE970072E93E /* Frameworks */,
145124
B5B5E3B32D124AE00099C9BE /* Products */,
146125
);
@@ -151,7 +130,6 @@
151130
children = (
152131
B5B5E3B22D124AE00099C9BE /* VoiceAgent.app */,
153132
ACAEBA582DE6EE970072E93E /* BroadcastExtension.appex */,
154-
ACC280272DEDDA1D0023C137 /* VoiceAgentTests.xctest */,
155133
);
156134
name = Products;
157135
sourceTree = "<group>";
@@ -182,29 +160,6 @@
182160
productReference = ACAEBA582DE6EE970072E93E /* BroadcastExtension.appex */;
183161
productType = "com.apple.product-type.app-extension";
184162
};
185-
ACC280262DEDDA1D0023C137 /* VoiceAgentTests */ = {
186-
isa = PBXNativeTarget;
187-
buildConfigurationList = ACC2802F2DEDDA1D0023C137 /* Build configuration list for PBXNativeTarget "VoiceAgentTests" */;
188-
buildPhases = (
189-
ACC280232DEDDA1D0023C137 /* Sources */,
190-
ACC280242DEDDA1D0023C137 /* Frameworks */,
191-
ACC280252DEDDA1D0023C137 /* Resources */,
192-
);
193-
buildRules = (
194-
);
195-
dependencies = (
196-
ACC2802C2DEDDA1D0023C137 /* PBXTargetDependency */,
197-
);
198-
fileSystemSynchronizedGroups = (
199-
ACC280282DEDDA1D0023C137 /* VoiceAgentTests */,
200-
);
201-
name = VoiceAgentTests;
202-
packageProductDependencies = (
203-
);
204-
productName = VoiceAgentTests;
205-
productReference = ACC280272DEDDA1D0023C137 /* VoiceAgentTests.xctest */;
206-
productType = "com.apple.product-type.bundle.unit-test";
207-
};
208163
B5B5E3B12D124AE00099C9BE /* VoiceAgent */ = {
209164
isa = PBXNativeTarget;
210165
buildConfigurationList = B5B5E3C12D124AE20099C9BE /* Build configuration list for PBXNativeTarget "VoiceAgent" */;
@@ -245,10 +200,6 @@
245200
ACAEBA572DE6EE970072E93E = {
246201
CreatedOnToolsVersion = 16.3;
247202
};
248-
ACC280262DEDDA1D0023C137 = {
249-
CreatedOnToolsVersion = 16.3;
250-
TestTargetID = B5B5E3B12D124AE00099C9BE;
251-
};
252203
B5B5E3B12D124AE00099C9BE = {
253204
CreatedOnToolsVersion = 16.2;
254205
};
@@ -274,7 +225,6 @@
274225
projectRoot = "";
275226
targets = (
276227
B5B5E3B12D124AE00099C9BE /* VoiceAgent */,
277-
ACC280262DEDDA1D0023C137 /* VoiceAgentTests */,
278228
ACAEBA572DE6EE970072E93E /* BroadcastExtension */,
279229
);
280230
};
@@ -288,13 +238,6 @@
288238
);
289239
runOnlyForDeploymentPostprocessing = 0;
290240
};
291-
ACC280252DEDDA1D0023C137 /* Resources */ = {
292-
isa = PBXResourcesBuildPhase;
293-
buildActionMask = 2147483647;
294-
files = (
295-
);
296-
runOnlyForDeploymentPostprocessing = 0;
297-
};
298241
B5B5E3B02D124AE00099C9BE /* Resources */ = {
299242
isa = PBXResourcesBuildPhase;
300243
buildActionMask = 2147483647;
@@ -312,13 +255,6 @@
312255
);
313256
runOnlyForDeploymentPostprocessing = 0;
314257
};
315-
ACC280232DEDDA1D0023C137 /* Sources */ = {
316-
isa = PBXSourcesBuildPhase;
317-
buildActionMask = 2147483647;
318-
files = (
319-
);
320-
runOnlyForDeploymentPostprocessing = 0;
321-
};
322258
B5B5E3AE2D124AE00099C9BE /* Sources */ = {
323259
isa = PBXSourcesBuildPhase;
324260
buildActionMask = 2147483647;
@@ -338,11 +274,6 @@
338274
target = ACAEBA572DE6EE970072E93E /* BroadcastExtension */;
339275
targetProxy = ACAEBA602DE6EE970072E93E /* PBXContainerItemProxy */;
340276
};
341-
ACC2802C2DEDDA1D0023C137 /* PBXTargetDependency */ = {
342-
isa = PBXTargetDependency;
343-
target = B5B5E3B12D124AE00099C9BE /* VoiceAgent */;
344-
targetProxy = ACC2802B2DEDDA1D0023C137 /* PBXContainerItemProxy */;
345-
};
346277
/* End PBXTargetDependency section */
347278

348279
/* Begin XCBuildConfiguration section */
@@ -411,58 +342,6 @@
411342
};
412343
name = Release;
413344
};
414-
ACC2802D2DEDDA1D0023C137 /* Debug */ = {
415-
isa = XCBuildConfiguration;
416-
buildSettings = {
417-
BUNDLE_LOADER = "$(TEST_HOST)";
418-
CODE_SIGN_IDENTITY = "Apple Development";
419-
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
420-
CODE_SIGN_STYLE = Automatic;
421-
DEAD_CODE_STRIPPING = YES;
422-
DEVELOPMENT_TEAM = 76TVFCUKK7;
423-
GENERATE_INFOPLIST_FILE = YES;
424-
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
425-
MACOSX_DEPLOYMENT_TARGET = 15.0;
426-
MARKETING_VERSION = 1.0;
427-
PRODUCT_BUNDLE_IDENTIFIER = com.livekit.VoiceAgentTests;
428-
PRODUCT_NAME = "$(TARGET_NAME)";
429-
PROVISIONING_PROFILE_SPECIFIER = "";
430-
SDKROOT = auto;
431-
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator";
432-
SWIFT_EMIT_LOC_STRINGS = NO;
433-
SWIFT_VERSION = 5.0;
434-
TARGETED_DEVICE_FAMILY = "1,2,7";
435-
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/VoiceAgent.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/VoiceAgent";
436-
XROS_DEPLOYMENT_TARGET = 2.0;
437-
};
438-
name = Debug;
439-
};
440-
ACC2802E2DEDDA1D0023C137 /* Release */ = {
441-
isa = XCBuildConfiguration;
442-
buildSettings = {
443-
BUNDLE_LOADER = "$(TEST_HOST)";
444-
CODE_SIGN_IDENTITY = "Apple Development";
445-
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
446-
CODE_SIGN_STYLE = Automatic;
447-
DEAD_CODE_STRIPPING = YES;
448-
DEVELOPMENT_TEAM = 76TVFCUKK7;
449-
GENERATE_INFOPLIST_FILE = YES;
450-
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
451-
MACOSX_DEPLOYMENT_TARGET = 15.0;
452-
MARKETING_VERSION = 1.0;
453-
PRODUCT_BUNDLE_IDENTIFIER = com.livekit.VoiceAgentTests;
454-
PRODUCT_NAME = "$(TARGET_NAME)";
455-
PROVISIONING_PROFILE_SPECIFIER = "";
456-
SDKROOT = auto;
457-
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator";
458-
SWIFT_EMIT_LOC_STRINGS = NO;
459-
SWIFT_VERSION = 5.0;
460-
TARGETED_DEVICE_FAMILY = "1,2,7";
461-
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/VoiceAgent.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/VoiceAgent";
462-
XROS_DEPLOYMENT_TARGET = 2.0;
463-
};
464-
name = Release;
465-
};
466345
B5B5E3BF2D124AE20099C9BE /* Debug */ = {
467346
isa = XCBuildConfiguration;
468347
buildSettings = {
@@ -689,15 +568,6 @@
689568
defaultConfigurationIsVisible = 0;
690569
defaultConfigurationName = Release;
691570
};
692-
ACC2802F2DEDDA1D0023C137 /* Build configuration list for PBXNativeTarget "VoiceAgentTests" */ = {
693-
isa = XCConfigurationList;
694-
buildConfigurations = (
695-
ACC2802D2DEDDA1D0023C137 /* Debug */,
696-
ACC2802E2DEDDA1D0023C137 /* Release */,
697-
);
698-
defaultConfigurationIsVisible = 0;
699-
defaultConfigurationName = Release;
700-
};
701571
B5B5E3AD2D124AE00099C9BE /* Build configuration list for PBXProject "VoiceAgent" */ = {
702572
isa = XCConfigurationList;
703573
buildConfigurations = (

VoiceAgent.xcodeproj/xcshareddata/xcschemes/VoiceAgent.xcscheme

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,8 @@
2727
buildConfiguration = "Debug"
2828
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
2929
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
30-
shouldUseLaunchSchemeArgsEnv = "YES">
31-
<TestPlans>
32-
<TestPlanReference
33-
reference = "container:VoiceAgent/VoiceAgent.xctestplan"
34-
default = "YES">
35-
</TestPlanReference>
36-
</TestPlans>
30+
shouldUseLaunchSchemeArgsEnv = "YES"
31+
shouldAutocreateTestPlan = "YES">
3732
<Testables>
3833
<TestableReference
3934
skipped = "NO"

VoiceAgent/App/AppView.swift

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
1+
import LiveKit
12
import SwiftUI
23

34
struct AppView: View {
4-
@Environment(AppViewModel.self) private var viewModel
5-
@State private var chatViewModel = ChatViewModel()
5+
@LKConversation private var conversation
6+
@LKLocalMedia private var localMedia
67

7-
@State private var error: Error?
8-
@FocusState private var keyboardFocus: Bool
8+
@State private var chat: Bool = false
99

10+
@FocusState private var keyboardFocus: Bool
1011
@Namespace private var namespace
1112

1213
var body: some View {
1314
ZStack(alignment: .top) {
14-
if viewModel.isInteractive {
15+
if conversation.isReady {
1516
interactions()
1617
} else {
1718
start()
@@ -22,57 +23,54 @@ struct AppView: View {
2223
.environment(\.namespace, namespace)
2324
#if os(visionOS)
2425
.ornament(attachmentAnchor: .scene(.bottom)) {
25-
if viewModel.isInteractive {
26-
ControlBar()
26+
if conversation.isReady {
27+
ControlBar(chat: $chat)
2728
.glassBackgroundEffect()
2829
}
2930
}
30-
.alert("warning.reconnecting", isPresented: .constant(viewModel.connectionState == .reconnecting)) {}
31-
.alert(error?.localizedDescription ?? "error.title", isPresented: .constant(error != nil)) {
32-
Button("error.ok") { error = nil }
31+
.alert("warning.reconnecting", isPresented: .constant(conversation.connectionState == .reconnecting)) {}
32+
.alert(conversation.error?.localizedDescription ?? "error.title", isPresented: .constant(conversation.error != nil)) {
33+
Button("error.ok") { conversation.resetError() }
3334
}
3435
#else
3536
.safeAreaInset(edge: .bottom) {
36-
if viewModel.isInteractive, !keyboardFocus {
37-
ControlBar()
37+
if conversation.isReady, !keyboardFocus {
38+
ControlBar(chat: $chat)
3839
.transition(.asymmetric(insertion: .move(edge: .bottom).combined(with: .opacity), removal: .opacity))
3940
}
4041
}
4142
#endif
4243
.background(.bg1)
43-
.animation(.default, value: viewModel.isInteractive)
44-
.animation(.default, value: viewModel.interactionMode)
45-
.animation(.default, value: viewModel.isCameraEnabled)
46-
.animation(.default, value: viewModel.isScreenShareEnabled)
47-
.animation(.default, value: error?.localizedDescription)
48-
.onAppear {
49-
Dependencies.shared.errorHandler = { error = $0 }
50-
}
44+
.animation(.default, value: chat)
45+
.animation(.default, value: conversation.isReady)
46+
.animation(.default, value: conversation.error?.localizedDescription)
47+
.animation(.default, value: localMedia.isCameraEnabled)
48+
.animation(.default, value: localMedia.isScreenShareEnabled)
5149
#if os(iOS)
52-
.sensoryFeedback(.impact, trigger: viewModel.isListening)
50+
.sensoryFeedback(.impact, trigger: conversation.isListening) { !$0 && $1 }
5351
#endif
5452
}
5553

5654
@ViewBuilder
5755
private func start() -> some View {
5856
StartView()
57+
.onAppear {
58+
chat = false
59+
}
5960
}
6061

6162
@ViewBuilder
6263
private func interactions() -> some View {
6364
#if os(visionOS)
64-
VisionInteractionView(keyboardFocus: $keyboardFocus)
65-
.environment(chatViewModel)
65+
VisionInteractionView(chat: chat, keyboardFocus: $keyboardFocus)
6666
.overlay(alignment: .bottom) {
6767
agentListening()
6868
.padding(16 * .grid)
6969
}
7070
#else
71-
switch viewModel.interactionMode {
72-
case .text:
71+
if chat {
7372
TextInteractionView(keyboardFocus: $keyboardFocus)
74-
.environment(chatViewModel)
75-
case .voice:
73+
} else {
7674
VoiceInteractionView()
7775
.overlay(alignment: .bottom) {
7876
agentListening()
@@ -85,27 +83,27 @@ struct AppView: View {
8583
@ViewBuilder
8684
private func errors() -> some View {
8785
#if !os(visionOS)
88-
if case .reconnecting = viewModel.connectionState {
86+
if case .reconnecting = conversation.connectionState {
8987
WarningView(warning: "warning.reconnecting")
9088
}
9189

92-
if let error {
93-
ErrorView(error: error) { self.error = nil }
90+
if let error = conversation.error {
91+
ErrorView(error: error) { conversation.resetError() }
9492
}
9593
#endif
9694
}
9795

9896
@ViewBuilder
9997
private func agentListening() -> some View {
10098
ZStack {
101-
if chatViewModel.messages.isEmpty,
102-
!viewModel.isCameraEnabled,
103-
!viewModel.isScreenShareEnabled
99+
if conversation.messages.isEmpty,
100+
!localMedia.isCameraEnabled,
101+
!localMedia.isScreenShareEnabled
104102
{
105103
AgentListeningView()
106104
}
107105
}
108-
.animation(.default, value: chatViewModel.messages.isEmpty)
106+
.animation(.default, value: conversation.messages.isEmpty)
109107
}
110108
}
111109

0 commit comments

Comments
 (0)