From 51b9c810f411dcee1c6bc733542d8270d613ed82 Mon Sep 17 00:00:00 2001 From: tisfeng Date: Fri, 19 Jan 2024 10:08:41 +0800 Subject: [PATCH 01/13] docs: update Longman dict link --- docs/How-to-use-macOS-system-dictionary-in-Easydict-en.md | 2 +- docs/How-to-use-macOS-system-dictionary-in-Easydict-zh.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/How-to-use-macOS-system-dictionary-in-Easydict-en.md b/docs/How-to-use-macOS-system-dictionary-in-Easydict-en.md index 42a3be4c6..9cfe6d240 100644 --- a/docs/How-to-use-macOS-system-dictionary-in-Easydict-en.md +++ b/docs/How-to-use-macOS-system-dictionary-in-Easydict-en.md @@ -43,7 +43,7 @@ Longman, Collins, and Oxford are three substantial yet outstanding dictionaries. | Concise English-Chinese dictionary | Chinese-English | [GitHub](https://github.com/skywind3000/ECDICT) | https://drive.google.com/file/d/1-RoulJykOmcADGRHSmUjX2SkwiyLTHP1/view?usp=sharing | | Youdao Words Analysis | Chinese-English | [freemdict](https://downloads.freemdict.com/%E5%B0%9A%E6%9C%AA%E6%95%B4%E7%90%86/%E5%85%B1%E4%BA%AB2020.5.11/qwjs/39_%E6%9C%89%E9%81%93%E8%AF%8D%E8%AF%AD%E8%BE%A8%E6%9E%90/) | https://drive.google.com/file/d/1-HGanRhQDRR0OSMLb19or07lPwn_R0cn/view?usp=sharing | | Great Cictionary | Chinese-English | [mdict](https://mdict.org/post/dacihai/) | https://drive.google.com/file/d/1-8cBLcuA_N4PAjIMn_-d03ELv4uVrmIr/view?usp=sharing | -| Longman Dictionary of Contemporary Advanced English | Chinese-English | [v2ex](https://www.v2ex.com/t/907272) | https://drive.google.com/file/d/1-7g-hDiwqAFtweL1qePKSRcGFJvruu97/view?usp=share_link | +| Longman Dictionary of Contemporary Advanced English | Chinese-English | [v2ex](https://www.v2ex.com/t/907272) | https://drive.google.com/file/d/1scunXbe2JppVuKxNvn2uOidTbAZpiktk/view?usp=drive_link | | Collins Advanced English-Chinese Dictionary | Chinese-English | [《柯林斯双解》for macOS](https://placeless.net/blog/macos-dictionaries) | https://drive.google.com/file/d/1-KQmILchx71L2rFqhIZMtusIcemIlM01/view?usp=share_link | | Oxford Advanced Learner's English-Chinese Dictionary (8th Edition) | Chinese-English | [Jianshu](https://www.jianshu.com/p/e279d4a979fa) | https://drive.google.com/file/d/1-N0kiXmfTHREcBtumAmNn4sUM5poyiC7/view?usp=share_link | | Oxford Advanced Learner's English-Chinese Dictionary (8) | Chinese-English | Source unknown, I modified the css myself | https://drive.google.com/file/d/1-SigzdPPjQlycPwBHICgQSUOHpR8mMf7/view?usp=share_link | diff --git a/docs/How-to-use-macOS-system-dictionary-in-Easydict-zh.md b/docs/How-to-use-macOS-system-dictionary-in-Easydict-zh.md index d990d6210..5faddb4c0 100644 --- a/docs/How-to-use-macOS-system-dictionary-in-Easydict-zh.md +++ b/docs/How-to-use-macOS-system-dictionary-in-Easydict-zh.md @@ -43,9 +43,9 @@ Easydict 自动支持词典 App 中系统自带的词典,如牛津英汉汉英 | 简明英汉字典 | 中英 | [GitHub](https://github.com/skywind3000/ECDICT) | https://drive.google.com/file/d/1-RoulJykOmcADGRHSmUjX2SkwiyLTHP1/view?usp=sharing | | 有道词语辨析 | 中英 | [freemdict](https://downloads.freemdict.com/%E5%B0%9A%E6%9C%AA%E6%95%B4%E7%90%86/%E5%85%B1%E4%BA%AB2020.5.11/qwjs/39_%E6%9C%89%E9%81%93%E8%AF%8D%E8%AF%AD%E8%BE%A8%E6%9E%90/) | https://drive.google.com/file/d/1-HGanRhQDRR0OSMLb19or07lPwn_R0cn/view?usp=sharing | | 大辞海 | 中文 | [mdict](https://mdict.org/post/dacihai/) | https://drive.google.com/file/d/1-8cBLcuA_N4PAjIMn_-d03ELv4uVrmIr/view?usp=sharing | -| 朗文当代高级英语辞典 | 中英 | [v2ex](https://www.v2ex.com/t/907272) | https://drive.google.com/file/d/1-7g-hDiwqAFtweL1qePKSRcGFJvruu97/view?usp=share_link | +| 朗文当代高级英语辞典 | 中英 | [v2ex](https://www.v2ex.com/t/907272) | https://drive.google.com/file/d/1scunXbe2JppVuKxNvn2uOidTbAZpiktk/view?usp=drive_link | | 柯林斯高阶英汉双解 | 中英 | [《柯林斯双解》for macOS](https://placeless.net/blog/macos-dictionaries) | https://drive.google.com/file/d/1-KQmILchx71L2rFqhIZMtusIcemIlM01/view?usp=share_link | -| 牛津高阶英汉双解词典(第8版) | 中英 | [简书](https://www.jianshu.com/p/e279d4a979fa) | https://drive.google.com/file/d/1-N0kiXmfTHREcBtumAmNn4sUM5poyiC7/view?usp=share_link | +| 牛津高阶英汉双解词典(第 8 版) | 中英 | [简书](https://www.jianshu.com/p/e279d4a979fa) | https://drive.google.com/file/d/1-N0kiXmfTHREcBtumAmNn4sUM5poyiC7/view?usp=share_link | | 牛津高阶英汉双解词典(8) | 中英 | 来源不详,我自己修改的 css | https://drive.google.com/file/d/1-SigzdPPjQlycPwBHICgQSUOHpR8mMf7/view?usp=share_link | ### 简明英汉字典 @@ -71,7 +71,7 @@ Easydict 自动支持词典 App 中系统自带的词典,如牛津英汉汉英 ![image-20231001184454574](https://raw.githubusercontent.com/tisfeng/ImageBed/main/uPic/image-20231001184454574-1696157094.png) -### 牛津高阶英汉双解词典(第8版) +### 牛津高阶英汉双解词典(第 8 版) ![image-20231001185812289](https://raw.githubusercontent.com/tisfeng/ImageBed/main/uPic/image-20231001185812289-1696157892.png) From 95ea1dba96ea83090bca03c933ed7c15714ef635 Mon Sep 17 00:00:00 2001 From: tisfeng Date: Fri, 19 Jan 2024 18:03:38 +0800 Subject: [PATCH 02/13] fix: do not check Beta class, since it is Bool in Swift --- Easydict/Feature/Configuration/EZConfiguration.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Easydict/Feature/Configuration/EZConfiguration.m b/Easydict/Feature/Configuration/EZConfiguration.m index 939744f59..b15c3184d 100644 --- a/Easydict/Feature/Configuration/EZConfiguration.m +++ b/Easydict/Feature/Configuration/EZConfiguration.m @@ -665,7 +665,7 @@ - (void)setBeta:(BOOL)beta { [NSUserDefaults mm_write:stringValue forKey:EZBetaFeatureKey]; } - (BOOL)isBeta { - NSString *stringValue = [NSUserDefaults mm_readString:EZBetaFeatureKey defaultValue:@"0"]; + NSString *stringValue = [NSUserDefaults mm_read:EZBetaFeatureKey]; BOOL isBeta = [stringValue boolValue]; return isBeta; } From 25b651c7513511aef0acc9d2fda75406d376ce8a Mon Sep 17 00:00:00 2001 From: Tisfeng Date: Sat, 20 Jan 2024 12:24:50 +0800 Subject: [PATCH 03/13] perf: adjust setting UI (#341) * perf: set all setting pages to the same * perf: disable zoom button in Settings --- .../NewApp/View/SettingView/SettingView.swift | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/Easydict/NewApp/View/SettingView/SettingView.swift b/Easydict/NewApp/View/SettingView/SettingView.swift index a7e27c991..c6446538c 100644 --- a/Easydict/NewApp/View/SettingView/SettingView.swift +++ b/Easydict/NewApp/View/SettingView/SettingView.swift @@ -51,15 +51,26 @@ struct SettingView: View { func resizeWindowFrame() { guard let window else { return } + + // Disable zoom button, ref: https://stackoverflow.com/a/66039864/8378840 + window.standardWindowButton(.zoomButton)?.isEnabled = false - let originalFrame = window.frame - let newSize = switch selection { - case .general, .privacy, .about: - CGSize(width: 500, height: 520) + // Keep the settings page windows all the same width to avoid strange animations. + let maxWidth = 650 + let height = switch selection { + case .general: + maxWidth case .service: - CGSize(width: 800, height: 520) + 500 + case .privacy: + 320 + case .about: + 450 } + let newSize = CGSize(width: maxWidth, height: height) + + let originalFrame = window.frame let newY = originalFrame.origin.y + originalFrame.size.height - newSize.height let newRect = NSRect(origin: CGPoint(x: originalFrame.origin.x, y: newY), size: newSize) From 1f6fdc27ce25060057d6b0aca71eb7719e521f24 Mon Sep 17 00:00:00 2001 From: phlpsong <103433299+phlpsong@users.noreply.github.com> Date: Sat, 20 Jan 2024 16:32:43 +0800 Subject: [PATCH 04/13] add disabled app list tab (#340) * feat: add disabled app tab * fix: refactor app list issues * fix: refactor disabled app tab * fix: remove list row bg color * fix: bundle application name issue * fix: update code for review comments * fix: update app item view model * fix: remove item view model * fix: refactor disable app item view * perf: adjust add & minus bg color * perf: add a border for list * perf: adjust custom color name * perf: show minus image color according to enable state * perf: adjust disabled tab UI * fix: add disabled title horizontal padding * fix: code refactor * fix: disabled environment * fix: disable issue --------- Co-authored-by: tisfeng --- Easydict.xcodeproj/project.pbxproj | 23 +- .../App/Assets.xcassets/Colors/Contents.json | 6 + .../add_minus_bg_color.colorset/Contents.json | 38 +++ .../list_border_color.colorset/Contents.json | 38 +++ .../Contents.json | 0 Easydict/App/Easydict-Bridging-Header.h | 1 + Easydict/App/Localizable.xcstrings | 20 ++ .../Utility/Swift/Bundle/Bundle+AppInfo.swift | 23 ++ .../NewApp/View/SettingView/SettingView.swift | 9 +- .../SettingView/Tabs/DisabledAppTab.swift | 231 ++++++++++++++++++ .../View/SettingView/Tabs/ServiceTab.swift | 2 +- 11 files changed, 385 insertions(+), 6 deletions(-) create mode 100644 Easydict/App/Assets.xcassets/Colors/Contents.json create mode 100644 Easydict/App/Assets.xcassets/Colors/add_minus_bg_color.colorset/Contents.json create mode 100644 Easydict/App/Assets.xcassets/Colors/list_border_color.colorset/Contents.json rename Easydict/App/Assets.xcassets/{service_cell_highlight.colorset => Colors/service_cell_highlight_color.colorset}/Contents.json (100%) create mode 100644 Easydict/Feature/Utility/Swift/Bundle/Bundle+AppInfo.swift create mode 100644 Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift diff --git a/Easydict.xcodeproj/project.pbxproj b/Easydict.xcodeproj/project.pbxproj index 9bb89217d..c1c23e80f 100644 --- a/Easydict.xcodeproj/project.pbxproj +++ b/Easydict.xcodeproj/project.pbxproj @@ -229,8 +229,10 @@ 03FD68BB2B1DC59600FD388E /* CryptoSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 03FD68BA2B1DC59600FD388E /* CryptoSwift */; }; 03FD68BE2B1E151A00FD388E /* String+EncryptAES.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03FD68BD2B1E151A00FD388E /* String+EncryptAES.swift */; }; 0A057D6D2B499A000025C51D /* ServiceTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A057D6C2B499A000025C51D /* ServiceTab.swift */; }; + 0A2A05A62B59757100EEA142 /* Bundle+AppInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A2A05A52B59757100EEA142 /* Bundle+AppInfo.swift */; }; 0A2BA9602B49A989002872A4 /* Binding+DidSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A2BA95F2B49A989002872A4 /* Binding+DidSet.swift */; }; 0A2BA9642B4A3CCD002872A4 /* Notification+Name.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A2BA9632B4A3CCD002872A4 /* Notification+Name.swift */; }; + 0A8685C82B552A590022534F /* DisabledAppTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A8685C72B552A590022534F /* DisabledAppTab.swift */; }; 0AC11B222B4D16A500F07198 /* WindowAccessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AC11B212B4D16A500F07198 /* WindowAccessor.swift */; }; 0AC11B242B4E46B300F07198 /* TapHandlerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AC11B232B4E46B300F07198 /* TapHandlerView.swift */; }; 17BCAEF72B0DFF9000A7D372 /* EZNiuTransTranslateResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 17BCAEF52B0DFF9000A7D372 /* EZNiuTransTranslateResponse.m */; }; @@ -704,8 +706,10 @@ 03FD68BD2B1E151A00FD388E /* String+EncryptAES.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+EncryptAES.swift"; sourceTree = ""; }; 06E15747A7BD34D510ADC6A8 /* Pods-Easydict.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Easydict.debug.xcconfig"; path = "Target Support Files/Pods-Easydict/Pods-Easydict.debug.xcconfig"; sourceTree = ""; }; 0A057D6C2B499A000025C51D /* ServiceTab.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceTab.swift; sourceTree = ""; }; + 0A2A05A52B59757100EEA142 /* Bundle+AppInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Bundle+AppInfo.swift"; sourceTree = ""; }; 0A2BA95F2B49A989002872A4 /* Binding+DidSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Binding+DidSet.swift"; sourceTree = ""; }; 0A2BA9632B4A3CCD002872A4 /* Notification+Name.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Notification+Name.swift"; sourceTree = ""; }; + 0A8685C72B552A590022534F /* DisabledAppTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisabledAppTab.swift; sourceTree = ""; }; 0AC11B212B4D16A500F07198 /* WindowAccessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowAccessor.swift; sourceTree = ""; }; 0AC11B232B4E46B300F07198 /* TapHandlerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TapHandlerView.swift; sourceTree = ""; }; 17BCAEF32B0DFF9000A7D372 /* EZNiuTransTranslateResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EZNiuTransTranslateResponse.h; sourceTree = ""; }; @@ -1821,6 +1825,7 @@ 03CF88602B137ECB0030C199 /* Swift */ = { isa = PBXGroup; children = ( + 0A2A05A42B59755F00EEA142 /* Bundle */, 0A2BA9622B4A3CBB002872A4 /* Notification */, 0A2BA95E2B49A967002872A4 /* Binding */, 03FD68BC2B1E14B500FD388E /* String */, @@ -2001,6 +2006,14 @@ path = String; sourceTree = ""; }; + 0A2A05A42B59755F00EEA142 /* Bundle */ = { + isa = PBXGroup; + children = ( + 0A2A05A52B59757100EEA142 /* Bundle+AppInfo.swift */, + ); + path = Bundle; + sourceTree = ""; + }; 0A2BA95E2B49A967002872A4 /* Binding */ = { isa = PBXGroup; children = ( @@ -2077,6 +2090,7 @@ EAED41EA2B54A4900005FE0A /* ServiceConfiguration */, 278540332B3DE04F004E9488 /* GeneralTab.swift */, 0A057D6C2B499A000025C51D /* ServiceTab.swift */, + 0A8685C72B552A590022534F /* DisabledAppTab.swift */, 276742042B3DC230002A2C75 /* PrivacyTab.swift */, 276742052B3DC230002A2C75 /* AboutTab.swift */, ); @@ -2320,7 +2334,7 @@ buildConfigurationList = C99EEB2C2385796900FEE666 /* Build configuration list for PBXNativeTarget "Easydict" */; buildPhases = ( 21D768ECC6D11E109E6EB73A /* [CP] Check Pods Manifest.lock */, - 03B04B582B2D4B8E00E30823 /* ShellScript */, + 03B04B582B2D4B8E00E30823 /* Run Script */, C99EEB142385796700FEE666 /* Sources */, C99EEB152385796700FEE666 /* Frameworks */, C99EEB162385796700FEE666 /* Resources */, @@ -2479,16 +2493,17 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 03B04B582B2D4B8E00E30823 /* ShellScript */ = { + 03B04B582B2D4B8E00E30823 /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; - buildActionMask = 2147483647; + buildActionMask = 12; files = ( ); inputFileListPaths = ( ); inputPaths = ( ); + name = "Run Script"; outputFileListPaths = ( ); outputPaths = ( @@ -2652,6 +2667,7 @@ 9672D7D22B4008B40023B8FB /* MASShortcutBinder+EZMASShortcutBinder.m in Sources */, 03BDA7BF2A26DA280079D04F /* NSScanner+EscapedScanning.m in Sources */, 03542A4C2937B5F100C34C33 /* EZYoudaoTranslate.m in Sources */, + 0A2A05A62B59757100EEA142 /* Bundle+AppInfo.swift in Sources */, 037852B329583F5200D0E2CF /* EZServiceCell.m in Sources */, 03247E362968158B00AFCD67 /* EZScriptExecutor.m in Sources */, 03882F8E29D95044005B5A52 /* ToastWindowController.m in Sources */, @@ -2691,6 +2707,7 @@ 17BCAEF82B0DFF9000A7D372 /* EZNiuTransTranslate.m in Sources */, 039F5506294B6E29004AB940 /* EZSettingViewController.m in Sources */, 03BD281E29481C0400F5891A /* EZAudioPlayer.m in Sources */, + 0A8685C82B552A590022534F /* DisabledAppTab.swift in Sources */, 03E02A2629250D1D00A10260 /* EZEventMonitor.m in Sources */, 03B0233429231FA6001C7E63 /* MMConsoleLogFormatter.m in Sources */, 037852B9295D49F900D0E2CF /* EZTableRowView.m in Sources */, diff --git a/Easydict/App/Assets.xcassets/Colors/Contents.json b/Easydict/App/Assets.xcassets/Colors/Contents.json new file mode 100644 index 000000000..73c00596a --- /dev/null +++ b/Easydict/App/Assets.xcassets/Colors/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Easydict/App/Assets.xcassets/Colors/add_minus_bg_color.colorset/Contents.json b/Easydict/App/Assets.xcassets/Colors/add_minus_bg_color.colorset/Contents.json new file mode 100644 index 000000000..a83dbf8e7 --- /dev/null +++ b/Easydict/App/Assets.xcassets/Colors/add_minus_bg_color.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xE9", + "green" : "0xE9", + "red" : "0xEA" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x3A", + "green" : "0x39", + "red" : "0x3B" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Easydict/App/Assets.xcassets/Colors/list_border_color.colorset/Contents.json b/Easydict/App/Assets.xcassets/Colors/list_border_color.colorset/Contents.json new file mode 100644 index 000000000..d60e3bb57 --- /dev/null +++ b/Easydict/App/Assets.xcassets/Colors/list_border_color.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xDE", + "green" : "0xDD", + "red" : "0xDE" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x50", + "green" : "0x50", + "red" : "0x50" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Easydict/App/Assets.xcassets/service_cell_highlight.colorset/Contents.json b/Easydict/App/Assets.xcassets/Colors/service_cell_highlight_color.colorset/Contents.json similarity index 100% rename from Easydict/App/Assets.xcassets/service_cell_highlight.colorset/Contents.json rename to Easydict/App/Assets.xcassets/Colors/service_cell_highlight_color.colorset/Contents.json diff --git a/Easydict/App/Easydict-Bridging-Header.h b/Easydict/App/Easydict-Bridging-Header.h index f98fcafec..06670f99e 100644 --- a/Easydict/App/Easydict-Bridging-Header.h +++ b/Easydict/App/Easydict-Bridging-Header.h @@ -21,6 +21,7 @@ #import "entry.h" #import "AppDelegate.h" #import "EZConfiguration.h" +#import "EZAppModel.h" #import "EZLocalStorage.h" #import "NSString+EZConvenience.h" diff --git a/Easydict/App/Localizable.xcstrings b/Easydict/App/Localizable.xcstrings index 2114e3a63..aacf0329e 100644 --- a/Easydict/App/Localizable.xcstrings +++ b/Easydict/App/Localizable.xcstrings @@ -1,6 +1,9 @@ { "sourceLanguage" : "en", "strings" : { + "" : { + + }, "about" : { "comment" : "about", "localizations" : { @@ -2415,6 +2418,23 @@ } } }, + "setting.disabled.import_app_error.message" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Unable to add Application" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无法添加应用" + } + } + } + }, "setting.general.advance.default_tts_service" : { "localizations" : { "en" : { diff --git a/Easydict/Feature/Utility/Swift/Bundle/Bundle+AppInfo.swift b/Easydict/Feature/Utility/Swift/Bundle/Bundle+AppInfo.swift new file mode 100644 index 000000000..c095084cb --- /dev/null +++ b/Easydict/Feature/Utility/Swift/Bundle/Bundle+AppInfo.swift @@ -0,0 +1,23 @@ +// +// Bundle+AppInfo.swift +// Easydict +// +// Created by phlpsong on 2024/1/18. +// Copyright © 2024 izual. All rights reserved. +// + +import Foundation + +extension Bundle { + var applicationName: String { + if let displayName: String = object(forInfoDictionaryKey: "CFBundleDisplayName") as? String { + return displayName + } else if let name: String = object(forInfoDictionaryKey: "CFBundleName") as? String { + return name + } + if let executableURL { + return executableURL.deletingLastPathComponent().lastPathComponent + } + return "" + } +} diff --git a/Easydict/NewApp/View/SettingView/SettingView.swift b/Easydict/NewApp/View/SettingView/SettingView.swift index c6446538c..f64f70efc 100644 --- a/Easydict/NewApp/View/SettingView/SettingView.swift +++ b/Easydict/NewApp/View/SettingView/SettingView.swift @@ -11,6 +11,7 @@ import SwiftUI enum SettingTab: Int { case general case service + case disabled case privacy case about } @@ -30,6 +31,10 @@ struct SettingView: View { .tabItem { Label("service", systemImage: "briefcase") } .tag(SettingTab.service) + DisabledAppTab() + .tabItem { Label("disabled_app_list", systemImage: "nosign") } + .tag(SettingTab.disabled) + PrivacyTab() .tabItem { Label("privacy", systemImage: "hand.raised.square") } .tag(SettingTab.privacy) @@ -51,7 +56,7 @@ struct SettingView: View { func resizeWindowFrame() { guard let window else { return } - + // Disable zoom button, ref: https://stackoverflow.com/a/66039864/8378840 window.standardWindowButton(.zoomButton)?.isEnabled = false @@ -60,7 +65,7 @@ struct SettingView: View { let height = switch selection { case .general: maxWidth - case .service: + case .service, .disabled: 500 case .privacy: 320 diff --git a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift new file mode 100644 index 000000000..a121652c7 --- /dev/null +++ b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift @@ -0,0 +1,231 @@ +// +// DisabledAppTab.swift +// Easydict +// +// Created by phlpsong on 2024/1/15. +// Copyright © 2024 izual. All rights reserved. +// + +import Combine +import SwiftUI + +private class DisabledAppViewModel: ObservableObject { + @Published var appModelList: [EZAppModel] = [] + @Published var selectedAppModels: Set = [] + @Published var isImporting = false + @Published var isShowImportErrorAlert = false + + init() { + fetchDisabledApps() + } + + func fetchDisabledApps() { + appModelList = EZLocalStorage.shared().selectTextTypeAppModelList + } + + func saveDisabledApps() { + EZLocalStorage.shared().selectTextTypeAppModelList = appModelList + } + + func removeDisabledApp() { + appModelList = appModelList.filter { !selectedAppModels.contains($0) } + saveDisabledApps() + selectedAppModels = [] + } + + func newAppURLsSelected(from urls: [URL]) { + urls.forEach { url in + let gotAccess = url.startAccessingSecurityScopedResource() + if !gotAccess { return } + appendNewDisabledApp(for: url) + url.stopAccessingSecurityScopedResource() + } + } + + func appendNewDisabledApp(for url: URL) { + guard let selectAppModel = disabledAppModel(from: url) else { return } + guard !appModelList.contains(selectAppModel) else { return } + appModelList.append(selectAppModel) + saveDisabledApps() + } + + func disabledAppModel(from url: URL) -> EZAppModel? { + let appModel = EZAppModel() + guard let bundle = Bundle(url: url) else { return nil } + appModel.appBundleID = bundle.bundleIdentifier ?? "" + appModel.triggerType = [] + return appModel + } +} + +@available(macOS 13.0, *) +struct DisabledAppTab: View { + @StateObject private var disabledAppViewModel = DisabledAppViewModel() + + var listToolbar: some View { + ListToolbar() + .fileImporter( + isPresented: $disabledAppViewModel.isImporting, + allowedContentTypes: [.application], + allowsMultipleSelection: true + ) { result in + switch result { + case let .success(urls): + disabledAppViewModel.newAppURLsSelected(from: urls) + case let .failure(error): + print("fileImporter error: \(error)") + disabledAppViewModel.isShowImportErrorAlert.toggle() + } + } + .alert(isPresented: $disabledAppViewModel.isShowImportErrorAlert) { + Alert(title: Text(""), message: Text("setting.disabled.import_app_error.message"), dismissButton: .default(Text("ok"))) + } + } + + var appListView: some View { + List(selection: $disabledAppViewModel.selectedAppModels) { + ForEach(disabledAppViewModel.appModelList, id: \.self) { app in + BlockAppItemView(with: app) + .tag(app) + } + .listRowSeparator(.hidden) + } + .listStyle(.plain) + .scrollIndicators(.never) + } + + var appListViewWithToolbar: some View { + VStack(spacing: 0) { + appListView + + listToolbar + } + .clipShape(RoundedRectangle(cornerRadius: 8)) + .overlay(content: { + RoundedRectangle(cornerRadius: 8) + .stroke(Color("list_border_color"), lineWidth: 0.5) + }) + .padding(.horizontal, 25) + .padding(.bottom, 25) + .onTapGesture { + disabledAppViewModel.selectedAppModels = [] + } + } + + var body: some View { + VStack { + Text("disabled_title") + .padding(.horizontal) + .padding(.top, 18) + .padding(.bottom, 8) + + appListViewWithToolbar + } + .environmentObject(disabledAppViewModel) + } +} + +@available(macOS 13.0, *) +private struct ListToolbar: View { + @EnvironmentObject private var disabledAppViewModel: DisabledAppViewModel + + var body: some View { + VStack(spacing: 0) { + Divider() + HStack(spacing: 0) { + ListButton(systemName: "plus") { + disabledAppViewModel.isImporting.toggle() + } + .disabled(false) + Divider() + .padding(.vertical, 1) + ListButton(systemName: "minus") { + disabledAppViewModel.removeDisabledApp() + } + .disabled(disabledAppViewModel.selectedAppModels.isEmpty) + Spacer() + } + .padding(2) + } + .frame(height: 28) + .background(Color("add_minus_bg_color")) + } +} + +@available(macOS 13.0, *) +private struct ListButton: View { + @Environment(\.isEnabled) private var isEnabled: Bool + var systemName: String + var action: () -> Void + + var body: some View { + Button(action: { + action() + }) { + Image(systemName: systemName) + .resizable() + .scaledToFit() + .frame(width: 10, height: 10) + .padding(.horizontal, 8) + .contentShape(Rectangle()) + .foregroundStyle(isEnabled ? Color(.secondaryLabelColor) : Color(.tertiaryLabelColor)) + .font(.system(size: 14, weight: .semibold)) + } + .buttonStyle(BorderlessButtonStyle()) + } +} + +@available(macOS 13.0, *) +private struct BlockAppItemView: View { + @EnvironmentObject var disabledAppViewModel: DisabledAppViewModel + + let appIcon: NSImage + let appName: String + + init(with appModel: EZAppModel) { + let appBundleId = appModel.appBundleID + let workspace = NSWorkspace.shared + let appURL = workspace.urlForApplication(withBundleIdentifier: appBundleId) + guard let appURL else { + appIcon = .init() + appName = "" + return + } + + let appPath = NSWorkspace.shared.urlForApplication(withBundleIdentifier: appBundleId) + guard let appPath else { + appIcon = .init() + appName = "" + return + } + appIcon = workspace.icon(forFile: appPath.path(percentEncoded: false)) + + guard let appBundle = Bundle(url: appURL) else { + appName = "" + return + } + appName = appBundle.applicationName + } + + var body: some View { + HStack(alignment: .center) { + Image(nsImage: appIcon) + .resizable() + .scaledToFit() + .frame(width: 24, height: 24) + + Text(appName) + + Spacer() + } + .frame(maxWidth: .infinity) + .contentShape(Rectangle()) + .padding(.vertical, 4) + .padding(.leading, 6) + } +} + +@available(macOS 13.0, *) +#Preview { + DisabledAppTab() +} diff --git a/Easydict/NewApp/View/SettingView/Tabs/ServiceTab.swift b/Easydict/NewApp/View/SettingView/Tabs/ServiceTab.swift index 5399f9af7..83a5f6398 100644 --- a/Easydict/NewApp/View/SettingView/Tabs/ServiceTab.swift +++ b/Easydict/NewApp/View/SettingView/Tabs/ServiceTab.swift @@ -172,7 +172,7 @@ private struct ServiceItemView: View { .listRowSeparator(.hidden) .listRowInsets(.init()) .padding(10) - .listRowBackground(viewModel.selectedService == service ? Color("service_cell_highlight") : tableColor) + .listRowBackground(viewModel.selectedService == service ? Color("service_cell_highlight_color") : tableColor) .overlay { TapHandler { viewModel.selectedService = service From 5384b39a05cad484b1f383d2a8668cf36220ae0e Mon Sep 17 00:00:00 2001 From: phlpsong <103433299+phlpsong@users.noreply.github.com> Date: Sun, 21 Jan 2024 09:37:12 +0800 Subject: [PATCH 05/13] fix: disable app list lag after add too many apps (#347) --- .../SettingView/Tabs/DisabledAppTab.swift | 58 ++++++++++--------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift index a121652c7..7d70402ff 100644 --- a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift +++ b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift @@ -179,42 +179,20 @@ private struct ListButton: View { private struct BlockAppItemView: View { @EnvironmentObject var disabledAppViewModel: DisabledAppViewModel - let appIcon: NSImage - let appName: String + @StateObject private var appItemViewModel: AppItemViewModel init(with appModel: EZAppModel) { - let appBundleId = appModel.appBundleID - let workspace = NSWorkspace.shared - let appURL = workspace.urlForApplication(withBundleIdentifier: appBundleId) - guard let appURL else { - appIcon = .init() - appName = "" - return - } - - let appPath = NSWorkspace.shared.urlForApplication(withBundleIdentifier: appBundleId) - guard let appPath else { - appIcon = .init() - appName = "" - return - } - appIcon = workspace.icon(forFile: appPath.path(percentEncoded: false)) - - guard let appBundle = Bundle(url: appURL) else { - appName = "" - return - } - appName = appBundle.applicationName + _appItemViewModel = StateObject(wrappedValue: AppItemViewModel(appModel: appModel)) } var body: some View { HStack(alignment: .center) { - Image(nsImage: appIcon) + Image(nsImage: appItemViewModel.appIcon) .resizable() .scaledToFit() .frame(width: 24, height: 24) - Text(appName) + Text(appItemViewModel.appName) Spacer() } @@ -225,6 +203,34 @@ private struct BlockAppItemView: View { } } +@available(macOS 13.0, *) +private class AppItemViewModel: ObservableObject { + @Published var appIcon = NSImage() + + @Published var appName = "" + + var appModel: EZAppModel + + init(appModel: EZAppModel) { + self.appModel = appModel + getAppBundleInfo() + } + + func getAppBundleInfo() { + let appBundleId = appModel.appBundleID + let workspace = NSWorkspace.shared + let appURL = workspace.urlForApplication(withBundleIdentifier: appBundleId) + guard let appURL else { return } + + let appPath = NSWorkspace.shared.urlForApplication(withBundleIdentifier: appBundleId) + guard let appPath else { return } + appIcon = workspace.icon(forFile: appPath.path(percentEncoded: false)) + + guard let appBundle = Bundle(url: appURL) else { return } + appName = appBundle.applicationName + } +} + @available(macOS 13.0, *) #Preview { DisabledAppTab() From 18ae512d90b684208d8a1235de49ad40ed467eab Mon Sep 17 00:00:00 2001 From: NeverAgain11 Date: Tue, 23 Jan 2024 17:08:43 +0800 Subject: [PATCH 06/13] [Refactor] rewrite EZConfiguration using Swift (#335) * rewrite EZConfiguration using swift * add nullable to the error in EZScriptExecutor * use DefaultsWrapper to replace Defaults * refactor EZConfiguration+EZUserData using swift * Remove the limitation to the defaultTTSServiceType * add missing quotation * Replace EZConfiguration with Configuration * fix: observe Configuration keys when init cause dead cycle * fixed Simultaneous accesses * make the rawValue of TTSServiceType equivalent to ServiceType * fix: updateDarkMode missing parameter * fix: key changes trigger the observer multi times * fixed Simultaneous accesses * fix input error service type * remove unused code * remove unused code Co-authored-by: Tisfeng * rename files * remove #import "EZConfiguration.h" from Easydict-Bridging-Header.h * Remove unnecessary code --------- Co-authored-by: tisfeng Co-authored-by: Lava <34743145+CanglongCl@users.noreply.github.com> --- Easydict.xcodeproj/project.pbxproj | 16 +- Easydict/App/AppDelegate+EZURLScheme.m | 6 +- Easydict/App/AppDelegate.m | 2 +- Easydict/App/Easydict-Bridging-Header.h | 7 +- .../Configuration+UserData.swift | 63 ++ .../Feature/Configuration/Configuration.swift | 701 ++++++++++++++++++ .../Feature/Configuration/EZConfiguration.m | 2 +- Easydict/Feature/DarkMode/DarkModeManager.h | 5 +- Easydict/Feature/DarkMode/DarkModeManager.m | 10 +- .../Feature/EventMonitor/EZEventMonitor.m | 11 +- .../EZDisableAutoSelectTextViewController.m | 5 +- .../PerferenceWindow/EZAboutViewController.m | 5 +- .../EZPrivacyViewController.m | 9 +- .../EZSettingViewController.m | 6 +- .../Feature/Service/Apple/EZAppleService.m | 3 +- .../Feature/Service/Apple/EZScriptExecutor.h | 8 +- .../Feature/Service/Apple/EZScriptExecutor.m | 2 +- .../Service/AudioPlayer/EZAudioPlayer.m | 3 +- .../Feature/Service/Baidu/EZBaiduTranslate.m | 6 +- Easydict/Feature/Service/Bing/EZBingService.m | 3 +- .../Service/Google/EZGoogleTranslate.m | 3 +- .../Service/Language/EZLanguageManager.m | 5 +- .../Feature/Service/Model/EZDetectManager.m | 7 +- .../Feature/Service/Model/EZQueryService.m | 3 +- .../OpenAI/EZOpenAIService+EZPromptMessages.m | 5 +- .../Feature/Service/OpenAI/EZOpenAIService.m | 4 +- .../Service/Youdao/EZYoudaoTranslate.m | 2 +- .../Feature/StatusItem/EZMenuItemManager.m | 6 +- .../AppleScript/EZAppleScriptManager.m | 3 +- .../Utility/EZLinkParser/EZSchemeParser.m | 15 +- Easydict/Feature/Utility/EZLog/EZLog.m | 2 +- .../Cell/EZSelectLanguageCell.m | 15 +- .../ViewController/Model/EZQueryModel.m | 7 +- .../EZQueryMenuTextView/EZQueryMenuTextView.m | 7 +- .../View/QueryView/EZQueryView.m | 4 +- .../ViewController/View/Titlebar/EZTitlebar.m | 7 +- .../View/WordResultView/EZWebViewManager.m | 3 +- .../View/WordResultView/EZWordResultView.m | 8 +- .../EZBaseQueryViewController.m | 14 +- .../Window/WindowManager/EZLayoutManager.m | 5 +- .../Window/WindowManager/EZWindowManager.m | 29 +- ...ion.swift => Configuration+Defaults.swift} | 78 +- Easydict/NewApp/Model/TTSServiceType.swift | 10 +- .../LanguageDetectOptimizeExtensions.swift | 8 +- .../View/SettingView/Tabs/GeneralTab.swift | 2 +- 45 files changed, 1000 insertions(+), 125 deletions(-) create mode 100644 Easydict/Feature/Configuration/Configuration+UserData.swift create mode 100644 Easydict/Feature/Configuration/Configuration.swift rename Easydict/NewApp/Configuration/{Configuration.swift => Configuration+Defaults.swift} (68%) diff --git a/Easydict.xcodeproj/project.pbxproj b/Easydict.xcodeproj/project.pbxproj index c1c23e80f..43ca6f7b7 100644 --- a/Easydict.xcodeproj/project.pbxproj +++ b/Easydict.xcodeproj/project.pbxproj @@ -265,9 +265,11 @@ C4DE3D6D2AC00EB500C2B85D /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = C4DE3D6C2AC00EB500C2B85D /* Localizable.xcstrings */; }; C98CAE75239F4619005F7DCA /* EasydictHelper.app in CopyFiles */ = {isa = PBXBuildFile; fileRef = C90BE309239F38EB00ADE88B /* EasydictHelper.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; DC3C643F2B187119008EEDD8 /* ChangeFontSizeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC3C643E2B187119008EEDD8 /* ChangeFontSizeView.swift */; }; + DC46DF802B4417B900DEAE3E /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC46DF7F2B4417B900DEAE3E /* Configuration.swift */; }; DC6D9C872B352EBC0055EFFC /* FontSizeHintView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC6D9C862B352EBC0055EFFC /* FontSizeHintView.swift */; }; DC6D9C892B3969510055EFFC /* Appearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC6D9C882B3969510055EFFC /* Appearance.swift */; }; - EA3B81F92B5254AA004C0E8B /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA3B81F82B5254AA004C0E8B /* Configuration.swift */; }; + DCF176F22B57CED700CA6026 /* Configuration+UserData.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCF176F12B57CED700CA6026 /* Configuration+UserData.swift */; }; + EA3B81F92B5254AA004C0E8B /* Configuration+Defaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA3B81F82B5254AA004C0E8B /* Configuration+Defaults.swift */; }; EA3B81FC2B52555C004C0E8B /* Defaults in Frameworks */ = {isa = PBXBuildFile; productRef = EA3B81FB2B52555C004C0E8B /* Defaults */; }; EA9943E32B534C3300EE7B97 /* TTSServiceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA9943E22B534C3300EE7B97 /* TTSServiceType.swift */; }; EA9943E82B534D8900EE7B97 /* LanguageDetectOptimizeExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA9943E72B534D8900EE7B97 /* LanguageDetectOptimizeExtensions.swift */; }; @@ -758,9 +760,11 @@ C90BE309239F38EB00ADE88B /* EasydictHelper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EasydictHelper.app; sourceTree = BUILT_PRODUCTS_DIR; }; C99EEB182385796700FEE666 /* Easydict-debug.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Easydict-debug.app"; sourceTree = BUILT_PRODUCTS_DIR; }; DC3C643E2B187119008EEDD8 /* ChangeFontSizeView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChangeFontSizeView.swift; sourceTree = ""; }; + DC46DF7F2B4417B900DEAE3E /* Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = ""; }; DC6D9C862B352EBC0055EFFC /* FontSizeHintView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontSizeHintView.swift; sourceTree = ""; }; DC6D9C882B3969510055EFFC /* Appearance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Appearance.swift; sourceTree = ""; }; - EA3B81F82B5254AA004C0E8B /* Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = ""; }; + DCF176F12B57CED700CA6026 /* Configuration+UserData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Configuration+UserData.swift"; sourceTree = ""; }; + EA3B81F82B5254AA004C0E8B /* Configuration+Defaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Configuration+Defaults.swift"; sourceTree = ""; }; EA9943E22B534C3300EE7B97 /* TTSServiceType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TTSServiceType.swift; sourceTree = ""; }; EA9943E72B534D8900EE7B97 /* LanguageDetectOptimizeExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LanguageDetectOptimizeExtensions.swift; sourceTree = ""; }; EA9943ED2B5353AB00EE7B97 /* WindowTypeExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowTypeExtensions.swift; sourceTree = ""; }; @@ -1298,6 +1302,8 @@ 03542A572937CC3200C34C33 /* EZConfiguration.m */, 03D8A65A2A433B4100D9A968 /* EZConfiguration+EZUserData.h */, 03D8A65B2A433B4100D9A968 /* EZConfiguration+EZUserData.m */, + DC46DF7F2B4417B900DEAE3E /* Configuration.swift */, + DCF176F12B57CED700CA6026 /* Configuration+UserData.swift */, DC6D9C882B3969510055EFFC /* Appearance.swift */, ); path = Configuration; @@ -2213,7 +2219,7 @@ EA3B81F72B52549B004C0E8B /* Configuration */ = { isa = PBXGroup; children = ( - EA3B81F82B5254AA004C0E8B /* Configuration.swift */, + EA3B81F82B5254AA004C0E8B /* Configuration+Defaults.swift */, ); path = Configuration; sourceTree = ""; @@ -2654,6 +2660,7 @@ 03FD68BE2B1E151A00FD388E /* String+EncryptAES.swift in Sources */, 03B0230729231FA6001C7E63 /* EZCommonView.m in Sources */, 03B0233329231FA6001C7E63 /* MMLog.m in Sources */, + DCF176F22B57CED700CA6026 /* Configuration+UserData.swift in Sources */, 0309E1F4292BD6A100AFB76A /* EZQueryModel.m in Sources */, 03BFFC7129612E10004E033E /* NSString+EZConvenience.m in Sources */, 03BDA7BD2A26DA280079D04F /* XPMArguments_Coalescer_Internal.m in Sources */, @@ -2728,7 +2735,7 @@ 03B0233229231FA6001C7E63 /* MMLog.swift in Sources */, 03DC7C5E2A3ABE28000BF7C9 /* EZConstKey.m in Sources */, 62E2BF4C2B4082BA00E42D38 /* AliTranslateType.swift in Sources */, - EA3B81F92B5254AA004C0E8B /* Configuration.swift in Sources */, + EA3B81F92B5254AA004C0E8B /* Configuration+Defaults.swift in Sources */, 03E3E7C22ADE318800812C84 /* EZQueryMenuTextView.m in Sources */, 03B0231829231FA6001C7E63 /* SnipWindowController.m in Sources */, 03542A342936F70F00C34C33 /* EZLanguageManager.m in Sources */, @@ -2821,6 +2828,7 @@ 6220AD5B2A82812300BBFB52 /* EZBingService.m in Sources */, 039F5508294B6E29004AB940 /* EZAboutViewController.m in Sources */, 03D8A6592A42A1A300D9A968 /* EZAppModel.m in Sources */, + DC46DF802B4417B900DEAE3E /* Configuration.swift in Sources */, 036E7D7B293F4FC8002675DF /* EZOpenLinkButton.m in Sources */, EAED41EC2B54AA920005FE0A /* ServiceConfigurationSection.swift in Sources */, 276742092B3DC230002A2C75 /* AboutTab.swift in Sources */, diff --git a/Easydict/App/AppDelegate+EZURLScheme.m b/Easydict/App/AppDelegate+EZURLScheme.m index eef2674c5..f3ce651bd 100644 --- a/Easydict/App/AppDelegate+EZURLScheme.m +++ b/Easydict/App/AppDelegate+EZURLScheme.m @@ -10,7 +10,7 @@ #import #import "EZWindowManager.h" #import "EZSchemeParser.h" -#import "EZConfiguration.h" +#import "Easydict-Swift.h" @implementation AppDelegate (EZURLScheme) @@ -70,8 +70,8 @@ - (void)registerRouters { - (void)showFloatingWindowAndAutoQueryText:(NSString *)text { EZWindowManager *windowManager = [EZWindowManager shared]; - EZWindowType windowType = EZConfiguration.shared.shortcutSelectTranslateWindowType; - + EZWindowType windowType = Configuration.shared.shortcutSelectTranslateWindowType; + [windowManager showFloatingWindowType:windowType queryText:text.trim autoQuery:YES diff --git a/Easydict/App/AppDelegate.m b/Easydict/App/AppDelegate.m index 8aa9e5f27..6e6efd49c 100644 --- a/Easydict/App/AppDelegate.m +++ b/Easydict/App/AppDelegate.m @@ -12,7 +12,6 @@ #import "MMCrash.h" #import "EZWindowManager.h" #import "EZLanguageManager.h" -#import "EZConfiguration.h" #import "EZLog.h" #import "EZSchemeParser.h" #import "AppDelegate+EZURLScheme.h" @@ -31,6 +30,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { // Capturing crash logs must be placed first. [MMCrash registerHandler]; + [EZLog setupCrashLogService]; [EZLog logAppInfo]; diff --git a/Easydict/App/Easydict-Bridging-Header.h b/Easydict/App/Easydict-Bridging-Header.h index 06670f99e..7bcde5af5 100644 --- a/Easydict/App/Easydict-Bridging-Header.h +++ b/Easydict/App/Easydict-Bridging-Header.h @@ -20,12 +20,15 @@ #import "entry.h" #import "AppDelegate.h" -#import "EZConfiguration.h" + #import "EZAppModel.h" #import "EZLocalStorage.h" #import "NSString+EZConvenience.h" #import "EZWindowManager.h" #import "NSViewController+EZWindow.h" - +#import "EZLog.h" +#import "EZLanguageManager.h" +#import "DarkModeManager.h" +#import "EZScriptExecutor.h" #import "EZOpenAIService.h" diff --git a/Easydict/Feature/Configuration/Configuration+UserData.swift b/Easydict/Feature/Configuration/Configuration+UserData.swift new file mode 100644 index 000000000..0b6784aac --- /dev/null +++ b/Easydict/Feature/Configuration/Configuration+UserData.swift @@ -0,0 +1,63 @@ +// +// Configuration+UserData.swift +// Easydict +// +// Created by ljk on 2024/1/17. +// Copyright © 2024 izual. All rights reserved. +// + +import Foundation + +extension Configuration { + var userDefaultsData: [String: Any] { + let userDefaults = UserDefaults.standard + + var userConfigDict = [String: Any]() + if let bundleIdentifier = Bundle.main.bundleIdentifier, let appUserDefaultsData = userDefaults.persistentDomain(forName: bundleIdentifier) { + for (key, value) in appUserDefaultsData { + if !key.hasPrefix("MASPreferences"), !(value is Data) { + userConfigDict[key] = value + } + } + } + + return userConfigDict + } + + func saveUserDefaultsDataToDownloadFolder() { + writeDictToDownloadFolder(userDefaultsData) + } + + func resetUserDefaultsData() { + guard let bundleIdentifier = Bundle.main.bundleIdentifier else { return } + UserDefaults.standard.removePersistentDomain(forName: bundleIdentifier) + } + + func writeDictToDownloadFolder(_ dict: [String: Any]) { + let downloadPath = downloadPath + let name = ProcessInfo.processInfo.processName + let date = currentDate + let fileName = "\(name)_\(date).plist" + let plistPath = (downloadPath as NSString?)?.appendingPathComponent(fileName) + guard let path = plistPath else { return } + + let plistData = try? PropertyListSerialization.data(fromPropertyList: dict, format: .binary, options: 0) + try? plistData?.write(to: URL(fileURLWithPath: path)) + } + + var downloadPath: String? { + NSSearchPathForDirectoriesInDomains(.downloadsDirectory, .userDomainMask, true).first + } + + var currentDate: String { + let currentDate = Date() + let formatter = DateFormatter() + formatter.dateStyle = .medium + formatter.timeStyle = .medium + + let formattedDate = formatter.string(from: currentDate) + print("Formatted Date: ", formattedDate) + + return formattedDate + } +} diff --git a/Easydict/Feature/Configuration/Configuration.swift b/Easydict/Feature/Configuration/Configuration.swift new file mode 100644 index 000000000..f888889c2 --- /dev/null +++ b/Easydict/Feature/Configuration/Configuration.swift @@ -0,0 +1,701 @@ +// +// Configuration.swift +// Easydict +// +// Created by ljk on 2024/1/2. +// Copyright © 2024 izual. All rights reserved. +// + +import Combine +import Defaults +import Foundation + +@objc enum LanguageDetectOptimize: Int { + case none = 0 + case baidu = 1 + case google = 2 +} + +let kEnableBetaNewAppKey = "EZConfiguration_kEnableBetaNewAppKey" +let kHideMenuBarIconKey = "EZConfiguration_kHideMenuBarIconKey" + +@objcMembers class Configuration: NSObject { + private(set) static var shared = Configuration() + + override private init() { + super.init() + DispatchQueue.main.async { [weak self] in + guard let self else { return } + observeKeys() + } + } + + var appDelegate = NSApp.delegate as? AppDelegate + + var updater: SPUUpdater? { + appDelegate?.updaterController.updater + } + + @DefaultsWrapper(.firstLanguage) + var firstLanguage: Language + + @DefaultsWrapper(.secondLanguage) + var secondLanguage: Language + + @DefaultsWrapper(.queryFromLanguage) + var fromLanguage: Language + + @DefaultsWrapper(.queryToLanguage) + var toLanguage: Language + + @DefaultsWrapper(.autoSelectText) + var autoSelectText: Bool + + @DefaultsWrapper(.forceAutoGetSelectedText) + var forceAutoGetSelectedText: Bool + + @DefaultsWrapper(.disableEmptyCopyBeep) + var disableEmptyCopyBeep: Bool // Some apps will beep when empty copy. + + @DefaultsWrapper(.clickQuery) + var clickQuery: Bool + + @DefaultsWrapper(.launchAtStartup) + var launchAtStartup: Bool + + var automaticallyChecksForUpdates: Bool { + get { + updater?.automaticallyChecksForUpdates ?? false + } + set { + updater?.automaticallyChecksForUpdates = newValue + logSettings(["automatically_checks_for_updates": newValue]) + } + } + + @DefaultsWrapper(.hideMainWindow) + var hideMainWindow: Bool + + @DefaultsWrapper(.autoQueryOCRText) + var autoQueryOCRText: Bool + + @DefaultsWrapper(.autoQuerySelectedText) + var autoQuerySelectedText: Bool + + @DefaultsWrapper(.autoQueryPastedText) + var autoQueryPastedText: Bool + + @DefaultsWrapper(.autoPlayAudio) + var autoPlayAudio: Bool + + @DefaultsWrapper(.autoCopySelectedText) + var autoCopySelectedText: Bool + + @DefaultsWrapper(.autoCopyOCRText) + var autoCopyOCRText: Bool + + @DefaultsWrapper(.autoCopyFirstTranslatedText) + var autoCopyFirstTranslatedText: Bool + + @DefaultsWrapper(.languageDetectOptimize) + var languageDetectOptimize: LanguageDetectOptimize + + var defaultTTSServiceType: ServiceType { + get { + ServiceType(rawValue: Defaults[.defaultTTSServiceType].rawValue) + } + set { + Defaults[.defaultTTSServiceType] = TTSServiceType(rawValue: newValue.rawValue) ?? .youdao + } + } + + @DefaultsWrapper(.showGoogleQuickLink) + var showGoogleQuickLink: Bool + + @DefaultsWrapper(.showEudicQuickLink) + var showEudicQuickLink: Bool + + @DefaultsWrapper(.showAppleDictionaryQuickLink) + var showAppleDictionaryQuickLink: Bool + + @DefaultsWrapper(.hideMenuBarIcon) + var hideMenuBarIcon: Bool + + @DefaultsWrapper(.enableBetaNewApp) + var enableBetaNewApp: Bool + + @DefaultsWrapper(.fixedWindowPosition) + var fixedWindowPosition: EZShowWindowPosition + + @DefaultsWrapper(.mouseSelectTranslateWindowType) + var mouseSelectTranslateWindowType: EZWindowType + + @DefaultsWrapper(.shortcutSelectTranslateWindowType) + var shortcutSelectTranslateWindowType: EZWindowType + + @DefaultsWrapper(.adjustPopButtonOrigin) + var adjustPopButtomOrigin: Bool + + @DefaultsWrapper(.allowCrashLog) + var allowCrashLog: Bool + + @DefaultsWrapper(.allowAnalytics) + var allowAnalytics: Bool + + @DefaultsWrapper(.clearInput) + var clearInput: Bool + + var disabledAutoSelect: Bool = false + + var isRecordingSelectTextShortcutKey: Bool = false + + let fontSizes: [CGFloat] = [1, 1.1, 1.2, 1.3, 1.4] + + var fontSizeRatio: CGFloat { + fontSizes[Int(fontSizeIndex)] + } + + @DefaultsWrapper(.fontSizeOptionIndex) + var fontSizeIndex: UInt + + @DefaultsWrapper(.appearanceType) + var appearance: AppearenceType + + @DefaultsWrapper(.enableBetaFeature) + private(set) var beta: Bool + + static func destroySharedInstance() { + shared = Configuration() + } + + private func observeKeys() { + cancellables.append( + Defaults.publisher(.firstLanguage) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetFirstLanguage() + } + ) + + cancellables.append( + Defaults.publisher(.secondLanguage) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetSecondLanguage() + } + ) + + cancellables.append( + Defaults.publisher(.autoSelectText) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetAutoSelectText() + } + ) + + cancellables.append( + Defaults.publisher(.forceAutoGetSelectedText) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetForceAutoGetSelectedText() + } + ) + + cancellables.append( + Defaults.publisher(.disableEmptyCopyBeep) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetDisableEmptyCopyBeep() + } + ) + + cancellables.append( + Defaults.publisher(.clickQuery) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetClickQuery() + } + ) + + cancellables.append( + Defaults.publisher(.launchAtStartup) + .removeDuplicates() + .sink { [weak self] change in + self?.didSetLaunchAtStartup(change.oldValue, new: change.newValue) + } + ) + + cancellables.append( + Defaults.publisher(.hideMainWindow) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetHideMainWindow() + } + ) + + cancellables.append( + Defaults.publisher(.autoQueryOCRText) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetAutoQueryOCRText() + } + ) + + cancellables.append( + Defaults.publisher(.autoQuerySelectedText) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetAutoQuerySelectedText() + } + ) + + cancellables.append( + Defaults.publisher(.autoQueryPastedText) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetAutoQueryPastedText() + } + ) + + cancellables.append( + Defaults.publisher(.autoPlayAudio) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetAutoPlayAudio() + } + ) + + cancellables.append( + Defaults.publisher(.autoCopySelectedText) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetAutoCopySelectedText() + } + ) + + cancellables.append( + Defaults.publisher(.autoCopyOCRText) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetAutoCopyOCRText() + } + ) + + cancellables.append( + Defaults.publisher(.autoCopyFirstTranslatedText) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetAutoCopyFirstTranslatedText() + } + ) + + cancellables.append( + Defaults.publisher(.languageDetectOptimize) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetLanguageDetectOptimize() + } + ) + + cancellables.append( + Defaults.publisher(.defaultTTSServiceType) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetDefaultTTSServiceType() + } + ) + + cancellables.append( + Defaults.publisher(.showGoogleQuickLink) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetShowGoogleQuickLink() + } + ) + + cancellables.append( + Defaults.publisher(.showEudicQuickLink) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetShowEudicQuickLink() + } + ) + + cancellables.append( + Defaults.publisher(.showAppleDictionaryQuickLink) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetShowAppleDictionaryQuickLink() + } + ) + + cancellables.append( + Defaults.publisher(.hideMenuBarIcon) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetHideMenuBarIcon() + } + ) + + cancellables.append( + Defaults.publisher(.enableBetaNewApp) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetEnableBetaNewApp() + } + ) + + cancellables.append( + Defaults.publisher(.fixedWindowPosition) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetFixedWindowPosition() + } + ) + + cancellables.append( + Defaults.publisher(.mouseSelectTranslateWindowType) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetMouseSelectTranslateWindowType() + } + ) + + cancellables.append( + Defaults.publisher(.shortcutSelectTranslateWindowType) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetShortcutSelectTranslateWindowType() + } + ) + + cancellables.append( + Defaults.publisher(.adjustPopButtonOrigin) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetAdjustPopButtomOrigin() + } + ) + + cancellables.append( + Defaults.publisher(.allowCrashLog) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetAllowCrashLog() + } + ) + + cancellables.append( + Defaults.publisher(.allowAnalytics) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetAllowAnalytics() + } + ) + + cancellables.append( + Defaults.publisher(.clearInput) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetClearInput() + } + ) + + cancellables.append( + Defaults.publisher(.fontSizeOptionIndex) + .removeDuplicates() + .sink { [weak self] _ in + self?.didSetFontSizeIndex() + } + ) + + cancellables.append( + Defaults.publisher(.appearanceType) + .removeDuplicates() + .sink { [weak self] change in + let newValue = change.newValue + + self?.didSetAppearance(newValue) + } + ) + } + + var cancellables: [AnyCancellable] = [] + + func enableBetaFeaturesIfNeeded() { + guard beta else { return } + } +} + +// MARK: setter + +private extension Configuration { + func didSetFirstLanguage() { + logSettings(["first_language": firstLanguage]) + } + + func didSetSecondLanguage() { + logSettings(["second_language": secondLanguage]) + } + + func didSetAutoSelectText() { + logSettings(["auto_select_sext": autoSelectText]) + } + + func didSetForceAutoGetSelectedText() { + logSettings(["force_get_selected_text": forceAutoGetSelectedText]) + } + + func didSetDisableEmptyCopyBeep() { + logSettings(["disableEmptyCopyBeep": disableEmptyCopyBeep]) + } + + func didSetClickQuery() { + EZWindowManager.shared().updatePopButtonQueryAction() + + logSettings(["click_query": clickQuery]) + } + + func didSetLaunchAtStartup(_ old: Bool, new: Bool) { + if new != old { + updateLoginItemWithLaunchAtStartup(new) + } + + logSettings(["launch_at_startup": new]) + } + + func didSetAutomaticallyChecksForUpdates() { + logSettings(["automatically_checks_for_updates": automaticallyChecksForUpdates]) + } + + func didSetHideMainWindow() { + let windowManger = EZWindowManager.shared() + windowManger.updatePopButtonQueryAction() + if hideMainWindow { + windowManger.closeMainWindowIfNeeded() + } + + logSettings(["hide_main_window": hideMainWindow]) + } + + func didSetAutoQueryOCRText() { + logSettings(["auto_query_ocr_text": autoQueryOCRText]) + } + + func didSetAutoQuerySelectedText() { + logSettings(["auto_query_selected_text": autoQuerySelectedText]) + } + + func didSetAutoQueryPastedText() { + logSettings(["auto_query_pasted_text": autoQueryPastedText]) + } + + func didSetAutoPlayAudio() { + logSettings(["auto_play_word_audio": autoPlayAudio]) + } + + func didSetAutoCopySelectedText() { + logSettings(["auto_copy_selected_text": autoCopySelectedText]) + } + + func didSetAutoCopyOCRText() { + logSettings(["auto_copy_ocr_text": autoCopyOCRText]) + } + + func didSetAutoCopyFirstTranslatedText() { + logSettings(["auto_copy_first_translated_text": autoCopyFirstTranslatedText]) + } + + func didSetLanguageDetectOptimize() { + logSettings(["detect_optimize": languageDetectOptimize]) + } + + func didSetDefaultTTSServiceType() { + let value = defaultTTSServiceType + logSettings(["tts": value]) + } + + func didSetShowGoogleQuickLink() { + postUpdateQuickLinkButtonNotification() + + EZMenuItemManager.shared().googleItem?.isHidden = !showGoogleQuickLink + + logSettings(["show_google_link": showGoogleQuickLink]) + } + + func didSetShowEudicQuickLink() { + postUpdateQuickLinkButtonNotification() + + EZMenuItemManager.shared().eudicItem?.isHidden = !showEudicQuickLink + + logSettings(["show_eudic_link": showEudicQuickLink]) + } + + func didSetShowAppleDictionaryQuickLink() { + postUpdateQuickLinkButtonNotification() + + EZMenuItemManager.shared().appleDictionaryItem?.isHidden = !showAppleDictionaryQuickLink + + logSettings(["show_apple_dictionary_link": showAppleDictionaryQuickLink]) + } + + func didSetHideMenuBarIcon() { + if !NewAppManager.shared.enable { + hideMenuBarIcon(hidden: hideMenuBarIcon) + } + + logSettings(["hide_menu_bar_icon": hideMenuBarIcon]) + } + + func didSetEnableBetaNewApp() { + logSettings(["enable_beta_new_app": enableBetaNewApp]) + } + + func didSetFixedWindowPosition() { + logSettings(["show_fixed_window_position": fixedWindowPosition]) + } + + func didSetMouseSelectTranslateWindowType() { + logSettings(["show_mouse_window_type": mouseSelectTranslateWindowType]) + } + + func didSetShortcutSelectTranslateWindowType() { + logSettings(["show_shortcut_window_type": shortcutSelectTranslateWindowType]) + } + + func didSetAdjustPopButtomOrigin() { + logSettings(["adjust_pop_buttom_origin": adjustPopButtomOrigin]) + } + + func didSetAllowCrashLog() { + EZLog.setCrashEnabled(allowCrashLog) + logSettings(["allow_crash_log": allowCrashLog]) + } + + func didSetAllowAnalytics() { + logSettings(["allow_analytics": allowAnalytics]) + } + + func didSetClearInput() { + logSettings(["clear_input": clearInput]) + } + + func didSetFontSizeIndex() { + NotificationCenter.default.post(name: .init(ChangeFontSizeView.changeFontSizeNotificationName), object: nil) + } + + func didSetAppearance(_ appearance: AppearenceType) { + DarkModeManager.sharedManager().updateDarkMode(appearance.rawValue) + } +} + +// MARK: Window Frame + +extension Configuration { + func windowFrameWithType(_ windowType: EZWindowType) -> CGRect { + Defaults[.windorFrame(for: windowType)] + } + + func setWindowFrame(_ frame: CGRect, windowType: EZWindowType) { + Defaults[.windorFrame(for: windowType)] = frame + } +} + +// MARK: Intelligent Query Text Type of Service + +extension Configuration { + func setIntelligentQueryTextType(_ queryTextType: EZQueryTextType, serviceType: ServiceType) { + Defaults[.intelligentQueryTextType(for: serviceType)] = queryTextType + } + + func intelligentQueryTextTypeForServiceType(_ serviceType: ServiceType) -> EZQueryTextType { + Defaults[.intelligentQueryTextType(for: serviceType)] + } +} + +// MARK: Intelligent Query Text Type of Service + +extension Configuration { + func setQueryTextType(_ queryTextType: EZQueryTextType, serviceType: ServiceType) { + Defaults[.queryTextType(for: serviceType)] = queryTextType + } + + func queryTextTypeForServiceType(_ serviceType: ServiceType) -> EZQueryTextType { + Defaults[.queryTextType(for: serviceType)] + } +} + +// MARK: Intelligent Query Mode + +extension Configuration { + func setIntelligentQueryMode(_ enabled: Bool, windowType: EZWindowType) { + let key = EZConstKey.constkey("IntelligentQueryMode", windowType: windowType) + let stringValue = "\(enabled)" + UserDefaults.standard.set(stringValue, forKey: key) + + let parameters = [ + "enabled": enabled, + "window_type": windowType.rawValue, + ] as [String: Any] + + EZLog.logEvent(withName: "intelligent_query_mode", parameters: parameters) + } + + func intelligentQueryModeForWindowType(_ windowType: EZWindowType) -> Bool { + let key = EZConstKey.constkey("IntelligentQueryMode", windowType: windowType) + let defaultValue = "0" + // Turn on intelligent query mode by default in mini window. + if windowType == .mini { + return true + } + return UserDefaults.standard.string(forKey: key) ?? defaultValue == "1" + } +} + +private extension Configuration { + func postUpdateQuickLinkButtonNotification() { + let notification = Notification(name: .init("EZQuickLinkButtonUpdateNotification"), object: nil) + NotificationCenter.default.post(notification) + } + + func hideMenuBarIcon(hidden: Bool) { + if hidden { + EZMenuItemManager.shared().remove() + } else { + EZMenuItemManager.shared().setup() + } + } + + func updateLoginItemWithLaunchAtStartup(_ launchAtStartup: Bool) { + let appName = Bundle.main.object(forInfoDictionaryKey: "CFBundleExecutable") as? String + let appBundlePath = Bundle.main.bundlePath + + let script = """ + tell application "System Events" to get the name of every login item + tell application "System Events" + set loginItems to every login item + repeat with aLoginItem in loginItems + if (aLoginItem's name is "\(appName ?? "")") then + delete aLoginItem + end if + end repeat + if \(launchAtStartup) then + make login item at end with properties {path:"\(appBundlePath)", hidden:false} + end if + end tell + """ + + let exeCommand = EZScriptExecutor() + exeCommand.runAppleScript(script) { result, error in + if let error { + MMLogInfo("launchAtStartup error: error: \(error)") + } else { + print("launchAtStartup result:", result) + } + } + } + + func logSettings(_ parameters: [String: Any]) { + EZLog.logEvent(withName: "settings", parameters: parameters) + } +} diff --git a/Easydict/Feature/Configuration/EZConfiguration.m b/Easydict/Feature/Configuration/EZConfiguration.m index b15c3184d..e1b40f69b 100644 --- a/Easydict/Feature/Configuration/EZConfiguration.m +++ b/Easydict/Feature/Configuration/EZConfiguration.m @@ -455,7 +455,7 @@ - (void)setAppearance:(EZAppearenceType)appearance { [NSUserDefaults mm_write:@(appearance) forKey:kApperanceKey]; - [[DarkModeManager manager] updateDarkMode]; + [[DarkModeManager manager] updateDarkMode:appearance]; } #pragma mark - Window Frame diff --git a/Easydict/Feature/DarkMode/DarkModeManager.h b/Easydict/Feature/DarkMode/DarkModeManager.h index 722bee8a3..446803e26 100644 --- a/Easydict/Feature/DarkMode/DarkModeManager.h +++ b/Easydict/Feature/DarkMode/DarkModeManager.h @@ -10,15 +10,14 @@ NS_ASSUME_NONNULL_BEGIN - @interface DarkModeManager : NSObject @property (nonatomic, assign, readonly) BOOL systemDarkMode; -+ (instancetype)manager; ++ (instancetype)manager NS_SWIFT_NAME(sharedManager()); - (void)excuteLight:(void (^)(void))light dark:(void (^)(void))dark; -- (void)updateDarkMode; +- (void)updateDarkMode:(NSInteger)apperance; @end diff --git a/Easydict/Feature/DarkMode/DarkModeManager.m b/Easydict/Feature/DarkMode/DarkModeManager.m index af749d661..7dcdf5e59 100644 --- a/Easydict/Feature/DarkMode/DarkModeManager.m +++ b/Easydict/Feature/DarkMode/DarkModeManager.m @@ -42,14 +42,18 @@ - (void)excuteLight:(void (^)(void))light dark:(void (^)(void))dark { - (void)monitor { NSString *const darkModeNotificationName = @"AppleInterfaceThemeChangedNotification"; - [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(updateDarkMode) name:darkModeNotificationName object:nil]; + [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(themeDidChange) name:darkModeNotificationName object:nil]; } -- (void)updateDarkMode { +- (void)themeDidChange { + [self updateDarkMode:Configuration.shared.appearance]; +} + +- (void)updateDarkMode:(NSInteger)apperance { BOOL isDarkMode = [self isDarkMode]; NSLog(@"%@", isDarkMode ? @"深色模式" : @"浅色模式"); - AppearenceType type = (AppearenceType)EZConfiguration.shared.appearance; + AppearenceType type = apperance; switch (type) { case AppearenceTypeDark: self.systemDarkMode = true; diff --git a/Easydict/Feature/EventMonitor/EZEventMonitor.m b/Easydict/Feature/EventMonitor/EZEventMonitor.m index 2578efd37..f3acfe5ab 100644 --- a/Easydict/Feature/EventMonitor/EZEventMonitor.m +++ b/Easydict/Feature/EventMonitor/EZEventMonitor.m @@ -17,6 +17,7 @@ #import "EZLocalStorage.h" #import "EZAppleScriptManager.h" #import "EZSystemUtility.h" +#import "Easydict-Swift.h" static CGFloat const kDismissPopButtonDelayTime = 0.1; static NSTimeInterval const kDelayGetSelectedTextTime = 0.1; @@ -300,7 +301,7 @@ - (void)getSelectedText:(BOOL)checkTextFrame completion:(void (^)(NSString *_Nul self.selectTextType = EZSelectTextTypeAccessibility; // Monitor CGEventTap must be required after using Accessibility successfully. - if (EZConfiguration.shared.autoSelectText) { + if (Configuration.shared.autoSelectText) { [self monitorCGEventTap]; } @@ -407,7 +408,7 @@ - (void)autoGetSelectedText:(BOOL)checkTextFrame { } - (BOOL)enabledAutoSelectText { - EZConfiguration *config = [EZConfiguration shared]; + Configuration *config = [Configuration shared]; BOOL enabled = config.autoSelectText && !config.disabledAutoSelect; if (!enabled) { NSLog(@"disabled autoSelectText"); @@ -437,7 +438,7 @@ - (void)getSelectedTextBySimulatedKey:(void (^)(NSString *_Nullable))completion // If playing audio, we do not silence system volume. [EZAudioUtils isPlayingAudio:^(BOOL isPlaying) { - BOOL shouldTurnOffSoundTemporarily = EZConfiguration.shared.disableEmptyCopyBeep && !isPlaying; + BOOL shouldTurnOffSoundTemporarily = Configuration.shared.disableEmptyCopyBeep && !isPlaying; // Set volume to 0 to avoid system alert. if (shouldTurnOffSoundTemporarily) { @@ -596,7 +597,7 @@ - (BOOL)isAccessibilityEnabled { /// Check if should use simulation key to get selected text. - (BOOL)shouldUseSimulatedKey:(NSString *)text error:(AXError)error { BOOL isAutoSelectQuery = self.actionType == EZActionTypeAutoSelectQuery; - BOOL allowedForceAutoGetSelectedText = [EZConfiguration.shared forceAutoGetSelectedText]; + BOOL allowedForceAutoGetSelectedText = [Configuration.shared forceAutoGetSelectedText]; NSString *easydictBundleID = [[NSBundle mainBundle] bundleIdentifier]; @@ -610,7 +611,7 @@ - (BOOL)shouldUseSimulatedKey:(NSString *)text error:(AXError)error { FIX: https://github.com/tisfeng/Easydict/issues/192#issuecomment-1797878909 */ - if (isInEasydict && EZConfiguration.shared.isRecordingSelectTextShortcutKey) { + if (isInEasydict && Configuration.shared.isRecordingSelectTextShortcutKey) { return NO; } diff --git a/Easydict/Feature/PerferenceWindow/DisableAutoSelectTextViewController/EZDisableAutoSelectTextViewController.m b/Easydict/Feature/PerferenceWindow/DisableAutoSelectTextViewController/EZDisableAutoSelectTextViewController.m index 477b392e3..86a5c8e56 100644 --- a/Easydict/Feature/PerferenceWindow/DisableAutoSelectTextViewController/EZDisableAutoSelectTextViewController.m +++ b/Easydict/Feature/PerferenceWindow/DisableAutoSelectTextViewController/EZDisableAutoSelectTextViewController.m @@ -16,6 +16,7 @@ #import "EZConfiguration.h" #import "NSImage+EZSymbolmage.h" #import "NSImage+EZResize.h" +#import "Easydict-Swift.h" static CGFloat const kMargin = 20; static CGFloat const kRowHeight = 45; @@ -254,7 +255,7 @@ - (void)selectApp { [openPanel setAllowedContentTypes:allowedTypes]; // ???: Since [auto select] will cause lag when dragging select apps, I don't know why 😰 - EZConfiguration.shared.disabledAutoSelect = YES; + Configuration.shared.disabledAutoSelect = YES; NSModalResponse result = [openPanel runModal]; if (result == NSModalResponseOK) { @@ -267,7 +268,7 @@ - (void)selectApp { [self.tableView reloadData]; } - EZConfiguration.shared.disabledAutoSelect = NO; + Configuration.shared.disabledAutoSelect = NO; } - (NSArray *)appModelsFromBundleIDDict:(NSDictionary *)appBundleIDDict { diff --git a/Easydict/Feature/PerferenceWindow/EZAboutViewController.m b/Easydict/Feature/PerferenceWindow/EZAboutViewController.m index 67fc4d277..9196c696a 100644 --- a/Easydict/Feature/PerferenceWindow/EZAboutViewController.m +++ b/Easydict/Feature/PerferenceWindow/EZAboutViewController.m @@ -10,6 +10,7 @@ #import "EZBlueTextButton.h" #import "EZConfiguration.h" #import "EZMenuItemManager.h" +#import "Easydict-Swift.h" @interface EZAboutViewController () @@ -35,7 +36,7 @@ - (void)viewDidLoad { [super viewDidLoad]; [self setupUI]; - self.autoCheckUpdateButton.mm_isOn = EZConfiguration.shared.automaticallyChecksForUpdates; + self.autoCheckUpdateButton.mm_isOn = Configuration.shared.automaticallyChecksForUpdates; [self updateViewSize]; @@ -177,7 +178,7 @@ - (void)updateViewConstraints { #pragma mark - Actions - (void)autoCheckUpdateButtonClicked:(NSButton *)sender { - EZConfiguration.shared.automaticallyChecksForUpdates = sender.mm_isOn; + Configuration.shared.automaticallyChecksForUpdates = sender.mm_isOn; } - (void)updateLatestVersion { diff --git a/Easydict/Feature/PerferenceWindow/EZPrivacyViewController.m b/Easydict/Feature/PerferenceWindow/EZPrivacyViewController.m index e5fc7ccd3..fb00a64e3 100644 --- a/Easydict/Feature/PerferenceWindow/EZPrivacyViewController.m +++ b/Easydict/Feature/PerferenceWindow/EZPrivacyViewController.m @@ -11,6 +11,7 @@ #import "EZConfiguration.h" #import "NSViewController+EZWindow.h" #import "NSImage+EZSymbolmage.h" +#import "Easydict-Swift.h" @interface EZPrivacyViewController () @@ -61,7 +62,7 @@ - (void)setupUI { action:@selector(analyticsButtonClicked:)]; [self.contentView addSubview:self.analyticsButton]; - EZConfiguration *configuration = [EZConfiguration shared]; + Configuration *configuration = [Configuration shared]; self.crashLogButton.mm_isOn = configuration.allowCrashLog; self.analyticsButton.mm_isOn = configuration.allowAnalytics; } @@ -120,16 +121,16 @@ - (void)crashLogButtonClicked:(NSButton *)sender { } else { sender.mm_isOn = YES; } - EZConfiguration.shared.allowCrashLog = sender.mm_isOn; + Configuration.shared.allowCrashLog = sender.mm_isOn; }]; } else { - EZConfiguration.shared.allowCrashLog = YES; + Configuration.shared.allowCrashLog = YES; } } - (void)analyticsButtonClicked:(NSButton *)sender { - EZConfiguration.shared.allowAnalytics = sender.mm_isOn; + Configuration.shared.allowAnalytics = sender.mm_isOn; } #pragma mark - MASPreferencesViewController diff --git a/Easydict/Feature/PerferenceWindow/EZSettingViewController.m b/Easydict/Feature/PerferenceWindow/EZSettingViewController.m index 528ab13e0..38d2aec42 100644 --- a/Easydict/Feature/PerferenceWindow/EZSettingViewController.m +++ b/Easydict/Feature/PerferenceWindow/EZSettingViewController.m @@ -17,7 +17,7 @@ @interface EZSettingViewController () -@property (nonatomic, strong) EZConfiguration *config; +@property (nonatomic, strong) Configuration *config; @property (nonatomic, strong) NSTextField *selectLabel; @property (nonatomic, strong) NSTextField *inputLabel; @@ -153,7 +153,7 @@ - (void)viewDidLoad { [super viewDidLoad]; // Do view setup here. - self.config = [EZConfiguration shared]; + self.config = [Configuration shared]; [self setupUI]; @@ -165,7 +165,7 @@ - (void)viewDidLoad { // Observe selectionShortcutView.recording status. [self.KVOController observe:self.selectionShortcutView keyPath:@"recording" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew block:^(EZSettingViewController *settingVC, MASShortcutView *selectionShortcutView, NSDictionary *_Nonnull change) { - EZConfiguration.shared.isRecordingSelectTextShortcutKey = [change[NSKeyValueChangeNewKey] boolValue]; + Configuration.shared.isRecordingSelectTextShortcutKey = [change[NSKeyValueChangeNewKey] boolValue]; }]; } diff --git a/Easydict/Feature/Service/Apple/EZAppleService.m b/Easydict/Feature/Service/Apple/EZAppleService.m index e2a4b567c..be76679f2 100644 --- a/Easydict/Feature/Service/Apple/EZAppleService.m +++ b/Easydict/Feature/Service/Apple/EZAppleService.m @@ -16,6 +16,7 @@ #import #import "NSString+EZUtils.h" #import "EZAppleDictionary.h" +#import "Easydict-Swift.h" static NSString *const kLineBreakText = @"\n"; static NSString *const kParagraphBreakText = @"\n\n"; @@ -607,7 +608,7 @@ - (NLLanguage)detectUnkownText:(NSString *)text { NLLanguage language = NLLanguageEnglish; // 729 if ([text isNumbers]) { - EZLanguage firstLanguage = EZConfiguration.shared.firstLanguage; + EZLanguage firstLanguage = Configuration.shared.firstLanguage; language = [self appleLanguageFromLanguageEnum:firstLanguage]; } diff --git a/Easydict/Feature/Service/Apple/EZScriptExecutor.h b/Easydict/Feature/Service/Apple/EZScriptExecutor.h index a0b6259df..8ad161b9f 100644 --- a/Easydict/Feature/Service/Apple/EZScriptExecutor.h +++ b/Easydict/Feature/Service/Apple/EZScriptExecutor.h @@ -17,17 +17,17 @@ typedef void(^AppleScriptCompletionHandler)( NSString *_Nullable result, EZError /// Run translate shortcut with parameters. - (NSTask *)runTranslateShortcut:(NSDictionary *)parameters - completionHandler:(void (^)(NSString *result, EZError *error))completionHandler; + completionHandler:(void (^)(NSString *result, EZError * _Nullable error))completionHandler; /// Run shortcut with parameters. - (NSTask *)runShortcut:(NSString *)shortcutName parameters:(NSDictionary *)parameters - completionHandler:(void (^)(NSString *result, EZError *error))completionHandler; + completionHandler:(void (^)(NSString *result, EZError * _Nullable error))completionHandler; /// Use NSTask to run AppleScript. -- (NSTask *)runAppleScriptWithTask:(NSString *)script completionHandler:(void (^)(NSString *result, EZError *error))completionHandler; +- (NSTask *)runAppleScriptWithTask:(NSString *)script completionHandler:(void (^)(NSString *result, EZError * _Nullable error))completionHandler; -- (void)runAppleScript:(NSString *)script completionHandler:(void (^)(NSString *result, EZError *error))completionHandler; +- (void)runAppleScript:(NSString *)script completionHandler:(void (^)(NSString *result, EZError * _Nullable error))completionHandler; @end diff --git a/Easydict/Feature/Service/Apple/EZScriptExecutor.m b/Easydict/Feature/Service/Apple/EZScriptExecutor.m index 51ff38453..702f0fb08 100644 --- a/Easydict/Feature/Service/Apple/EZScriptExecutor.m +++ b/Easydict/Feature/Service/Apple/EZScriptExecutor.m @@ -94,7 +94,7 @@ - (NSTask *)runAppleScriptWithTask:(NSString *)script completionHandler:(void (^ /// Use NSAppleScript to run AppleScript, faster than NSTask. /// !!!: Note that this method may fail due to execution permissions, it will not automatically apply for permissions when I test. -- (void)runAppleScript:(NSString *)script completionHandler:(void (^)(NSString *result, EZError *error))completionHandler { +- (void)runAppleScript:(NSString *)script completionHandler:(void (^)(NSString *result, EZError * _Nullable error))completionHandler { NSAppleScript *appleScript = [[NSAppleScript alloc] initWithSource:script]; CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ diff --git a/Easydict/Feature/Service/AudioPlayer/EZAudioPlayer.m b/Easydict/Feature/Service/AudioPlayer/EZAudioPlayer.m index 7ef68a030..ce07b3d7a 100644 --- a/Easydict/Feature/Service/AudioPlayer/EZAudioPlayer.m +++ b/Easydict/Feature/Service/AudioPlayer/EZAudioPlayer.m @@ -17,6 +17,7 @@ #import "EZServiceTypes.h" #import "EZConfiguration.h" #import +#import "Easydict-Swift.h" static NSString *const kFileExtendedAttributes = @"NSFileExtendedAttributes"; @@ -128,7 +129,7 @@ - (void)setIsPlaying:(BOOL)playing { // Note that user may change it when using, so we need to read it every time. - (EZQueryService *)defaultTTSService { - EZServiceType defaultTTSServiceType = EZConfiguration.shared.defaultTTSServiceType; + EZServiceType defaultTTSServiceType = Configuration.shared.defaultTTSServiceType; if (![_defaultTTSService.serviceType isEqualToString:defaultTTSServiceType]) { EZQueryService *defaultTTSService = [EZServiceTypes.shared serviceWithType:defaultTTSServiceType]; _defaultTTSService = defaultTTSService; diff --git a/Easydict/Feature/Service/Baidu/EZBaiduTranslate.m b/Easydict/Feature/Service/Baidu/EZBaiduTranslate.m index 5b6137076..726add2ad 100644 --- a/Easydict/Feature/Service/Baidu/EZBaiduTranslate.m +++ b/Easydict/Feature/Service/Baidu/EZBaiduTranslate.m @@ -13,6 +13,7 @@ #import "EZNetworkManager.h" #import "EZConfiguration.h" #import "NSString+EZRegex.h" +#import "Easydict-Swift.h" static NSString *const kBaiduTranslateURL = @"https://fanyi.baidu.com"; @@ -124,7 +125,8 @@ - (EZServiceType)serviceType { - (EZQueryTextType)queryTextType { EZQueryTextType defaultType = EZQueryTextTypeDictionary | EZQueryTextTypeSentence | EZQueryTextTypeTranslation; - EZQueryTextType type = [EZConfiguration.shared queryTextTypeForServiceType:self.serviceType]; + EZQueryTextType type = [Configuration.shared queryTextTypeForServiceType:self.serviceType]; + if (type == 0) { type = defaultType; } @@ -132,7 +134,7 @@ - (EZQueryTextType)queryTextType { } - (EZQueryTextType)intelligentQueryTextType { - EZQueryTextType type = [EZConfiguration.shared intelligentQueryTextTypeForServiceType:self.serviceType]; + EZQueryTextType type = [Configuration.shared intelligentQueryTextTypeForServiceType:self.serviceType]; return type; } diff --git a/Easydict/Feature/Service/Bing/EZBingService.m b/Easydict/Feature/Service/Bing/EZBingService.m index db282c86b..2b08d0ed1 100644 --- a/Easydict/Feature/Service/Bing/EZBingService.m +++ b/Easydict/Feature/Service/Bing/EZBingService.m @@ -12,6 +12,7 @@ #import "EZBingLookupModel.h" #import "EZConfiguration.h" #import "NSString+EZUtils.h" +#import "Easydict-Swift.h" @interface EZBingService () @property (nonatomic, strong) EZBingRequest *request; @@ -32,7 +33,7 @@ - (instancetype)init { #pragma mark - override - (EZQueryTextType)intelligentQueryTextType { - EZQueryTextType type = [EZConfiguration.shared intelligentQueryTextTypeForServiceType:self.serviceType]; + EZQueryTextType type = [Configuration.shared intelligentQueryTextTypeForServiceType:self.serviceType]; return type; } diff --git a/Easydict/Feature/Service/Google/EZGoogleTranslate.m b/Easydict/Feature/Service/Google/EZGoogleTranslate.m index 5c65d0e22..f2af0a9ae 100644 --- a/Easydict/Feature/Service/Google/EZGoogleTranslate.m +++ b/Easydict/Feature/Service/Google/EZGoogleTranslate.m @@ -11,6 +11,7 @@ #import #import "NSString+EZUtils.h" #import "EZConfiguration.h" +#import "Easydict-Swift.h" static NSString *const kGoogleTranslateURL = @"https://translate.google.com"; @@ -115,7 +116,7 @@ - (EZQueryTextType)queryTextType { } - (EZQueryTextType)intelligentQueryTextType { - EZQueryTextType type = [EZConfiguration.shared intelligentQueryTextTypeForServiceType:self.serviceType]; + EZQueryTextType type = [Configuration.shared intelligentQueryTextTypeForServiceType:self.serviceType]; return type; } diff --git a/Easydict/Feature/Service/Language/EZLanguageManager.m b/Easydict/Feature/Service/Language/EZLanguageManager.m index f2e430349..6650763d5 100644 --- a/Easydict/Feature/Service/Language/EZLanguageManager.m +++ b/Easydict/Feature/Service/Language/EZLanguageManager.m @@ -9,6 +9,7 @@ #import "EZLanguageManager.h" #import "EZAppleService.h" #import "EZConfiguration.h" +#import "Easydict-Swift.h" @interface EZLanguageManager () @@ -170,7 +171,7 @@ - (EZLanguage)systemSecondLanguage { } - (EZLanguage)userFirstLanguage { - EZLanguage firstLanguage = EZConfiguration.shared.firstLanguage; + EZLanguage firstLanguage = Configuration.shared.firstLanguage; if (!firstLanguage) { firstLanguage = [self systemPreferredTwoLanguages][0]; } @@ -178,7 +179,7 @@ - (EZLanguage)userFirstLanguage { } - (EZLanguage)userSecondLanguage { - EZLanguage secondLanguage = EZConfiguration.shared.secondLanguage; + EZLanguage secondLanguage = Configuration.shared.secondLanguage; if (!secondLanguage) { secondLanguage = [self systemPreferredTwoLanguages][1]; } diff --git a/Easydict/Feature/Service/Model/EZDetectManager.m b/Easydict/Feature/Service/Model/EZDetectManager.m index 40d6c9bff..a4c5575ee 100644 --- a/Easydict/Feature/Service/Model/EZDetectManager.m +++ b/Easydict/Feature/Service/Model/EZDetectManager.m @@ -12,6 +12,7 @@ #import "EZConfiguration.h" #import "EZYoudaoTranslate.h" #import "EZConfiguration+EZUserData.h" +#import "Easydict-Swift.h" @interface EZDetectManager () @@ -101,7 +102,7 @@ - (void)detectText:(NSString *)queryText completion:(void (^)(EZQueryModel *_Non [self.appleService detectText:queryText completion:^(EZLanguage appleDetectdedLanguage, NSError *_Nullable error) { NSMutableArray *preferredLanguages = [[EZLanguageManager.shared preferredLanguages] mutableCopy]; - EZLanguageDetectOptimize languageDetectOptimize = EZConfiguration.shared.languageDetectOptimize; + LanguageDetectOptimize languageDetectOptimize = Configuration.shared.languageDetectOptimize; // Add English and Chinese to the preferred language list, in general, sysytem detect English and Chinese is relatively accurate, so we don't need to use google or baidu to detect again. [preferredLanguages addObjectsFromArray:@[ @@ -111,7 +112,7 @@ - (void)detectText:(NSString *)queryText completion:(void (^)(EZQueryModel *_Non ]]; BOOL isPreferredLanguage = [preferredLanguages containsObject:appleDetectdedLanguage]; - if (isPreferredLanguage || languageDetectOptimize == EZLanguageDetectOptimizeNone) { + if (isPreferredLanguage || languageDetectOptimize == LanguageDetectOptimizeNone) { [self handleDetectedLanguage:appleDetectdedLanguage error:error completion:completion]; return; } @@ -237,7 +238,7 @@ - (void)handleOCRResult:(EZOCRResult *_Nullable)ocrResult error:(NSError *_Nulla Sometimes Apple OCR may fail, like Japanese text, but we have set Japanese as preferred language and OCR again when OCR result is empty, currently it seems work, but we do not guarantee it is always work in other languages. */ - if ([EZConfiguration.shared isBeta]) { + if (Configuration.shared.beta) { [self.youdaoService ocr:self.queryModel completion:^(EZOCRResult *_Nullable youdaoOCRResult, NSError *_Nullable youdaoOCRError) { if (!youdaoOCRError) { completion(youdaoOCRResult, nil); diff --git a/Easydict/Feature/Service/Model/EZQueryService.m b/Easydict/Feature/Service/Model/EZQueryService.m index b7cc43e1c..a2a5f7734 100644 --- a/Easydict/Feature/Service/Model/EZQueryService.m +++ b/Easydict/Feature/Service/Model/EZQueryService.m @@ -12,6 +12,7 @@ #import "NSString+EZChineseText.h" #import "NSString+EZUtils.h" #import "EZConfiguration.h" +#import "Easydict-Swift.h" #define MethodNotImplemented() \ @throw [NSException exceptionWithName:NSInternalInconsistencyException \ @@ -54,7 +55,7 @@ - (BOOL)enabledAutoQuery { return NO; } - if ([EZConfiguration.shared intelligentQueryModeForWindowType:self.windowType]) { + if ([Configuration.shared intelligentQueryModeForWindowType:self.windowType]) { // We usually don't want to lookup dictionary if text word > 1. EZQueryTextType queryType = [self.queryModel.queryText queryTypeWithLanguage:self.queryModel.queryFromLanguage maxWordCount:1]; if ((queryType & self.intelligentQueryTextType) != queryType) { diff --git a/Easydict/Feature/Service/OpenAI/EZOpenAIService+EZPromptMessages.m b/Easydict/Feature/Service/OpenAI/EZOpenAIService+EZPromptMessages.m index 2bfa712d6..2b32e8d74 100644 --- a/Easydict/Feature/Service/OpenAI/EZOpenAIService+EZPromptMessages.m +++ b/Easydict/Feature/Service/OpenAI/EZOpenAIService+EZPromptMessages.m @@ -9,6 +9,7 @@ #import "EZOpenAIService+EZPromptMessages.h" #import "EZConfiguration.h" #import "NSString+EZUtils.h" +#import "Easydict-Swift.h" // You are a faithful translation assistant that can only translate text and cannot interpret it, you can only return the translated text, do not show additional descriptions and annotations. @@ -84,7 +85,7 @@ - (NSArray *)translatioMessages:(NSString *)text from:(EZLanguage)sourceLanguage /// Sentence messages. - (NSArray *)sentenceMessages:(NSString *)sentence from:(EZLanguage)sourceLanguage to:(EZLanguage)targetLanguage { - NSString *answerLanguage = EZConfiguration.shared.firstLanguage; + NSString *answerLanguage = Configuration.shared.firstLanguage; self.result.to = answerLanguage; NSString *prompt = @""; @@ -274,7 +275,7 @@ - (NSArray *)translatioMessages:(NSString *)text from:(EZLanguage)sourceLanguage // V5. prompt NSString *prompt = @""; - NSString *answerLanguage = EZConfiguration.shared.firstLanguage; + NSString *answerLanguage = Configuration.shared.firstLanguage; self.result.to = answerLanguage; NSString *pronunciation = @"Pronunciation"; diff --git a/Easydict/Feature/Service/OpenAI/EZOpenAIService.m b/Easydict/Feature/Service/OpenAI/EZOpenAIService.m index 1123049e4..f97a0ea71 100644 --- a/Easydict/Feature/Service/OpenAI/EZOpenAIService.m +++ b/Easydict/Feature/Service/OpenAI/EZOpenAIService.m @@ -57,7 +57,7 @@ - (NSString *)apiKey { // easydict://writeKeyValue?EZOpenAIAPIKey= NSString *apiKey = [[NSUserDefaults standardUserDefaults] stringForKey:EZOpenAIAPIKey] ?: @""; - if (apiKey.length == 0 && EZConfiguration.shared.isBeta) { + if (apiKey.length == 0 && Configuration.shared.beta) { apiKey = self.defaultAPIKey; } return apiKey; @@ -135,7 +135,7 @@ - (EZQueryTextType)queryTextType { } - (EZQueryTextType)intelligentQueryTextType { - EZQueryTextType type = [EZConfiguration.shared intelligentQueryTextTypeForServiceType:self.serviceType]; + EZQueryTextType type = [Configuration.shared intelligentQueryTextTypeForServiceType:self.serviceType]; return type; } diff --git a/Easydict/Feature/Service/Youdao/EZYoudaoTranslate.m b/Easydict/Feature/Service/Youdao/EZYoudaoTranslate.m index 0df3d35b1..3c9f476b4 100644 --- a/Easydict/Feature/Service/Youdao/EZYoudaoTranslate.m +++ b/Easydict/Feature/Service/Youdao/EZYoudaoTranslate.m @@ -174,7 +174,7 @@ - (EZQueryTextType)queryTextType { } - (EZQueryTextType)intelligentQueryTextType { - EZQueryTextType type = [EZConfiguration.shared intelligentQueryTextTypeForServiceType:self.serviceType]; + EZQueryTextType type = [Configuration.shared intelligentQueryTextTypeForServiceType:self.serviceType]; return type; } diff --git a/Easydict/Feature/StatusItem/EZMenuItemManager.m b/Easydict/Feature/StatusItem/EZMenuItemManager.m index 1d47cb1d6..8d9f3b017 100644 --- a/Easydict/Feature/StatusItem/EZMenuItemManager.m +++ b/Easydict/Feature/StatusItem/EZMenuItemManager.m @@ -70,7 +70,7 @@ - (void)setup { if (self.statusItem) { return; } - if (EZConfiguration.shared.hideMenuBarIcon) { + if (Configuration.shared.hideMenuBarIcon) { return; } @@ -273,12 +273,12 @@ - (IBAction)appleDictionaryAction:(NSMenuItem *)sender { } - (IBAction)increaseFontSizeAction:(NSMenuItem *)sender { - EZConfiguration.shared.fontSizeIndex += 1; + Configuration.shared.fontSizeIndex += 1; } - (IBAction)decreaseFontSizeAction:(NSMenuItem *)sender { - EZConfiguration.shared.fontSizeIndex -= 1; + Configuration.shared.fontSizeIndex -= 1; } diff --git a/Easydict/Feature/Utility/AppleScript/EZAppleScriptManager.m b/Easydict/Feature/Utility/AppleScript/EZAppleScriptManager.m index a32fb0dda..6cf871203 100644 --- a/Easydict/Feature/Utility/AppleScript/EZAppleScriptManager.m +++ b/Easydict/Feature/Utility/AppleScript/EZAppleScriptManager.m @@ -8,6 +8,7 @@ #import "EZAppleScriptManager.h" #import "EZConfiguration.h" +#import "Easydict-Swift.h" @interface EZAppleScriptManager () @@ -225,7 +226,7 @@ - (void)checkApplicationSupportCopyAction:(NSString *)appBundleID completion:(vo NSString *edit; if (!appLanguage) { - appLanguage = EZConfiguration.shared.firstLanguage; + appLanguage = Configuration.shared.firstLanguage; } if ([appLanguage isEqualToString:EZLanguageEnglish]) { diff --git a/Easydict/Feature/Utility/EZLinkParser/EZSchemeParser.m b/Easydict/Feature/Utility/EZLinkParser/EZSchemeParser.m index cd8ba1630..6a7a25442 100644 --- a/Easydict/Feature/Utility/EZLinkParser/EZSchemeParser.m +++ b/Easydict/Feature/Utility/EZLinkParser/EZSchemeParser.m @@ -14,6 +14,7 @@ #import "EZConfiguration+EZUserData.h" #import "EZConfiguration.h" #import "EZLocalStorage.h" +#import "Easydict-Swift.h" @implementation EZSchemeParser @@ -110,14 +111,14 @@ - (BOOL)writeKeyValues:(NSDictionary *)keyValues { NSString *value = keyValues[key]; handled = [self enabledReadWriteKey:key]; if (handled) { - EZConfiguration *config = [EZConfiguration shared]; - BOOL isBeta = config.isBeta; + Configuration *config = [Configuration shared]; + BOOL isBeta = config.beta; [[NSUserDefaults standardUserDefaults] setObject:value forKey:key]; // If enabling beta feature, setup beta features. - if (!isBeta && config.isBeta) { - [EZConfiguration.shared enableBetaFeaturesIfNeeded]; + if (!isBeta && config.beta) { + [Configuration.shared enableBetaFeaturesIfNeeded]; } } } @@ -154,15 +155,15 @@ - (BOOL)enabledReadWriteKey:(NSString *)key { - (void)resetUserDefaultsData { // easydict://resetUserDefaultsData - [EZConfiguration.shared resetUserDefaultsData]; + [Configuration.shared resetUserDefaultsData]; [EZLocalStorage destroySharedInstance]; - [EZConfiguration destroySharedInstance]; + [Configuration destroySharedInstance]; } - (void)saveUserDefaultsDataToDownloadFolder { // easydict://saveUserDefaultsDataToDownloadFolder - [EZConfiguration.shared saveUserDefaultsDataToDownloadFolder]; + [Configuration.shared saveUserDefaultsDataToDownloadFolder]; } diff --git a/Easydict/Feature/Utility/EZLog/EZLog.m b/Easydict/Feature/Utility/EZLog/EZLog.m index 81ba2860b..c17f1e7b9 100644 --- a/Easydict/Feature/Utility/EZLog/EZLog.m +++ b/Easydict/Feature/Utility/EZLog/EZLog.m @@ -47,7 +47,7 @@ + (void)setCrashEnabled:(BOOL)enabled { + (void)logEventWithName:(NSString *)name parameters:(nullable NSDictionary *)dict { // NSLog(@"log event: %@, %@", name, dict); - if (![EZConfiguration.shared allowAnalytics]) { + if (![Configuration.shared allowAnalytics]) { return; } diff --git a/Easydict/Feature/ViewController/Cell/EZSelectLanguageCell.m b/Easydict/Feature/ViewController/Cell/EZSelectLanguageCell.m index bc993c1df..1be65ee65 100644 --- a/Easydict/Feature/ViewController/Cell/EZSelectLanguageCell.m +++ b/Easydict/Feature/ViewController/Cell/EZSelectLanguageCell.m @@ -11,6 +11,7 @@ #import "EZConfiguration.h" #import "NSColor+MyColors.h" #import "EZHoverButton.h" +#import "Easydict-Swift.h" @interface EZSelectLanguageCell () @@ -86,8 +87,8 @@ - (void)setup { mm_strongify(self); self.queryModel.userSourceLanguage = selectedLanguage; - if (![selectedLanguage isEqualToString:EZConfiguration.shared.from]) { - EZConfiguration.shared.from = selectedLanguage; + if (![selectedLanguage isEqualToString:Configuration.shared.fromLanguage]) { + Configuration.shared.fromLanguage = selectedLanguage; [self enterAction]; } }]; @@ -103,8 +104,8 @@ - (void)setup { mm_strongify(self); self.queryModel.userTargetLanguage = selectedLanguage; - if (![selectedLanguage isEqualToString:EZConfiguration.shared.to]) { - EZConfiguration.shared.to = selectedLanguage; + if (![selectedLanguage isEqualToString:Configuration.shared.toLanguage]) { + Configuration.shared.toLanguage = selectedLanguage; [self enterAction]; } }]; @@ -164,8 +165,8 @@ - (void)toggleTranslationLanguages { EZLanguage toLang = self.queryModel.userTargetLanguage; if (![fromLang isEqualToString:toLang]) { - EZConfiguration.shared.from = toLang; - EZConfiguration.shared.to = fromLang; + Configuration.shared.fromLanguage = toLang; + Configuration.shared.toLanguage = fromLang; [self.fromLanguageButton setSelectedLanguage:toLang]; [self.toLanguageButton setSelectedLanguage:fromLang]; @@ -181,7 +182,7 @@ - (void)enterAction { [self setNeedsUpdateConstraints:YES]; if (self.enterActionBlock) { - self.enterActionBlock(EZConfiguration.shared.from, EZConfiguration.shared.to); + self.enterActionBlock(Configuration.shared.fromLanguage, Configuration.shared.toLanguage); } } diff --git a/Easydict/Feature/ViewController/Model/EZQueryModel.m b/Easydict/Feature/ViewController/Model/EZQueryModel.m index c398ffd87..810385940 100644 --- a/Easydict/Feature/ViewController/Model/EZQueryModel.m +++ b/Easydict/Feature/ViewController/Model/EZQueryModel.m @@ -13,6 +13,7 @@ #import "NSString+EZSplit.h" #import "EZAppleDictionary.h" #import "NSString+EZHandleInputText.h" +#import "Easydict-Swift.h" @interface EZQueryModel () @@ -29,10 +30,10 @@ @implementation EZQueryModel - (instancetype)init { if (self = [super init]) { - [self.KVOController observe:EZConfiguration.shared keyPath:@"from" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew block:^(EZQueryModel *queryModel, EZConfiguration *config, NSDictionary *_Nonnull change) { + [self.KVOController observe:Configuration.shared keyPath:@"fromLanguage" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew block:^(EZQueryModel *queryModel, Configuration *config, NSDictionary *_Nonnull change) { queryModel.userSourceLanguage = change[NSKeyValueChangeNewKey]; }]; - [self.KVOController observe:EZConfiguration.shared keyPath:@"to" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew block:^(EZQueryModel *queryModel, EZConfiguration *config, NSDictionary *_Nonnull change) { + [self.KVOController observe:Configuration.shared keyPath:@"toLanguage" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew block:^(EZQueryModel *queryModel, Configuration *config, NSDictionary *_Nonnull change) { queryModel.userTargetLanguage = change[NSKeyValueChangeNewKey]; }]; @@ -198,7 +199,7 @@ - (NSString *)handleInputText:(NSString *)inputText { } } - if (EZConfiguration.shared.isBeta) { + if (Configuration.shared.beta) { // Remove prefix [//,#,*,] and join texts. queryText = [queryText removeCommentBlockSymbols]; } diff --git a/Easydict/Feature/ViewController/View/EZQueryMenuTextView/EZQueryMenuTextView.m b/Easydict/Feature/ViewController/View/EZQueryMenuTextView/EZQueryMenuTextView.m index 6a88cde89..ab46a8a8b 100644 --- a/Easydict/Feature/ViewController/View/EZQueryMenuTextView/EZQueryMenuTextView.m +++ b/Easydict/Feature/ViewController/View/EZQueryMenuTextView/EZQueryMenuTextView.m @@ -12,6 +12,7 @@ #import "EZCoordinateUtils.h" #import "EZLog.h" #import "NSString+EZUtils.h" +#import "Easydict-Swift.h" @interface EZQueryMenuTextView () @@ -54,10 +55,10 @@ - (void)queryInApp:(id)sender { EZWindowManager *windowManager = [EZWindowManager shared]; EZWindowType floatingWindowType = windowManager.floatingWindowType; - if (EZConfiguration.shared.mouseSelectTranslateWindowType == floatingWindowType) { - anotherWindowType = EZConfiguration.shared.shortcutSelectTranslateWindowType; + if (Configuration.shared.mouseSelectTranslateWindowType == floatingWindowType) { + anotherWindowType = Configuration.shared.shortcutSelectTranslateWindowType; } else { - anotherWindowType = EZConfiguration.shared.mouseSelectTranslateWindowType; + anotherWindowType = Configuration.shared.mouseSelectTranslateWindowType; } if (anotherWindowType != floatingWindowType) { diff --git a/Easydict/Feature/ViewController/View/QueryView/EZQueryView.m b/Easydict/Feature/ViewController/View/QueryView/EZQueryView.m index 964cd6483..a99a4d73a 100644 --- a/Easydict/Feature/ViewController/View/QueryView/EZQueryView.m +++ b/Easydict/Feature/ViewController/View/QueryView/EZQueryView.m @@ -74,7 +74,7 @@ - (void)setup { textView.delegate = self; textView.textStorage.delegate = self; textView.textContainerInset = CGSizeMake(6, 8); - textView.font = [NSFont systemFontOfSize:14 * EZConfiguration.shared.fontSizeRatio]; + textView.font = [NSFont systemFontOfSize:14 * Configuration.shared.fontSizeRatio]; mm_weakify(self); [textView setPasteTextBlock:^(NSString *_Nonnull text) { @@ -87,7 +87,7 @@ - (void)setup { [[NSNotificationCenter defaultCenter] addObserverForName:ChangeFontSizeView.changeFontSizeNotificationName object:nil queue:NSOperationQueue.mainQueue usingBlock:^(NSNotification * _Nonnull notification) { mm_strongify(self); - self.textView.font = [NSFont systemFontOfSize:14 * EZConfiguration.shared.fontSizeRatio]; + self.textView.font = [NSFont systemFontOfSize:14 * Configuration.shared.fontSizeRatio]; }]; // When programatically setting the text, like auto select text, or OCR text. diff --git a/Easydict/Feature/ViewController/View/Titlebar/EZTitlebar.m b/Easydict/Feature/ViewController/View/Titlebar/EZTitlebar.m index e6cb2d6e7..2b2c364aa 100644 --- a/Easydict/Feature/ViewController/View/Titlebar/EZTitlebar.m +++ b/Easydict/Feature/ViewController/View/Titlebar/EZTitlebar.m @@ -13,6 +13,7 @@ #import "NSObject+EZDarkMode.h" #import "EZBaseQueryWindow.h" #import "EZConfiguration.h" +#import "Easydict-Swift.h" @interface EZTitlebar () @@ -92,7 +93,7 @@ - (void)updateConstraints { // TODO: We should refactor it later. // Google - if (EZConfiguration.shared.showGoogleQuickLink) { + if (Configuration.shared.showGoogleQuickLink) { EZOpenLinkButton *googleButton = [[EZOpenLinkButton alloc] init]; [self addSubview:googleButton]; self.googleButton = googleButton; @@ -116,7 +117,7 @@ - (void)updateConstraints { } // Apple Dictionary - if (EZConfiguration.shared.showAppleDictionaryQuickLink) { + if (Configuration.shared.showAppleDictionaryQuickLink) { EZOpenLinkButton *appleDictButton = [[EZOpenLinkButton alloc] init]; [self addSubview:appleDictButton]; self.appleDictionaryButton = appleDictButton; @@ -140,7 +141,7 @@ - (void)updateConstraints { } // Eudic - if (EZConfiguration.shared.showEudicQuickLink) { + if (Configuration.shared.showEudicQuickLink) { EZOpenLinkButton *eudicButton = [[EZOpenLinkButton alloc] init]; // !!!: Note that some applications have multiple channel versions. Ref: https://github.com/tisfeng/Raycast-Easydict/issues/16 diff --git a/Easydict/Feature/ViewController/View/WordResultView/EZWebViewManager.m b/Easydict/Feature/ViewController/View/WordResultView/EZWebViewManager.m index aafe9b446..7c32f3634 100644 --- a/Easydict/Feature/ViewController/View/WordResultView/EZWebViewManager.m +++ b/Easydict/Feature/ViewController/View/WordResultView/EZWebViewManager.m @@ -8,6 +8,7 @@ #import "EZWebViewManager.h" #import "EZConfiguration.h" +#import "Easydict-Swift.h" static NSString *kObjcHandler = @"objcHandler"; static NSString *kMethod = @"method"; @@ -57,7 +58,7 @@ - (void)userContentController:(WKUserContentController *)userContentController d #pragma mark - WebView evaluateJavaScript - (void)updateAllIframe { - CGFloat fontSize = EZConfiguration.shared.fontSizeRatio; // 1.4 --> 140% + CGFloat fontSize = Configuration.shared.fontSizeRatio; // 1.4 --> 140% NSString *script = [NSString stringWithFormat:@"changeIframeBodyFontSize(%.1f); updateAllIframeStyle();", fontSize]; [self.webView evaluateJavaScript:script completionHandler:^(id _Nullable result, NSError *_Nullable error) { if (!error) { diff --git a/Easydict/Feature/ViewController/View/WordResultView/EZWordResultView.m b/Easydict/Feature/ViewController/View/WordResultView/EZWordResultView.m index 10268c06b..0bf1f2b72 100644 --- a/Easydict/Feature/ViewController/View/WordResultView/EZWordResultView.m +++ b/Easydict/Feature/ViewController/View/WordResultView/EZWordResultView.m @@ -58,7 +58,7 @@ - (instancetype)initWithFrame:(NSRect)frame { if (self) { self.wantsLayer = YES; self.layer.cornerRadius = EZCornerRadius_8; - self.fontSizeRatio = EZConfiguration.shared.fontSizeRatio; + self.fontSizeRatio = Configuration.shared.fontSizeRatio; [self.layer excuteLight:^(CALayer *layer) { layer.backgroundColor = [NSColor ez_resultViewBgLightColor].CGColor; } dark:^(CALayer *layer) { @@ -71,7 +71,7 @@ - (instancetype)initWithFrame:(NSRect)frame { // TODO: This method is too long, need to refactor. - (void)refreshWithResult:(EZQueryResult *)result { self.result = result; - self.fontSizeRatio = EZConfiguration.shared.fontSizeRatio; + self.fontSizeRatio = Configuration.shared.fontSizeRatio; EZTranslateWordResult *wordResult = result.wordResult; self.webView = result.webViewManager.webView; @@ -826,7 +826,7 @@ - (void)refreshWithResult:(EZQueryResult *)result { language = result.to; } - EZServiceType defaultTTSServiceType = EZConfiguration.shared.defaultTTSServiceType; + EZServiceType defaultTTSServiceType = Configuration.shared.defaultTTSServiceType; EZQueryService *defaultTTSService = [EZServiceTypes.shared serviceWithType:defaultTTSServiceType]; [result.service.audioPlayer playTextAudio:text @@ -1324,7 +1324,7 @@ - (void)getTextWithHref:(NSString *)href completionHandler:(void (^_Nullable)(NS } - (void)updateWebViewAllIframeFontSize { - CGFloat fontSize = EZConfiguration.shared.fontSizeRatio * 100; + CGFloat fontSize = Configuration.shared.fontSizeRatio * 100; NSString *jsCode = [NSString stringWithFormat: @"var iframes = document.querySelectorAll('iframe');" diff --git a/Easydict/Feature/ViewController/Window/BaseQueryWindow/EZBaseQueryViewController.m b/Easydict/Feature/ViewController/Window/BaseQueryWindow/EZBaseQueryViewController.m index 58d48a8a3..c1bb5cc13 100644 --- a/Easydict/Feature/ViewController/Window/BaseQueryWindow/EZBaseQueryViewController.m +++ b/Easydict/Feature/ViewController/Window/BaseQueryWindow/EZBaseQueryViewController.m @@ -192,7 +192,7 @@ - (void)setupServices { NSMutableArray *services = [NSMutableArray array]; self.youdaoService = nil; - EZServiceType defaultTTSServiceType = EZConfiguration.shared.defaultTTSServiceType; + EZServiceType defaultTTSServiceType = Configuration.shared.defaultTTSServiceType; NSArray *allServices = [EZLocalStorage.shared allServices:self.windowType]; for (EZQueryService *service in allServices) { @@ -352,7 +352,7 @@ - (NSString *)queryText { } - (EZQueryService *)defaultTTSService { - EZServiceType defaultTTSServiceType = EZConfiguration.shared.defaultTTSServiceType; + EZServiceType defaultTTSServiceType = Configuration.shared.defaultTTSServiceType; if (![_defaultTTSService.serviceType isEqualToString:defaultTTSServiceType]) { _defaultTTSService = [EZServiceTypes.shared serviceWithType:defaultTTSServiceType]; } @@ -480,7 +480,7 @@ - (void)startOCRImage:(NSImage *)image actionType:(EZActionType)actionType { return; } - if (EZConfiguration.shared.autoCopyOCRText) { + if (Configuration.shared.autoCopyOCRText) { [inputText copyToPasteboardSafely]; } @@ -493,7 +493,7 @@ - (void)startOCRImage:(NSImage *)image actionType:(EZActionType)actionType { return; } - BOOL autoSnipTranslate = EZConfiguration.shared.autoQueryOCRText; + BOOL autoSnipTranslate = Configuration.shared.autoQueryOCRText; if (autoSnipTranslate && queryModel.autoQuery) { [self startQueryText]; } @@ -1199,7 +1199,7 @@ - (EZQueryView *)createQueryView { [queryView setPasteTextBlock:^(NSString *_Nonnull text) { mm_strongify(self); [self detectQueryText:^(NSString *_Nonnull language) { - if ([EZConfiguration.shared autoQueryPastedText]) { + if ([Configuration.shared autoQueryPastedText]) { [self startQueryWithType:EZActionTypeInputQuery]; } }]; @@ -1484,7 +1484,7 @@ - (CGFloat)miniQueryViewHeight { #pragma mark - Auto play English word - (void)autoPlayEnglishWordAudio { - if (!EZConfiguration.shared.autoPlayAudio) { + if (!Configuration.shared.autoPlayAudio) { return; } @@ -1502,7 +1502,7 @@ - (void)autoPlayEnglishWordAudio { /// Auto copy translated text. - (void)autoCopyTranslatedTextOfService:(EZQueryService *)service { - if (![EZConfiguration.shared autoCopyFirstTranslatedText]) { + if (![Configuration.shared autoCopyFirstTranslatedText]) { service.autoCopyTranslatedTextBlock = nil; return; } diff --git a/Easydict/Feature/ViewController/Window/WindowManager/EZLayoutManager.m b/Easydict/Feature/ViewController/Window/WindowManager/EZLayoutManager.m index 0fecef8c3..3b8490d02 100644 --- a/Easydict/Feature/ViewController/Window/WindowManager/EZLayoutManager.m +++ b/Easydict/Feature/ViewController/Window/WindowManager/EZLayoutManager.m @@ -9,6 +9,7 @@ #import "EZLayoutManager.h" #import "EZBaseQueryWindow.h" #import "EZConfiguration.h" +#import "Easydict-Swift.h" @interface EZLayoutManager () @@ -46,7 +47,7 @@ - (void)commonInitialize { self.screen = NSScreen.mainScreen; self.minimumWindowSize = CGSizeMake(300, 70); - EZConfiguration *configuration = [EZConfiguration shared]; + Configuration *configuration = [Configuration shared]; self.miniWindowFrame = [configuration windowFrameWithType:EZWindowTypeMini]; if (CGRectEqualToRect(self.miniWindowFrame, CGRectZero)) { @@ -207,7 +208,7 @@ - (void)updateWindowFrame:(EZBaseQueryWindow *)window { break; } - [EZConfiguration.shared setWindowFrame:window.frame windowType:windowType]; + [Configuration.shared setWindowFrame:window.frame windowType:windowType]; } @end diff --git a/Easydict/Feature/ViewController/Window/WindowManager/EZWindowManager.m b/Easydict/Feature/ViewController/Window/WindowManager/EZWindowManager.m index 24204c5e4..dd2c18664 100644 --- a/Easydict/Feature/ViewController/Window/WindowManager/EZWindowManager.m +++ b/Easydict/Feature/ViewController/Window/WindowManager/EZWindowManager.m @@ -15,6 +15,7 @@ #import "EZPreferencesWindowController.h" #import "EZConfiguration.h" #import "EZLog.h" +#import "Easydict-Swift.h" @interface EZWindowManager () @@ -154,7 +155,7 @@ - (void)updatePopButtonQueryAction { mm_weakify(self); EZButton *popButton = self.popButtonWindow.popButton; - EZConfiguration *config = [EZConfiguration shared]; + Configuration *config = [Configuration shared]; if (config.hideMainWindow) { // FIXME: Click pop button will also show preferences window. @@ -182,7 +183,7 @@ - (void)updatePopButtonQueryAction { } - (void)popButtonWindowClicked { - EZWindowType windowType = EZConfiguration.shared.mouseSelectTranslateWindowType; + EZWindowType windowType = Configuration.shared.mouseSelectTranslateWindowType; self.actionType = EZActionTypeAutoSelectQuery; [self showFloatingWindowType:windowType queryText:self.selectedText]; [self->_popButtonWindow close]; @@ -291,7 +292,7 @@ - (void)showFloatingWindowType:(EZWindowType)windowType queryText:(nullable NSSt - (void)showFloatingWindowType:(EZWindowType)windowType queryText:(nullable NSString *)queryText actionType:(EZActionType)actionType { - BOOL autoQuery = [EZConfiguration.shared autoQuerySelectedText]; + BOOL autoQuery = [Configuration.shared autoQuerySelectedText]; [self showFloatingWindowType:windowType queryText:queryText autoQuery:autoQuery actionType:actionType]; } @@ -308,7 +309,7 @@ - (void)showFloatingWindowType:(EZWindowType)windowType actionType:(EZActionType)actionType atPoint:(CGPoint)point completionHandler:(nullable void (^)(void))completionHandler { - BOOL autoQuery = [EZConfiguration.shared autoQuerySelectedText]; + BOOL autoQuery = [Configuration.shared autoQuerySelectedText]; [self showFloatingWindowType:windowType queryText:queryText autoQuery:autoQuery actionType:actionType atPoint:point completionHandler:completionHandler]; } @@ -361,7 +362,7 @@ - (void)showFloatingWindowType:(EZWindowType)windowType } // TODO: Maybe we should remove this option, it seems useless. - if ([EZConfiguration.shared autoCopySelectedText]) { + if ([Configuration.shared autoCopySelectedText]) { [queryText copyToPasteboard]; } @@ -517,7 +518,7 @@ - (CGPoint)getPopButtonWindowLocation { // NSLog(@"start point: %@", NSStringFromPoint(startLocation)); // NSLog(@"end point: %@", NSStringFromPoint(endLocation)); - if (EZConfiguration.shared.adjustPopButtomOrigin) { + if (Configuration.shared.adjustPopButtomOrigin) { // Since the pop button may cover selected text, we need to move it to the left. CGFloat horizontalOffset = 20; @@ -539,7 +540,7 @@ - (CGPoint)getPopButtonWindowLocation { - (CGPoint)getMiniWindowLocation { CGPoint position = [self getShowingMouseLocation]; - if (EZConfiguration.shared.adjustPopButtomOrigin) { + if (Configuration.shared.adjustPopButtomOrigin) { position.y = position.y - 8; } @@ -587,7 +588,7 @@ - (CGPoint)getMouseLocation:(BOOL)offsetFlag { /// !!!: This return value is top-left point. - (CGPoint)getFixedWindowLocation { CGPoint position = CGPointZero; - EZShowWindowPosition windowPosition = EZConfiguration.shared.fixedWindowPosition; + EZShowWindowPosition windowPosition = Configuration.shared.fixedWindowPosition; switch (windowPosition) { case EZShowWindowPositionRight: { position = [self getFloatingWindowInRightSideOfScreenPoint:self.fixedWindow]; @@ -651,7 +652,7 @@ - (void)saveFrontmostApplication { } - (void)showMainWindowIfNedded { - BOOL showFlag = !EZConfiguration.shared.hideMainWindow; + BOOL showFlag = !Configuration.shared.hideMainWindow; NSApplicationActivationPolicy activationPolicy = showFlag ? NSApplicationActivationPolicyRegular : NSApplicationActivationPolicyAccessory; [NSApp setActivationPolicy:activationPolicy]; @@ -689,7 +690,7 @@ - (void)selectTextTranslate { return; } - EZWindowType windowType = EZConfiguration.shared.shortcutSelectTranslateWindowType; + EZWindowType windowType = Configuration.shared.shortcutSelectTranslateWindowType; NSLog(@"selectTextTranslate windowType: %@", @(windowType)); self.eventMonitor.actionType = EZActionTypeShortcutQuery; [self.eventMonitor getSelectedText:^(NSString *_Nullable text) { @@ -715,7 +716,7 @@ - (void)snipTranslate { } // Since ocr detect may be inaccurate, sometimes need to set sourceLanguage manually, so show Fixed window. - EZWindowType windowType = EZConfiguration.shared.shortcutSelectTranslateWindowType; + EZWindowType windowType = Configuration.shared.shortcutSelectTranslateWindowType; EZBaseQueryWindow *window = [self windowWithType:windowType]; // Wait to close floating window if need. @@ -755,7 +756,7 @@ - (void)inputTranslate { return; } - EZWindowType windowType = EZConfiguration.shared.shortcutSelectTranslateWindowType; + EZWindowType windowType = Configuration.shared.shortcutSelectTranslateWindowType; if (self.floatingWindowType == windowType) { [self closeFloatingWindow]; @@ -763,7 +764,7 @@ - (void)inputTranslate { } NSString *queryText = nil; - if ([EZConfiguration.shared clearInput]) { + if ([Configuration.shared clearInput]) { queryText = @""; } @@ -775,7 +776,7 @@ - (void)inputTranslate { - (void)showMiniFloatingWindow { MMLogInfo(@"showMiniFloatingWindow"); - EZWindowType windowType = EZConfiguration.shared.mouseSelectTranslateWindowType; + EZWindowType windowType = Configuration.shared.mouseSelectTranslateWindowType; if (self.floatingWindowType == windowType) { [self closeFloatingWindow]; diff --git a/Easydict/NewApp/Configuration/Configuration.swift b/Easydict/NewApp/Configuration/Configuration+Defaults.swift similarity index 68% rename from Easydict/NewApp/Configuration/Configuration.swift rename to Easydict/NewApp/Configuration/Configuration+Defaults.swift index 5777aa144..2cafce5ed 100644 --- a/Easydict/NewApp/Configuration/Configuration.swift +++ b/Easydict/NewApp/Configuration/Configuration+Defaults.swift @@ -1,5 +1,5 @@ // -// Configuration.swift +// Configuration+Defaults.swift // Easydict // // Created by 戴藏龙 on 2024/1/12. @@ -33,7 +33,7 @@ extension Defaults.Keys { static let autoCopyOCRText = Key("EZConfiguration_kAutoCopyOCRTextKey", default: false) static let autoCopySelectedText = Key("EZConfiguration_kAutoCopySelectedTextKey", default: false) static let autoCopyFirstTranslatedText = Key("EZConfiguration_kAutoCopyFirstTranslatedTextKey", default: false) - static let languageDetectOptimize = Key("EZConfiguration_kLanguageDetectOptimizeTypeKey", default: EZLanguageDetectOptimize.none) + static let languageDetectOptimize = Key("EZConfiguration_kLanguageDetectOptimizeTypeKey", default: LanguageDetectOptimize.none) static let defaultTTSServiceType = Key("EZConfiguration_kDefaultTTSServiceTypeKey", default: TTSServiceType.youdao) static let showGoogleQuickLink = Key("EZConfiguration_kShowGoogleLinkKey", default: true) static let showEudicQuickLink = Key("EZConfiguration_kShowEudicLinkKey", default: true) @@ -54,6 +54,80 @@ extension Defaults.Keys { static let fontSizeOptionIndex = Key("EZConfiguration_kTranslationControllerFontKey", default: 0) } +extension Defaults.Keys { + static func intelligentQueryTextType(for serviceType: ServiceType) -> Key { + let key = EZConstKey.constkey("IntelligentQueryTextType", serviceType: serviceType) + return .init(key, default: EZQueryTextType(rawValue: 7)) + } + + static func queryTextType(for serviceType: ServiceType) -> Key { + let key = EZConstKey.constkey("QueryTextType", serviceType: serviceType) + return .init(key, default: EZQueryTextType(rawValue: 0)) + } + + static func windorFrame(for windowType: EZWindowType) -> Key { + let key = "EZConfiguration_kWindowFrameKey_\(windowType)" + return .init(key, default: .zero) + } +} + +extension EZQueryTextType: Defaults.Serializable { + public static var bridge: Bridge = .init() + + public struct Bridge: Defaults.Bridge { + public func serialize(_ value: EZQueryTextType?) -> String? { + guard let value else { return "7" } + return "\(value.rawValue)" + } + + public func deserialize(_ object: String?) -> EZQueryTextType? { + guard let object else { return nil } + return EZQueryTextType(rawValue: UInt(object) ?? 7) + } + + public typealias Value = EZQueryTextType + + public typealias Serializable = String + } +} + +extension CGRect: Defaults.Serializable { + public static var bridge: Bridge = .init() + + public struct Bridge: Defaults.Bridge { + public func serialize(_ value: CGRect?) -> String? { + let value = value ?? .zero + return NSStringFromRect(value) + } + + public func deserialize(_ object: String?) -> CGRect? { + guard let object else { return nil } + return NSRectFromString(object) + } + + public typealias Value = CGRect + + public typealias Serializable = String + } +} + +@propertyWrapper +class DefaultsWrapper { + var wrappedValue: T { + get { + Defaults[key] + } set { + Defaults[key] = newValue + } + } + + init(_ key: Defaults.Key) { + self.key = key + } + + let key: Defaults.Key +} + // Service Configuration extension Defaults.Keys { // OPENAI diff --git a/Easydict/NewApp/Model/TTSServiceType.swift b/Easydict/NewApp/Model/TTSServiceType.swift index c28ef5938..a32efbe17 100644 --- a/Easydict/NewApp/Model/TTSServiceType.swift +++ b/Easydict/NewApp/Model/TTSServiceType.swift @@ -10,11 +10,11 @@ import Defaults import Foundation enum TTSServiceType: String, CaseIterable { - case youdao - case bing - case google - case baidu - case apple + case youdao = "Youdao" + case bing = "Bing" + case google = "Google" + case baidu = "Baidu" + case apple = "Apple" } @available(macOS 13, *) diff --git a/Easydict/NewApp/Utility/Extensions/LanguageDetectOptimizeExtensions.swift b/Easydict/NewApp/Utility/Extensions/LanguageDetectOptimizeExtensions.swift index 82ec281a1..2da99bad1 100644 --- a/Easydict/NewApp/Utility/Extensions/LanguageDetectOptimizeExtensions.swift +++ b/Easydict/NewApp/Utility/Extensions/LanguageDetectOptimizeExtensions.swift @@ -9,14 +9,14 @@ import Defaults import Foundation -extension EZLanguageDetectOptimize: Defaults.Serializable {} +extension LanguageDetectOptimize: Defaults.Serializable {} -extension EZLanguageDetectOptimize: CaseIterable { - public static let allCases: [EZLanguageDetectOptimize] = [.none, .baidu, .google] +extension LanguageDetectOptimize: CaseIterable { + public static let allCases: [LanguageDetectOptimize] = [.none, .baidu, .google] } @available(macOS 13, *) -extension EZLanguageDetectOptimize: CustomLocalizedStringResourceConvertible { +extension LanguageDetectOptimize: CustomLocalizedStringResourceConvertible { public var localizedStringResource: LocalizedStringResource { switch self { case .none: diff --git a/Easydict/NewApp/View/SettingView/Tabs/GeneralTab.swift b/Easydict/NewApp/View/SettingView/Tabs/GeneralTab.swift index 852631707..84668e464 100644 --- a/Easydict/NewApp/View/SettingView/Tabs/GeneralTab.swift +++ b/Easydict/NewApp/View/SettingView/Tabs/GeneralTab.swift @@ -26,7 +26,7 @@ struct GeneralTab: View { Section { FirstAndSecondLanguageSettingView() Picker("setting.general.language.language_detect_optimize", selection: $languageDetectOptimize) { - ForEach(EZLanguageDetectOptimize.allCases, id: \.rawValue) { option in + ForEach(LanguageDetectOptimize.allCases, id: \.rawValue) { option in Text(option.localizedStringResource) .tag(option) } From 6c837d417a9dface038948aaa29686ddb1577038 Mon Sep 17 00:00:00 2001 From: tisfeng Date: Tue, 23 Jan 2024 16:39:31 +0800 Subject: [PATCH 07/13] perf: add new advanced tab --- Easydict.xcodeproj/project.pbxproj | 4 ++ Easydict/App/Localizable.xcstrings | 19 ++++++++- .../NewApp/View/SettingView/SettingView.swift | 6 +++ .../View/SettingView/Tabs/AdvancedTab.swift | 42 +++++++++++++++++++ .../View/SettingView/Tabs/GeneralTab.swift | 15 ------- 5 files changed, 70 insertions(+), 16 deletions(-) create mode 100644 Easydict/NewApp/View/SettingView/Tabs/AdvancedTab.swift diff --git a/Easydict.xcodeproj/project.pbxproj b/Easydict.xcodeproj/project.pbxproj index 43ca6f7b7..0feacd3fa 100644 --- a/Easydict.xcodeproj/project.pbxproj +++ b/Easydict.xcodeproj/project.pbxproj @@ -70,6 +70,7 @@ 037E006D2B3DC098006491C6 /* EZOpenAIService+EZPromptMessages.m in Sources */ = {isa = PBXBuildFile; fileRef = 03CF27FA2B3A787900E19B57 /* EZOpenAIService+EZPromptMessages.m */; }; 038030952B4106800009230C /* CocoaLumberjack in Frameworks */ = {isa = PBXBuildFile; productRef = 038030942B4106800009230C /* CocoaLumberjack */; }; 038030972B4106800009230C /* CocoaLumberjackSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 038030962B4106800009230C /* CocoaLumberjackSwift */; }; + 03832F542B5F6BE200D0DC64 /* AdvancedTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03832F532B5F6BE200D0DC64 /* AdvancedTab.swift */; }; 0383914C292FBE120009828C /* Main.strings in Resources */ = {isa = PBXBuildFile; fileRef = 03839140292FBE120009828C /* Main.strings */; }; 0383914D292FBE120009828C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 03839143292FBE120009828C /* Assets.xcassets */; }; 0383914E292FBE120009828C /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 03839144292FBE120009828C /* ViewController.m */; }; @@ -421,6 +422,7 @@ 037852B529588EDE00D0E2CF /* EZCustomTableRowView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EZCustomTableRowView.m; sourceTree = ""; }; 037852B7295D49F900D0E2CF /* EZTableRowView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EZTableRowView.h; sourceTree = ""; }; 037852B8295D49F900D0E2CF /* EZTableRowView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EZTableRowView.m; sourceTree = ""; }; + 03832F532B5F6BE200D0DC64 /* AdvancedTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedTab.swift; sourceTree = ""; }; 03839141292FBE120009828C /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Main.strings"; sourceTree = ""; }; 03839142292FBE120009828C /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 03839143292FBE120009828C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -2099,6 +2101,7 @@ 0A8685C72B552A590022534F /* DisabledAppTab.swift */, 276742042B3DC230002A2C75 /* PrivacyTab.swift */, 276742052B3DC230002A2C75 /* AboutTab.swift */, + 03832F532B5F6BE200D0DC64 /* AdvancedTab.swift */, ); path = Tabs; sourceTree = ""; @@ -2831,6 +2834,7 @@ DC46DF802B4417B900DEAE3E /* Configuration.swift in Sources */, 036E7D7B293F4FC8002675DF /* EZOpenLinkButton.m in Sources */, EAED41EC2B54AA920005FE0A /* ServiceConfigurationSection.swift in Sources */, + 03832F542B5F6BE200D0DC64 /* AdvancedTab.swift in Sources */, 276742092B3DC230002A2C75 /* AboutTab.swift in Sources */, 03008B2E2941956D0062B821 /* EZURLSchemeHandler.m in Sources */, DC6D9C872B352EBC0055EFFC /* FontSizeHintView.swift in Sources */, diff --git a/Easydict/App/Localizable.xcstrings b/Easydict/App/Localizable.xcstrings index aacf0329e..d96c42854 100644 --- a/Easydict/App/Localizable.xcstrings +++ b/Easydict/App/Localizable.xcstrings @@ -2,7 +2,14 @@ "sourceLanguage" : "en", "strings" : { "" : { - + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "" + } + } + } }, "about" : { "comment" : "about", @@ -37,6 +44,16 @@ } } }, + "advanced" : { + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "高级" + } + } + } + }, "ali_translate" : { "extractionState" : "manual", "localizations" : { diff --git a/Easydict/NewApp/View/SettingView/SettingView.swift b/Easydict/NewApp/View/SettingView/SettingView.swift index f64f70efc..ec5c395ab 100644 --- a/Easydict/NewApp/View/SettingView/SettingView.swift +++ b/Easydict/NewApp/View/SettingView/SettingView.swift @@ -12,6 +12,7 @@ enum SettingTab: Int { case general case service case disabled + case advanced case privacy case about } @@ -34,6 +35,9 @@ struct SettingView: View { DisabledAppTab() .tabItem { Label("disabled_app_list", systemImage: "nosign") } .tag(SettingTab.disabled) + AdvancedTab() + .tabItem { Label("advanced", systemImage: "wrench.and.screwdriver") } + .tag(SettingTab.advanced) PrivacyTab() .tabItem { Label("privacy", systemImage: "hand.raised.square") } @@ -71,6 +75,8 @@ struct SettingView: View { 320 case .about: 450 + default: + 400 } let newSize = CGSize(width: maxWidth, height: height) diff --git a/Easydict/NewApp/View/SettingView/Tabs/AdvancedTab.swift b/Easydict/NewApp/View/SettingView/Tabs/AdvancedTab.swift new file mode 100644 index 000000000..55b9da5c3 --- /dev/null +++ b/Easydict/NewApp/View/SettingView/Tabs/AdvancedTab.swift @@ -0,0 +1,42 @@ +// +// AdvancedTab.swift +// Easydict +// +// Created by tisfeng on 2024/1/23. +// Copyright © 2024 izual. All rights reserved. +// + +import Defaults +import SwiftUI + +@available(macOS 13, *) +struct AdvancedTab: View { + var body: some View { + Form { + Section { + Picker("setting.general.advance.default_tts_service", selection: $defaultTTSServiceType) { + ForEach(TTSServiceType.allCases, id: \.rawValue) { option in + Text(option.localizedStringResource) + .tag(option) + } + } + Toggle("setting.general.advance.enable_beta_feature", isOn: $enableBetaFeature) + Toggle(isOn: $enableBetaNewApp) { + Text("enable_beta_new_app") + } + } header: { + Text("setting.general.advance.header") + } + } + .formStyle(.grouped) + } + + @Default(.defaultTTSServiceType) private var defaultTTSServiceType + @Default(.enableBetaFeature) private var enableBetaFeature + @Default(.enableBetaNewApp) private var enableBetaNewApp +} + +@available(macOS 13, *) +#Preview { + AdvancedTab() +} diff --git a/Easydict/NewApp/View/SettingView/Tabs/GeneralTab.swift b/Easydict/NewApp/View/SettingView/Tabs/GeneralTab.swift index 84668e464..6471771c1 100644 --- a/Easydict/NewApp/View/SettingView/Tabs/GeneralTab.swift +++ b/Easydict/NewApp/View/SettingView/Tabs/GeneralTab.swift @@ -139,21 +139,6 @@ struct GeneralTab: View { } header: { Text("other") } - - Section { - Picker("setting.general.advance.default_tts_service", selection: $defaultTTSServiceType) { - ForEach(TTSServiceType.allCases, id: \.rawValue) { option in - Text(option.localizedStringResource) - .tag(option) - } - } - Toggle("setting.general.advance.enable_beta_feature", isOn: $enableBetaFeature) - Toggle(isOn: $enableBetaNewApp) { - Text("enable_beta_new_app") - } - } header: { - Text("setting.general.advance.header") - } } .formStyle(.grouped) } From c673f6ca1f33a259dfb34fe4d4740a5a502b9a0d Mon Sep 17 00:00:00 2001 From: phlpsong <103433299+phlpsong@users.noreply.github.com> Date: Wed, 24 Jan 2024 11:50:19 +0800 Subject: [PATCH 08/13] fix add disable app drag lag issue (#355) * fix: add disable app by dragging lag issue * fix: revert default disable app workaround and disableAutoSelect * fix: revert workarounds and fix by disableAutoSelect --- Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift index 7d70402ff..d45ba5a44 100644 --- a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift +++ b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift @@ -12,8 +12,13 @@ import SwiftUI private class DisabledAppViewModel: ObservableObject { @Published var appModelList: [EZAppModel] = [] @Published var selectedAppModels: Set = [] - @Published var isImporting = false @Published var isShowImportErrorAlert = false + @Published var isImporting = false { + didSet { + // https://github.com/tisfeng/Easydict/issues/346 + Configuration.shared.disabledAutoSelect = isImporting + } + } init() { fetchDisabledApps() From f0bfe0bd072a81d806c6c233157e647a28e21ab7 Mon Sep 17 00:00:00 2001 From: tisfeng Date: Tue, 23 Jan 2024 23:25:12 +0800 Subject: [PATCH 09/13] docs: update sponsor list --- README.md | 1 + README_EN.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 2f0a8a952..dfb27f0b8 100644 --- a/README.md +++ b/README.md @@ -823,6 +823,7 @@ Easydict 作为一个免费开源的非盈利项目,目前主要是作者个 | 2024-01-09 | ㅤ Jack | 20 | 目前用过最好用的字典软件,谢谢! | | 2024-01-15 | ㅤ | 20 | 感谢开源,感谢有你:) | | 2024-01-16 | ㅤ sd | 5 | 大佬牛逼🐂🍺 | +| 2024-01-23 | ㅤ | 5 | |

diff --git a/README_EN.md b/README_EN.md index 026b259d3..369d47ec0 100644 --- a/README_EN.md +++ b/README_EN.md @@ -820,6 +820,7 @@ If you don't want your username to be displayed in the list, please choose anony | 2024-01-09 | ㅤ Jack | 20 | 目前用过最好用的字典软件,谢谢! | | 2024-01-15 | ㅤ | 20 | 感谢开源,感谢有你:) | | 2024-01-16 | ㅤ sd | 5 | 大佬牛逼🐂🍺 | +| 2024-01-23 | ㅤ | 5 | |

From 27c8eceeb36766031227e4fca82db00b7636348e Mon Sep 17 00:00:00 2001 From: tisfeng Date: Wed, 24 Jan 2024 11:50:06 +0800 Subject: [PATCH 10/13] chore: update issue templates --- .github/ISSUE_TEMPLATE/cn_bug_report_zh.yml | 20 +++++++++++++---- .github/ISSUE_TEMPLATE/cn_feature_request.yml | 8 +++++-- .github/ISSUE_TEMPLATE/en_bug_report.yml | 22 ++++++++++++++----- .github/ISSUE_TEMPLATE/en_feature_request.yml | 8 +++++-- 4 files changed, 45 insertions(+), 13 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/cn_bug_report_zh.yml b/.github/ISSUE_TEMPLATE/cn_bug_report_zh.yml index de97b7dfe..c2d0f068a 100644 --- a/.github/ISSUE_TEMPLATE/cn_bug_report_zh.yml +++ b/.github/ISSUE_TEMPLATE/cn_bug_report_zh.yml @@ -1,6 +1,6 @@ name: 反馈问题 description: 反馈问题 -title: "🐞 反馈问题:" +title: "🐞 反馈问题:{{请填写标题,不要留空}}" labels: ["bug"] body: @@ -22,18 +22,30 @@ body: id: description attributes: label: 问题描述 - description: 请详细描述你所遇到的问题,确保开发者能够理解、重现该问题。如果上下文信息不足,开发者无法定位,问题会被降低优先级或忽略。 + description: 请详细描述你所遇到的问题,确保开发者能够理解、重现该问题。如果上下文信息不足,导致开发者无法定位,问题会被降低优先级或忽略。 placeholder: 问题描述 validations: required: true + - type: dropdown + id: reproducible + attributes: + label: 该问题是否可以稳定重现? + multiple: false + options: + - 可重现 + - 不可重现 + validations: + required: true + - type: textarea id: reproduce attributes: label: 重现步骤 description: | - 请描述如何重现该问题。如果该问题是偶发性的,或者需要特定的操作步骤才能重现,请一定要详细提供重现步骤,否则开发者无法定位问题。 - (如果遇到一些很奇怪的问题,可以先尝试重启 Easydict,重启电脑,或卸载重装应用,看能否解决问题 🤔) + 如果该问题可重现,请一定要详细提供重现步骤,否则开发者无法定位问题。 + 如果该问题是偶发性的,可以先尝试重启 Easydict,重启电脑,或卸载重装应用,看能否解决问题 🤔 + 注意:鉴于开发者精力有限,目前只会处理可稳定重现的问题。对于不可重现的问题,当前只会简单记录下来,观察后续。 placeholder: 重现步骤 validations: required: true diff --git a/.github/ISSUE_TEMPLATE/cn_feature_request.yml b/.github/ISSUE_TEMPLATE/cn_feature_request.yml index 93baaa805..07b4f5297 100644 --- a/.github/ISSUE_TEMPLATE/cn_feature_request.yml +++ b/.github/ISSUE_TEMPLATE/cn_feature_request.yml @@ -1,6 +1,6 @@ name: 功能建议 description: 功能建议 -title: "🚀 功能建议:" +title: "🚀 功能建议:{{请填写标题,不要留空}}" labels: ["enhancement"] body: @@ -15,6 +15,8 @@ body: required: true - label: Easydict 已升级到 [最新版本](https://github.com/tisfeng/Easydict/releases) required: true + - label: 我理解并认可上述内容,并理解项目维护者精力有限,**不遵循规则的 issue 可能会被无视或直接关闭** + required: true - type: textarea id: feature_description @@ -29,7 +31,9 @@ body: id: feature_usecase attributes: label: 使用场景 - description: 请描述你希望功能的使用场景,有无其他类似可供参考的 App 功能等。 + description: | + 请描述你希望功能的使用场景,有无其他类似可供参考的 App 功能等。 + 如果该功能没有明确的使用场景,或是无法被开发者理解,可能会被降低优先级或忽略,因此请务必清晰描述。 placeholder: 使用场景 validations: required: true diff --git a/.github/ISSUE_TEMPLATE/en_bug_report.yml b/.github/ISSUE_TEMPLATE/en_bug_report.yml index fc13b2380..2f87973a8 100644 --- a/.github/ISSUE_TEMPLATE/en_bug_report.yml +++ b/.github/ISSUE_TEMPLATE/en_bug_report.yml @@ -1,6 +1,6 @@ name: Bug report description: Report an issue -title: "🐞 Bug Report: " +title: "🐞 Bug Report: {{Please fill in the title, don't leave it blank}} " labels: ["bug"] body: @@ -27,14 +27,26 @@ body: validations: required: true + - type: dropdown + id: reproducible + attributes: + label: Is the issue consistently reproducible? + multiple: false + options: + - Reproducible + - Non-reproducible + validations: + required: true + - type: textarea id: reproduce attributes: - label: Reproduction steps + label: Steps to Reproduce description: | - Please describe how to reproduce the problem. If the problem is episodic or requires specific action steps to reproduce, please describe it in as much detail as possible, otherwise the developer will not be able to locate the problem. - (If the problem is episodic, try restarting Easydict, restarting the device, or uninstalling and reinstalling the app to see if that solves the problem 🤔) - placeholder: Reproduction steps + If the issue is reproducible, please provide detailed steps to reproduce it. Otherwise, the developer may not be able to locate the issue. + If the issue is intermittent, you can try restarting Easydict, restarting your computer, or uninstalling and reinstalling the application to see if the problem can be resolved 🤔 + Note: Given the limited resources of the developer, only issues that can be reliably reproduced will be addressed at this time. For non-reproducible issues, they will be simply recorded for future observation. + placeholder: Steps to Reproduce validations: required: true diff --git a/.github/ISSUE_TEMPLATE/en_feature_request.yml b/.github/ISSUE_TEMPLATE/en_feature_request.yml index 5b50e36f2..f63be4bf5 100644 --- a/.github/ISSUE_TEMPLATE/en_feature_request.yml +++ b/.github/ISSUE_TEMPLATE/en_feature_request.yml @@ -1,6 +1,6 @@ name: Feature request description: Request a new feature -title: "🚀 Feature Request: " +title: "🚀 Feature Request: {{Please fill in the title, don't leave it blank}}" labels: ["enhancement"] body: @@ -15,6 +15,8 @@ body: required: true - label: Easydict has been upgraded to the [latest version](https://github.com/tisfeng/Easydict/releases) required: true + - label: I understand and agree to the above, and understand that the project maintainer has limited energy, **issues that do not follow the rules may be ignored or closed directly** + required: true - type: textarea id: feature_description @@ -29,7 +31,9 @@ body: id: feature_usecase attributes: label: Use case - description: Please describe the use case of the feature you're requesting, and whether there are any similar app features for reference. + description: | + Please describe the use case of the feature you're requesting, and whether there are any similar app features for reference. + If the feature has no actual usage scenarios or is not well understood by the developers it might get deprioritized or even ignored, so be sure to describe it clearly. placeholder: Use case validations: required: true From a2cc86277b9ea15d299afeb1dde8b961982b9908 Mon Sep 17 00:00:00 2001 From: phlpsong <103433299+phlpsong@users.noreply.github.com> Date: Wed, 24 Jan 2024 16:57:11 +0800 Subject: [PATCH 11/13] fix: General tab other section title (#361) * fix: general tab other title issue * fix: other translation --- Easydict/App/Localizable.xcstrings | 29 ++++++++++++------- .../View/SettingView/Tabs/GeneralTab.swift | 2 +- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/Easydict/App/Localizable.xcstrings b/Easydict/App/Localizable.xcstrings index d96c42854..bb3696775 100644 --- a/Easydict/App/Localizable.xcstrings +++ b/Easydict/App/Localizable.xcstrings @@ -1958,16 +1958,6 @@ } } }, - "other" : { - "localizations" : { - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "其他" - } - } - } - }, "Parameter Error" : { "comment" : "Error description", "localizations" : { @@ -2772,6 +2762,23 @@ } } }, + "setting.general.other.header" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Other" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "其他" + } + } + } + }, "setting.general.quick_link.header" : { "localizations" : { "en" : { @@ -3443,4 +3450,4 @@ } }, "version" : "1.0" -} \ No newline at end of file +} diff --git a/Easydict/NewApp/View/SettingView/Tabs/GeneralTab.swift b/Easydict/NewApp/View/SettingView/Tabs/GeneralTab.swift index 6471771c1..26e427fee 100644 --- a/Easydict/NewApp/View/SettingView/Tabs/GeneralTab.swift +++ b/Easydict/NewApp/View/SettingView/Tabs/GeneralTab.swift @@ -137,7 +137,7 @@ struct GeneralTab: View { Text("hide_menu_bar_icon") } } header: { - Text("other") + Text("setting.general.other.header") } } .formStyle(.grouped) From e0fd57a072ca7b2fd274fda46118761da783adfb Mon Sep 17 00:00:00 2001 From: tisfeng Date: Wed, 24 Jan 2024 14:06:46 +0800 Subject: [PATCH 12/13] perf: change to use gearshape.2 SF image for Advanced tab --- Easydict/NewApp/View/SettingView/SettingView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Easydict/NewApp/View/SettingView/SettingView.swift b/Easydict/NewApp/View/SettingView/SettingView.swift index ec5c395ab..81333b8ee 100644 --- a/Easydict/NewApp/View/SettingView/SettingView.swift +++ b/Easydict/NewApp/View/SettingView/SettingView.swift @@ -36,7 +36,7 @@ struct SettingView: View { .tabItem { Label("disabled_app_list", systemImage: "nosign") } .tag(SettingTab.disabled) AdvancedTab() - .tabItem { Label("advanced", systemImage: "wrench.and.screwdriver") } + .tabItem { Label("advanced", systemImage: "gearshape.2") } .tag(SettingTab.advanced) PrivacyTab() From 1dcf8d6d9e3ff11a33aac73f9f7f27cf39057120 Mon Sep 17 00:00:00 2001 From: tisfeng Date: Wed, 24 Jan 2024 18:18:51 +0800 Subject: [PATCH 13/13] fix: do not remove extra line breaks in DeepL --- Easydict/Feature/Service/DeepL/EZDeepLTranslate.m | 1 - 1 file changed, 1 deletion(-) diff --git a/Easydict/Feature/Service/DeepL/EZDeepLTranslate.m b/Easydict/Feature/Service/DeepL/EZDeepLTranslate.m index 44007d5ad..576c5de8c 100644 --- a/Easydict/Feature/Service/DeepL/EZDeepLTranslate.m +++ b/Easydict/Feature/Service/DeepL/EZDeepLTranslate.m @@ -390,7 +390,6 @@ - (void)deepLTranslate:(NSString *)text from:(EZLanguage)from to:(EZLanguage)to } */ NSString *translatedText = [responseObject[@"translations"] firstObject][@"text"]; - translatedText = [translatedText.trim removeExtraLineBreaks]; NSArray *translatedTextArray = [translatedText toParagraphs]; return translatedTextArray;