diff --git a/.gitsecret/paths/mapping.cfg b/.gitsecret/paths/mapping.cfg index 0a5e28f..ad88d2f 100644 --- a/.gitsecret/paths/mapping.cfg +++ b/.gitsecret/paths/mapping.cfg @@ -1 +1 @@ -OpenAI.xcconfig:8fc76376401e5c8b562fb5e262c7fd0a41751e5987fb0a6b449ac75c7c643ad3 +OpenAI.xcconfig:e95c1ca7bea3258d863be5c69dafafa4b2062cfbf3939e47a565a888a903be6c diff --git a/OpenAI.xcconfig.secret b/OpenAI.xcconfig.secret index ede770a..906a9f6 100644 Binary files a/OpenAI.xcconfig.secret and b/OpenAI.xcconfig.secret differ diff --git a/PlantUML/PlantUML+OpenAI.swift b/PlantUML/PlantUML+OpenAI.swift index 50c683d..5bf118d 100644 --- a/PlantUML/PlantUML+OpenAI.swift +++ b/PlantUML/PlantUML+OpenAI.swift @@ -92,11 +92,15 @@ class OpenAIService : ObservableObject { case Editing } + let models = ["text-davinci-edit-001", "code-davinci-edit-001"] + @Published public var status: Status = .Ready @Published public var inputApiKey = "" @Published public var inputOrgId = "" + @Published public var inputModel:String + @AppStorage("openaiModel") private var openAIModel:String? @AppSecureStorage("openaikey") private var openAIKey:String? @AppSecureStorage("openaiorg") private var openAIOrg:String? @@ -105,6 +109,8 @@ class OpenAIService : ObservableObject { init() { + inputModel = models[0] + if let apiKey = Bundle.main.object(forInfoDictionaryKey: "OPENAI_API_KEY") as? String, !apiKey.isEmpty { openAIKey = apiKey } @@ -112,9 +118,16 @@ class OpenAIService : ObservableObject { openAIOrg = orgId } + inputApiKey = openAIKey ?? "" inputOrgId = openAIOrg ?? "" - } + + if let openAIModel { + inputModel = openAIModel + } + + + } func commitSettings() { guard !inputApiKey.isEmpty, !inputOrgId.isEmpty else { @@ -122,12 +135,14 @@ class OpenAIService : ObservableObject { } openAIKey = inputApiKey openAIOrg = inputOrgId + openAIModel = inputModel // focobjectWillChange.send() } func resetSettings() { inputApiKey = "" inputOrgId = "" + inputModel = models[0] openAIKey = nil openAIOrg = nil } @@ -174,7 +189,7 @@ class OpenAIService : ObservableObject { @MainActor func generateEdit( input: String, instruction: String ) async -> String? { - guard let openAI, case .Ready = status else { + guard let openAI, let openAIModel, case .Ready = status else { return nil } @@ -182,7 +197,7 @@ class OpenAIService : ObservableObject { do { let editParameter = EditParameters( - model: "text-davinci-edit-001", + model: openAIModel, input: input, instruction: instruction, temperature: 0.0, @@ -222,6 +237,8 @@ struct OpenAIView : View { @FocusState private var promptInFocus: Bool + + var isEditing:Bool { if case .Editing = service.status { return true @@ -423,26 +440,54 @@ extension OpenAIView { var Settings_Fragment: some View { ZStack(alignment: .bottomTrailing ) { - Form { - Section { - SecureToggleField( "Api Key", value: $service.inputApiKey, hidden: hideOpenAISecrets) - SecureToggleField( "Org Id", value: $service.inputOrgId, hidden: hideOpenAISecrets) - } - header: { - HStack { - Text("OpenAI Secrets") - HideToggleButton(hidden: $hideOpenAISecrets) + // [How to scroll a Form to a specific UI element in SwiftUI](https://stackoverflow.com/a/65777080/521197) + ScrollViewReader { p in + Form { + Section { + SecureToggleField( "Api Key", value: $service.inputApiKey, hidden: hideOpenAISecrets) + + SecureToggleField( "Org Id", value: $service.inputOrgId, hidden: hideOpenAISecrets) } - } - footer: { - HStack { - Spacer() - Text("these data will be stored in onboard secure keychain") - Spacer() + header: { + HStack { + Text("OpenAI Secrets") + HideToggleButton(hidden: $hideOpenAISecrets) + Divider() + Button( action: { p.scrollTo("openai-settings", anchor: .top) }, label: { Text("More .....").font(.footnote) } ) + } + .id( "openai-secret") + + } + footer: { + HStack { + Spacer() + Text("these data will be stored in onboard secure keychain") + Spacer() + } + } + + Section { + Picker("Model", selection: $service.inputModel) { + ForEach(service.models, id: \.self) { + Text($0) + } + } } + header: { + HStack { + Text("OpenAI Extra settings") + Divider() + Button( action: { p.scrollTo("openai-secret", anchor: .bottom) }, label: { Text("Back ...").font(.footnote) } ) + } + .id( "openai-settings") + } + footer: { + Rectangle().fill(Color.clear).frame(height: 65) + + } + } } - HStack { Button( action: { service.resetSettings() diff --git a/PlantUMLApp.xcodeproj/project.pbxproj b/PlantUMLApp.xcodeproj/project.pbxproj index c7368ff..265c3cf 100644 --- a/PlantUMLApp.xcodeproj/project.pbxproj +++ b/PlantUMLApp.xcodeproj/project.pbxproj @@ -73,6 +73,7 @@ A038DB5B29D452880032E312 /* OpenAI.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = OpenAI.xcconfig; sourceTree = ""; }; A038DB5F29D489BA0032E312 /* PlantUML+OpenAI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "PlantUML+OpenAI.swift"; sourceTree = ""; }; A047206E29549ACC007E061F /* SwiftUI+Share.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SwiftUI+Share.swift"; sourceTree = ""; }; + A05F2E372A1FFC49007FDF36 /* CHANGELOG.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = ""; }; A068572D29D8B31100E82C2F /* View+Clipboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Clipboard.swift"; sourceTree = ""; }; A074F6982A16D40500061398 /* OpenAI.prod.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = OpenAI.prod.xcconfig; sourceTree = ""; }; A08AA78329561170004DE329 /* View+UIImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+UIImage.swift"; sourceTree = ""; }; @@ -156,6 +157,7 @@ A0D3C63D28984A0E000838D7 = { isa = PBXGroup; children = ( + A05F2E372A1FFC49007FDF36 /* CHANGELOG.md */, A074F6982A16D40500061398 /* OpenAI.prod.xcconfig */, A038DB5B29D452880032E312 /* OpenAI.xcconfig */, A01907EF2951CD5C0059CCBE /* privacy_policy.md */, @@ -610,7 +612,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"PlantUML/Preview Content\""; DEVELOPMENT_TEAM = 48J595L9BX; ENABLE_PREVIEWS = YES; @@ -628,7 +630,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.4.0; + MARKETING_VERSION = 1.4.1; PRODUCT_BUNDLE_IDENTIFIER = org.bsc.PlantUML; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; @@ -647,10 +649,11 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"PlantUML/Preview Content\""; DEVELOPMENT_TEAM = 48J595L9BX; ENABLE_PREVIEWS = YES; + "EXCLUDED_SOURCE_FILE_NAMES[arch=*]" = OpenAI.xcconfig; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = PlantUML/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = PlantUMLApp; @@ -665,7 +668,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.4.0; + MARKETING_VERSION = 1.4.1; PRODUCT_BUNDLE_IDENTIFIER = org.bsc.PlantUML; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; diff --git a/README.md b/README.md index 4d7ebd7..9bb2307 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ _Promotional Text_ 🤞 * Prompt your diagram request in natural language * Undo Prompt * Prompt's History + * choose AI Model ## App Store @@ -46,32 +47,32 @@ See the App on [App Store](https://apps.apple.com/us/app/plantuml-app/id64441649 Below all references that helped to develop such App -* [iOS Localization and Internationalization Testing with XCUITest](https://medium.com/xcblog/ios-localization-and-internationalization-testing-with-xcuitest-495747a74775) -* [How to access back bar button item in universal way under UITests in Xcode?](https://stackoverflow.com/a/38595332/521197) -* [SwiftUI: Forcing an Update](https://stackoverflow.com/a/65095862/521197) -* [How to convert a SwiftUI view to an image](https://www.hackingwithswift.com/quick-start/swiftui/how-to-convert-a-swiftui-view-to-an-image) -* [iOS UI testing: element descendants](https://pgu.dev/2020/12/20/ios-ui-tests-element-descendants.html) -* [How can I add caching to AsyncImage](https://stackoverflow.com/a/70916651/521197) -* [Open-source themes for PlantUML diagrams](https://bschwarz.github.io/puml-themes/gallery.html) +* [Get a binding from an environment value in SwiftUI](https://stackoverflow.com/q/69731360/521197) +* [How can I set an image tint in SwiftUI?](https://stackoverflow.com/a/73289182/521197) +* [Get the current first responder without using a private API](https://stackoverflow.com/a/1823360/521197) +* [Split Picture in tiles and put in array](https://stackoverflow.com/a/73628496/521197) * [SwiftUI exporting or sharing files](https://stackoverflow.com/a/56828100/521197) -* [Regular Expression Capture Groups in Swift](https://www.advancedswift.com/regex-capture-groups/) +* [Customizing Toggle with ToggleStyle](https://www.hackingwithswift.com/quick-start/swiftui/customizing-toggle-with-togglestyle) * [How to remove all the spaces in a String?](https://stackoverflow.com/a/34940120/521197) +* [Perform a full swipe left action in UI Tests?](https://stackoverflow.com/a/51639973) * [Managing Focus in SwiftUI List Views](https://peterfriese.dev/posts/swiftui-list-focus/) +* [How to access back bar button item in universal way under UITests in Xcode?](https://stackoverflow.com/a/38595332/521197) +* [Regular Expression Capture Groups in Swift](https://www.advancedswift.com/regex-capture-groups/) +* [iOS UI testing: element descendants](https://pgu.dev/2020/12/20/ios-ui-tests-element-descendants.html) * [SwiftUI Let View disappear automatically](https://stackoverflow.com/a/60820491/521197) -* [How can I set an image tint in SwiftUI?](https://stackoverflow.com/a/73289182/521197) +* [How to scroll a Form to a specific UI element in SwiftUI](https://stackoverflow.com/a/65777080/521197) +* [Conditional modifier](https://designcode.io/swiftui-handbook-conditional-modifier) +* [How to Display Web Page Using WKWebView](https://www.appcoda.com/swiftui-wkwebview/) * [Document based app shows 2 back chevrons on iPad](https://stackoverflow.com/a/74245034/521197) -* [Perform a full swipe left action in UI Tests?](https://stackoverflow.com/a/51639973) -* [Get the current first responder without using a private API](https://stackoverflow.com/a/1823360/521197) -* [Split Picture in tiles and put in array](https://stackoverflow.com/a/73628496/521197) -* [Button border with corner radius in Swift UI](https://stackoverflow.com/a/62544642/521197) +* [Compressing and Decompressing Data with Buffer Compression](https://developer.apple.com/documentation/accelerate/compressing_and_decompressing_data_with_buffer_compression) * [How to detect device rotation](https://www.hackingwithswift.com/quick-start/swiftui/how-to-detect-device-rotation) -* [Customizing Toggle with ToggleStyle](https://www.hackingwithswift.com/quick-start/swiftui/customizing-toggle-with-togglestyle) -* [Get a binding from an environment value in SwiftUI](https://stackoverflow.com/q/69731360/521197) +* [How to convert a SwiftUI view to an image](https://www.hackingwithswift.com/quick-start/swiftui/how-to-convert-a-swiftui-view-to-an-image) +* [Button border with corner radius in Swift UI](https://stackoverflow.com/a/62544642/521197) +* [SwiftUI: Forcing an Update](https://stackoverflow.com/a/65095862/521197) +* [How can I add caching to AsyncImage](https://stackoverflow.com/a/70916651/521197) +* [Open-source themes for PlantUML diagrams](https://bschwarz.github.io/puml-themes/gallery.html) +* [iOS Localization and Internationalization Testing with XCUITest](https://medium.com/xcblog/ios-localization-and-internationalization-testing-with-xcuitest-495747a74775) * [How to percent encode a URL String](https://useyourloaf.com/blog/how-to-percent-encode-a-url-string/) * [Sccess TextEditor from XCUIApplication](https://stackoverflow.com/a/69522578/521197) -* [Compressing and Decompressing Data with Buffer Compression](https://developer.apple.com/documentation/accelerate/compressing_and_decompressing_data_with_buffer_compression) -* [Conditional modifier](https://designcode.io/swiftui-handbook-conditional-modifier) -* [How to Display Web Page Using WKWebView](https://www.appcoda.com/swiftui-wkwebview/) - [openai]: https://openai.com