Skip to content

Commit 35afc9a

Browse files
authored
Merge pull request #161 from kalafus/MacPaw.views_abstraction
view abstraction of navigationTitle and modelSelect for reuse in demo
2 parents a2c8d17 + af81a41 commit 35afc9a

File tree

3 files changed

+76
-50
lines changed

3 files changed

+76
-50
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//
2+
// View.swift
3+
//
4+
//
5+
// Created by James J Kalafus on 2024-02-03.
6+
//
7+
8+
import SwiftUI
9+
10+
extension View {
11+
12+
@inlinable public func navigationTitle(_ titleKey: LocalizedStringKey, selectedModel: Binding<String>) -> some View {
13+
self
14+
.navigationTitle(titleKey)
15+
.safeAreaInset(edge: .top) {
16+
HStack {
17+
Text(
18+
"Model: \(selectedModel.wrappedValue)"
19+
)
20+
.font(.caption)
21+
.foregroundColor(.secondary)
22+
Spacer()
23+
}
24+
.padding(.horizontal, 16)
25+
.padding(.vertical, 8)
26+
}
27+
}
28+
29+
@inlinable public func modelSelect(selectedModel: Binding<String>, models: [String], showsModelSelectionSheet: Binding<Bool>, help: String) -> some View {
30+
self
31+
.toolbar {
32+
ToolbarItem(placement: .navigationBarTrailing) {
33+
Button(action: {
34+
showsModelSelectionSheet.wrappedValue.toggle()
35+
}) {
36+
Image(systemName: "cpu")
37+
}
38+
}
39+
}
40+
.confirmationDialog(
41+
"Select model",
42+
isPresented: showsModelSelectionSheet,
43+
titleVisibility: .visible,
44+
actions: {
45+
ForEach(models, id: \.self) { (model: String) in
46+
Button {
47+
selectedModel.wrappedValue = model
48+
} label: {
49+
Text(model)
50+
}
51+
}
52+
53+
Button("Cancel", role: .cancel) {
54+
showsModelSelectionSheet.wrappedValue = false
55+
}
56+
},
57+
message: {
58+
Text(
59+
"View \(help) for details"
60+
)
61+
.font(.caption)
62+
}
63+
)
64+
}
65+
}

Demo/DemoChat/Sources/UI/DetailView.swift

Lines changed: 3 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ struct DetailView: View {
1919
@State private var showsModelSelectionSheet = false
2020
@State private var selectedChatModel: Model = .gpt4_0613
2121

22-
private let availableChatModels: [Model] = [.gpt3_5Turbo, .gpt4_0613]
22+
private static let availableChatModels: [Model] = [.gpt3_5Turbo, .gpt4]
2323

2424
let conversation: Conversation
2525
let error: Error?
@@ -65,52 +65,8 @@ struct DetailView: View {
6565

6666
inputBar(scrollViewProxy: scrollViewProxy)
6767
}
68-
.navigationTitle("Chat")
69-
.safeAreaInset(edge: .top) {
70-
HStack {
71-
Text(
72-
"Model: \(selectedChatModel)"
73-
)
74-
.font(.caption)
75-
.foregroundColor(.secondary)
76-
Spacer()
77-
}
78-
.padding(.horizontal, 16)
79-
.padding(.vertical, 8)
80-
}
81-
.toolbar {
82-
ToolbarItem(placement: .navigationBarTrailing) {
83-
Button(action: {
84-
showsModelSelectionSheet.toggle()
85-
}) {
86-
Image(systemName: "cpu")
87-
}
88-
}
89-
}
90-
.confirmationDialog(
91-
"Select model",
92-
isPresented: $showsModelSelectionSheet,
93-
titleVisibility: .visible,
94-
actions: {
95-
ForEach(availableChatModels, id: \.self) { model in
96-
Button {
97-
selectedChatModel = model
98-
} label: {
99-
Text(model)
100-
}
101-
}
102-
103-
Button("Cancel", role: .cancel) {
104-
showsModelSelectionSheet = false
105-
}
106-
},
107-
message: {
108-
Text(
109-
"View https://platform.openai.com/docs/models/overview for details"
110-
)
111-
.font(.caption)
112-
}
113-
)
68+
.navigationTitle("Chat", selectedModel: $selectedChatModel)
69+
.modelSelect(selectedModel: $selectedChatModel, models: Self.availableChatModels, showsModelSelectionSheet: $showsModelSelectionSheet, help: "https://platform.openai.com/docs/models/overview")
11470
}
11571
}
11672
}

Demo/DemoChat/Sources/UI/TextToSpeechView.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ public struct TextToSpeechView: View {
1717
@State private var voice: AudioSpeechQuery.AudioSpeechVoice = .alloy
1818
@State private var speed: Double = AudioSpeechQuery.Speed.normal.rawValue
1919
@State private var responseFormat: AudioSpeechQuery.AudioSpeechResponseFormat = .mp3
20-
20+
@State private var showsModelSelectionSheet = false
21+
@State private var selectedSpeechModel: String = Model.tts_1
22+
23+
private static let availableSpeechModels: [String] = [Model.tts_1, Model.tts_1_hd]
24+
2125
public init(store: SpeechStore) {
2226
self.store = store
2327
}
@@ -79,7 +83,7 @@ public struct TextToSpeechView: View {
7983
Section {
8084
HStack {
8185
Button("Create Speech") {
82-
let query = AudioSpeechQuery(model: .tts_1,
86+
let query = AudioSpeechQuery(model: selectedSpeechModel,
8387
input: prompt,
8488
voice: voice,
8589
responseFormat: responseFormat,
@@ -93,6 +97,7 @@ public struct TextToSpeechView: View {
9397
.disabled(prompt.replacingOccurrences(of: " ", with: "").isEmpty)
9498
Spacer()
9599
}
100+
.modelSelect(selectedModel: $selectedSpeechModel, models: Self.availableSpeechModels, showsModelSelectionSheet: $showsModelSelectionSheet, help: "https://platform.openai.com/docs/models/tts")
96101
}
97102
if !$store.audioObjects.wrappedValue.isEmpty {
98103
Section("Click to play, swipe to save:") {
@@ -129,7 +134,7 @@ public struct TextToSpeechView: View {
129134
}
130135
.listStyle(.insetGrouped)
131136
.scrollDismissesKeyboard(.interactively)
132-
.navigationTitle("Create Speech")
137+
.navigationTitle("Create Speech", selectedModel: $selectedSpeechModel)
133138
}
134139
}
135140

0 commit comments

Comments
 (0)