Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: improve Defaults.Key #599

Merged
merged 23 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
82db8e1
refactor: replace const key with enum StoredKey
tisfeng Jun 8, 2024
27b588e
perf: remove unused code
tisfeng Jun 8, 2024
00318e7
refactor: improve Defaults.Key
tisfeng Jun 17, 2024
3b7e1dd
Merge branch 'dev' into refactor-stored-key
tisfeng Jun 24, 2024
c8bb781
refactor: improve TextEditorCell, use ServiceConfigurationPickerCell …
tisfeng Jun 25, 2024
6bf590b
perf: disable user to edit built-in supported models
tisfeng Jun 26, 2024
af08306
refactor: improve StreamConfigurationView, remove viewModel
tisfeng Jun 28, 2024
863cb5c
fix: setup subscribers when init, post update notification if model c…
tisfeng Jun 28, 2024
0af9a9f
perf: set defaultModels for OpenAI, Gemini and Built-in service
tisfeng Jun 30, 2024
18725e2
refactor: rename enum OpenAIModel and GeminiModel, update gpt3_5_turbo
tisfeng Jun 30, 2024
addfda3
fix: due to service memory leaks, multiple notifications are posted
tisfeng Jul 1, 2024
0a0e388
fix: if main window dealloc, we need to setup subscribers again
tisfeng Jul 2, 2024
c70e01c
fix: improve Gemini error message for empty model
tisfeng Jul 3, 2024
fcc1072
fix: replace validation viewModel @StateObject with @ObservedObject
tisfeng Jul 3, 2024
4f9f835
refactor: improve Gemini translate()
tisfeng Jul 3, 2024
998103d
fix: Gemini and Built-in service cannot validate
tisfeng Jul 3, 2024
48f58d4
fix: show different api key placeholders
tisfeng Jul 4, 2024
58eb633
fix: remove unused ObservableObject
tisfeng Jul 4, 2024
cabdad6
style: format code
tisfeng Jul 4, 2024
18f9592
chore: update SwiftFormat to 0.54
tisfeng Jul 4, 2024
9c9364a
style: replace override public with public override
tisfeng Jul 4, 2024
36e7c60
Merge branch 'dev' into refactor-defaults
tisfeng Jul 4, 2024
b2485c3
fix: validModels is empty even if defaultModels is set
tisfeng Jul 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .swiftformat
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ strongifiedSelf
--indent 4
--maxwidth 120
--typeattributes prev-line
--varattributes same-line
--storedvarattrs same-line
--voidtype tuple
--wraparguments before-first
--wrapparameters before-first
Expand All @@ -105,4 +105,7 @@ strongifiedSelf

# Following is by Lava

--ifdef no-indent
--ifdef no-indent

# Why doesn't this work?
--modifierorder public,override,
38 changes: 13 additions & 25 deletions Easydict.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

34 changes: 14 additions & 20 deletions Easydict/App/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@
}
}
},
"%@ API Key" : {
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "%@ API Key"
}
}
}
},
"about" : {
"comment" : "about",
"localizations" : {
Expand Down Expand Up @@ -2405,7 +2415,7 @@
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "完整接口地址"
"value" : "API 请求地址"
}
}
}
Expand Down Expand Up @@ -2442,22 +2452,6 @@
}
}
},
"service.configuration.gemini.api_key.placeholder" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "xxxxxxxxxxxxx"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "xxxxxxxxxxxxx"
}
}
}
},
"service.configuration.input.placeholder" : {
"localizations" : {
"en" : {
Expand Down Expand Up @@ -2543,13 +2537,13 @@
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "https://api.openai.com/v1/chat/completions"
"value" : "The full request URL, for example https://api.openai.com/v1/chat/completions"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "https://api.openai.com/v1/chat/completions"
"value" : "完整请求 URL,例如 https://api.openai.com/v1/chat/completions"
}
}
}
Expand All @@ -2565,7 +2559,7 @@
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "完整接口地址"
"value" : "API 请求地址"
}
}
}
Expand Down
149 changes: 20 additions & 129 deletions Easydict/Swift/Feature/Configuration/Configuration+Defaults.swift
Original file line number Diff line number Diff line change
Expand Up @@ -205,153 +205,44 @@ class ShortcutWrapper<T: KeyCombo> {
}
}

