diff --git a/Demo/DemoChat/Sources/Extensions/View.swift b/Demo/DemoChat/Sources/Extensions/View.swift new file mode 100644 index 00000000..4f311176 --- /dev/null +++ b/Demo/DemoChat/Sources/Extensions/View.swift @@ -0,0 +1,65 @@ +// +// View.swift +// +// +// Created by James J Kalafus on 2024-02-03. +// + +import SwiftUI + +extension View { + + @inlinable public func navigationTitle(_ titleKey: LocalizedStringKey, selectedModel: Binding) -> some View { + self + .navigationTitle(titleKey) + .safeAreaInset(edge: .top) { + HStack { + Text( + "Model: \(selectedModel.wrappedValue)" + ) + .font(.caption) + .foregroundColor(.secondary) + Spacer() + } + .padding(.horizontal, 16) + .padding(.vertical, 8) + } + } + + @inlinable public func modelSelect(selectedModel: Binding, models: [String], showsModelSelectionSheet: Binding, help: String) -> some View { + self + .toolbar { + ToolbarItem(placement: .navigationBarTrailing) { + Button(action: { + showsModelSelectionSheet.wrappedValue.toggle() + }) { + Image(systemName: "cpu") + } + } + } + .confirmationDialog( + "Select model", + isPresented: showsModelSelectionSheet, + titleVisibility: .visible, + actions: { + ForEach(models, id: \.self) { (model: String) in + Button { + selectedModel.wrappedValue = model + } label: { + Text(model) + } + } + + Button("Cancel", role: .cancel) { + showsModelSelectionSheet.wrappedValue = false + } + }, + message: { + Text( + "View \(help) for details" + ) + .font(.caption) + } + ) + } +} diff --git a/Demo/DemoChat/Sources/UI/DetailView.swift b/Demo/DemoChat/Sources/UI/DetailView.swift index 3cd119ea..8968ffee 100644 --- a/Demo/DemoChat/Sources/UI/DetailView.swift +++ b/Demo/DemoChat/Sources/UI/DetailView.swift @@ -19,7 +19,7 @@ struct DetailView: View { @State private var showsModelSelectionSheet = false @State private var selectedChatModel: Model = .gpt4_0613 - private let availableChatModels: [Model] = [.gpt3_5Turbo, .gpt4_0613] + private static let availableChatModels: [Model] = [.gpt3_5Turbo, .gpt4] let conversation: Conversation let error: Error? @@ -65,52 +65,8 @@ struct DetailView: View { inputBar(scrollViewProxy: scrollViewProxy) } - .navigationTitle("Chat") - .safeAreaInset(edge: .top) { - HStack { - Text( - "Model: \(selectedChatModel)" - ) - .font(.caption) - .foregroundColor(.secondary) - Spacer() - } - .padding(.horizontal, 16) - .padding(.vertical, 8) - } - .toolbar { - ToolbarItem(placement: .navigationBarTrailing) { - Button(action: { - showsModelSelectionSheet.toggle() - }) { - Image(systemName: "cpu") - } - } - } - .confirmationDialog( - "Select model", - isPresented: $showsModelSelectionSheet, - titleVisibility: .visible, - actions: { - ForEach(availableChatModels, id: \.self) { model in - Button { - selectedChatModel = model - } label: { - Text(model) - } - } - - Button("Cancel", role: .cancel) { - showsModelSelectionSheet = false - } - }, - message: { - Text( - "View https://platform.openai.com/docs/models/overview for details" - ) - .font(.caption) - } - ) + .navigationTitle("Chat", selectedModel: $selectedChatModel) + .modelSelect(selectedModel: $selectedChatModel, models: Self.availableChatModels, showsModelSelectionSheet: $showsModelSelectionSheet, help: "https://platform.openai.com/docs/models/overview") } } } diff --git a/Demo/DemoChat/Sources/UI/TextToSpeechView.swift b/Demo/DemoChat/Sources/UI/TextToSpeechView.swift index 023548ce..00ef4fe4 100644 --- a/Demo/DemoChat/Sources/UI/TextToSpeechView.swift +++ b/Demo/DemoChat/Sources/UI/TextToSpeechView.swift @@ -17,7 +17,11 @@ public struct TextToSpeechView: View { @State private var voice: AudioSpeechQuery.AudioSpeechVoice = .alloy @State private var speed: Double = AudioSpeechQuery.Speed.normal.rawValue @State private var responseFormat: AudioSpeechQuery.AudioSpeechResponseFormat = .mp3 - + @State private var showsModelSelectionSheet = false + @State private var selectedSpeechModel: String = Model.tts_1 + + private static let availableSpeechModels: [String] = [Model.tts_1, Model.tts_1_hd] + public init(store: SpeechStore) { self.store = store } @@ -79,7 +83,7 @@ public struct TextToSpeechView: View { Section { HStack { Button("Create Speech") { - let query = AudioSpeechQuery(model: .tts_1, + let query = AudioSpeechQuery(model: selectedSpeechModel, input: prompt, voice: voice, responseFormat: responseFormat, @@ -93,6 +97,7 @@ public struct TextToSpeechView: View { .disabled(prompt.replacingOccurrences(of: " ", with: "").isEmpty) Spacer() } + .modelSelect(selectedModel: $selectedSpeechModel, models: Self.availableSpeechModels, showsModelSelectionSheet: $showsModelSelectionSheet, help: "https://platform.openai.com/docs/models/tts") } if !$store.audioObjects.wrappedValue.isEmpty { Section("Click to play, swipe to save:") { @@ -129,7 +134,7 @@ public struct TextToSpeechView: View { } .listStyle(.insetGrouped) .scrollDismissesKeyboard(.interactively) - .navigationTitle("Create Speech") + .navigationTitle("Create Speech", selectedModel: $selectedSpeechModel) } }