// Service Configuration
extension Defaults.Keys {
// OpenAI
static let openAIAPIKey = Key<String?>(apiStoredKey(.openAI)) // EZOpenAIAPIKey
static let openAITranslation = Key<String>(
translationStoredKey(.openAI),
default: "1"
)
static let openAIDictionary = Key<String>(
dictionaryStoredKey(.openAI),
default: "1"
)
static let openAISentence = Key<String>(
sentenceStoredKey(.openAI),
default: "1"
)
static let openAIServiceUsageStatus = Key<ServiceUsageStatus>(
serviceUsageStatusStoredKey(.openAI),
default: .default
)
static let openAIEndPoint = Key<String?>(endpointStoredKey(.openAI))
static let openAIModel = Key<String>(
modelStoredKey(.openAI),
default: OpenAIModel.gpt3_5_turbo.rawValue
)
static let openAIAvailableModels = Key<String?>(
availableModelsStoredKey(.openAI),
default: OpenAIModel.allCases.map { $0.rawValue }.joined(separator: ",")
)
static let openAIVaildModels = Key<Array>(
validModelsStoredKey(.openAI),
default: OpenAIModel.allCases.map { $0.rawValue }
)

// Custom OpenAI
static let customOpenAINameKey = Key<String?>(
nameStoredKey(.customOpenAI),
default: NSLocalizedString("custom_openai", comment: "")
)
static let customOpenAIAPIKey = Key<String?>(apiStoredKey(.customOpenAI))
static let customOpenAITranslation = Key<String>(
translationStoredKey(.customOpenAI),
default: "1"
)
static let customOpenAIDictionary = Key<String>(
dictionaryStoredKey(.customOpenAI),
default: "0"
)
static let customOpenAISentence = Key<String>(
sentenceStoredKey(.customOpenAI),
default: "0"
)
static let customOpenAIServiceUsageStatus = Key<ServiceUsageStatus>(
serviceUsageStatusStoredKey(.builtInAI),
default: .default
)
static let customOpenAIEndPoint = Key<String?>(endpointStoredKey(.customOpenAI))
static let customOpenAIModel = Key<String>(
modelStoredKey(.customOpenAI),
default: ""
)
static let customOpenAIAvailableModels = Key<String?>(
availableModelsStoredKey(.customOpenAI),
default: ""
)
static let customOpenAIVaildModels = Key<Array>(
validModelsStoredKey(.customOpenAI),
default: [""]
)

// Built-in AI
static let builtInAIModel = Key<String>(
modelStoredKey(.builtInAI),
default: ""
) // EZBuiltInAIModelKey
static let builtInAITranslation = Key<String>(
translationStoredKey(.builtInAI),
default: "1"
)
static let builtInAIDictionary = Key<String>(
dictionaryStoredKey(.builtInAI),
default: "0"
)
static let builtInAISentence = Key<String>(
sentenceStoredKey(.builtInAI),
default: "0"
)
static let builtInAIServiceUsageStatus = Key<ServiceUsageStatus>(
serviceUsageStatusStoredKey(.builtInAI),
default: .default
)
func defaultsKey<T>(_ key: StoredKey, serviceType: ServiceType) -> Defaults.Key<T?> {
defaultsKey(key, serviceType: serviceType, defaultValue: nil)
}

// Gemni
static let geminiAPIKey = Key<String?>(apiStoredKey(.gemini)) // EZGeminiAPIKey
static let geminiTranslation = Key<String>(
translationStoredKey(.gemini),
default: "1"
)
static let geminiDictionary = Key<String>(
dictionaryStoredKey(.gemini),
default: "1"
)
static let geminiSentence = Key<String>(
sentenceStoredKey(.gemini),
default: "1"
)
static let geminiServiceUsageStatus = Key<ServiceUsageStatus>(
serviceUsageStatusStoredKey(.gemini),
default: .default
)
static let geminiModel = Key<String>(
modelStoredKey(.gemini),
default: GeminiModel.gemini1_5_flash.rawValue
)
static let geminiAvailableModels = Key<String?>(
availableModelsStoredKey(.gemini),
default: GeminiModel.allCases.map { $0.rawValue }.joined(separator: ",")
)
static let geminiValidModels = Key<Array>(
validModelsStoredKey(.gemini),
default: GeminiModel.allCases.map { $0.rawValue }
func defaultsKey<T: _DefaultsSerializable>(_ key: StoredKey, serviceType: ServiceType, defaultValue: T) -> Defaults
.Key<T> {
Defaults.Key<T>(
storedKey(key, serviceType: serviceType),
default: defaultValue
)
}

// Service Configuration
extension Defaults.Keys {
// DeepL
static let deepLAuth = Key<String?>(EZDeepLAuthKey)
static let deepLAuth = Key<String>(EZDeepLAuthKey, default: "")
static let deepLTranslation = Key<DeepLAPIUsagePriority>(
EZDeepLTranslationAPIKey,
default: DeepLAPIUsagePriority.webFirst
)
static let deepLTranslateEndPointKey = Key<String?>(EZDeepLTranslateEndPointKey)
static let deepLTranslateEndPointKey = Key<String>(EZDeepLTranslateEndPointKey, default: "")

// Bing
static let bingCookieKey = Key<String?>(EZBingCookieKey)
static let bingCookieKey = Key<String>(EZBingCookieKey, default: "")

// niu
static let niuTransAPIKey = Key<String?>(EZNiuTransAPIKey)
static let niuTransAPIKey = Key<String>(EZNiuTransAPIKey, default: "")

// Caiyun
static let caiyunToken = Key<String?>(EZCaiyunToken)
static let caiyunToken = Key<String>(EZCaiyunToken, default: "")

// tencent
static let tencentSecretId = Key<String?>(EZTencentSecretId)
static let tencentSecretKey = Key<String?>(EZTencentSecretKey)
static let tencentSecretId = Key<String>(EZTencentSecretId, default: "")
static let tencentSecretKey = Key<String>(EZTencentSecretKey, default: "")

// Ali
static let aliAccessKeyId = Key<String?>(EZAliAccessKeyId)
static let aliAccessKeySecret = Key<String?>(EZAliAccessKeySecret)
static let aliAccessKeyId = Key<String>(EZAliAccessKeyId, default: "")
static let aliAccessKeySecret = Key<String>(EZAliAccessKeySecret, default: "")
}

/// shortcut
Expand Down
70 changes: 25 additions & 45 deletions Easydict/Swift/Feature/Configuration/DefaultsStoredKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,64 +8,44 @@

import Foundation

// TODO: refactor key with enum key type.
func storedKey(_ key: String, serviceType: ServiceType) -> String {
func storedKey(_ key: StoredKey, serviceType: ServiceType) -> String {
// This key should be compatible with existing OpenAI config keys
// EZOpenAIServiceUsageStatusKey
// EZOpenAIDictionaryKey
"EZ" + serviceType.rawValue + key + "Key"
}

func serviceUsageStatusStoredKey(_ serviceType: ServiceType) -> String {
storedKey(EZServiceUsageStatusKey, serviceType: serviceType)
}

func translationStoredKey(_ serviceType: ServiceType) -> String {
storedKey(EZTranslationKey, serviceType: serviceType)
}

func sentenceStoredKey(_ serviceType: ServiceType) -> String {
storedKey(EZSentenceKey, serviceType: serviceType)
}

func dictionaryStoredKey(_ serviceType: ServiceType) -> String {
storedKey(EZDictionaryKey, serviceType: serviceType)
}

func availableModelsStoredKey(_ serviceType: ServiceType) -> String {
storedKey(EZAvailableModelsKey, serviceType: serviceType)
}

func validModelsStoredKey(_ serviceType: ServiceType) -> String {
storedKey(EZValidModelsKey, serviceType: serviceType)
}

func modelStoredKey(_ serviceType: ServiceType) -> String {
storedKey(EZModelKey, serviceType: serviceType)
}

func apiStoredKey(_ serviceType: ServiceType) -> String {
storedKey(EZAPIKey, serviceType: serviceType)
}

func endpointStoredKey(_ serviceType: ServiceType) -> String {
storedKey(EZEndpointKey, serviceType: serviceType)
}

func nameStoredKey(_ serviceType: ServiceType) -> String {
storedKey(EZNameKey, serviceType: serviceType)
"EZ" + serviceType.rawValue + key.rawValue.capitalizeFirstLetter() + "Key"
phlpsong marked this conversation as resolved.
Show resolved Hide resolved
}

extension UserDefaults {
static func bool(forKey key: String, serviceType: ServiceType) -> Bool {
static func bool(forKey key: StoredKey, serviceType: ServiceType) -> Bool {
let key = storedKey(key, serviceType: serviceType)
let value = standard.bool(forKey: key)
return value
}

static func string(forKey key: String, serviceType: ServiceType) -> String? {
static func string(forKey key: StoredKey, serviceType: ServiceType) -> String? {
let key = storedKey(key, serviceType: serviceType)
let value = standard.string(forKey: key)
return value
}
}

// MARK: - StoredKey

enum StoredKey: String {
case serviceUsageStatus
case translation
case dictionary
case sentence
case supportedModels = "AvailableModels" // save in String: "gpt-3.5, gpt-4"
phlpsong marked this conversation as resolved.
Show resolved Hide resolved
case validModels // save in [String]
case model
case apiKey = "API"
case endpoint = "EndPoint"
case name
}

extension String {
func capitalizeFirstLetter() -> String {
prefix(1).uppercased() + dropFirst()
}
}
10 changes: 9 additions & 1 deletion Easydict/Swift/Model/ServiceUsageStatus.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ extension ServiceUsageStatus: EnumLocalizedStringConvertible {
}
}

// MARK: Defaults.Serializable
// MARK: - String + EnumLocalizedStringConvertible

extension String: EnumLocalizedStringConvertible {
var title: LocalizedStringKey {
LocalizedStringKey(self)
}
}

// MARK: - ServiceUsageStatus + Defaults.Serializable

extension ServiceUsageStatus: Defaults.Serializable {}
Loading