diff --git a/Easydict.xcodeproj/project.pbxproj b/Easydict.xcodeproj/project.pbxproj index 9c6675780..b9ae9f3ed 100644 --- a/Easydict.xcodeproj/project.pbxproj +++ b/Easydict.xcodeproj/project.pbxproj @@ -303,6 +303,7 @@ 9672D7D22B4008B40023B8FB /* MASShortcutBinder+EZMASShortcutBinder.m in Sources */ = {isa = PBXBuildFile; fileRef = 9672D7D12B4008B40023B8FB /* MASShortcutBinder+EZMASShortcutBinder.m */; }; 967712EA2B5B913600105E0F /* KeyHolder in Frameworks */ = {isa = PBXBuildFile; productRef = 967712E92B5B913600105E0F /* KeyHolder */; }; 967712EE2B5B943400105E0F /* Shortcut.swift in Sources */ = {isa = PBXBuildFile; fileRef = 967712ED2B5B943400105E0F /* Shortcut.swift */; }; + 96DFEB832B82588000F5C7EF /* EZTableTipsCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 96DFEB822B82588000F5C7EF /* EZTableTipsCell.m */; }; A0B65CA0F31AC8ECFB8347CC /* Pods_EasydictTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 378E73A7EA8FC8FB9C975A63 /* Pods_EasydictTests.framework */; }; B87AC7E36367075BA5D13234 /* Pods_Easydict.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6372B33DFF803C7096A82250 /* Pods_Easydict.framework */; }; C415C0AD2B450D4800A9D231 /* GeminiService.swift in Sources */ = {isa = PBXBuildFile; fileRef = C415C0AC2B450D4800A9D231 /* GeminiService.swift */; }; @@ -841,6 +842,8 @@ 9672D7D02B4008B40023B8FB /* MASShortcutBinder+EZMASShortcutBinder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MASShortcutBinder+EZMASShortcutBinder.h"; sourceTree = ""; }; 9672D7D12B4008B40023B8FB /* MASShortcutBinder+EZMASShortcutBinder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "MASShortcutBinder+EZMASShortcutBinder.m"; sourceTree = ""; }; 967712ED2B5B943400105E0F /* Shortcut.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Shortcut.swift; sourceTree = ""; }; + 96DFEB812B82588000F5C7EF /* EZTableTipsCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EZTableTipsCell.h; sourceTree = ""; }; + 96DFEB822B82588000F5C7EF /* EZTableTipsCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EZTableTipsCell.m; sourceTree = ""; }; A230E9A2358C7FBC7FB26189 /* Pods-EasydictTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-EasydictTests.debug.xcconfig"; path = "Target Support Files/Pods-EasydictTests/Pods-EasydictTests.debug.xcconfig"; sourceTree = ""; }; C415C0AC2B450D4800A9D231 /* GeminiService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeminiService.swift; sourceTree = ""; }; C490BF712BE910B70021E40A /* AdvancedTabItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AdvancedTabItemView.swift; path = Easydict/Swift/View/AdvancedTabItemView.swift; sourceTree = SOURCE_ROOT; }; @@ -1579,6 +1582,8 @@ children = ( 0396D60F292C932F006A11D9 /* EZSelectLanguageCell.h */, 0396D610292C932F006A11D9 /* EZSelectLanguageCell.m */, + 96DFEB812B82588000F5C7EF /* EZTableTipsCell.h */, + 96DFEB822B82588000F5C7EF /* EZTableTipsCell.m */, 037852B7295D49F900D0E2CF /* EZTableRowView.h */, 037852B8295D49F900D0E2CF /* EZTableRowView.m */, ); @@ -3093,6 +3098,7 @@ 03B022FE29231FA6001C7E63 /* EZBaseQueryViewController.m in Sources */, DC6D9C892B3969510055EFFC /* Appearance.swift in Sources */, 0396D611292C932F006A11D9 /* EZSelectLanguageCell.m in Sources */, + 96DFEB832B82588000F5C7EF /* EZTableTipsCell.m in Sources */, 036196752A000F5900806370 /* FWEncryptorAES.m in Sources */, 9643D9462B71D103000FBEA6 /* KeyHolderRowView.swift in Sources */, 0399C6A829A74E0F00B4AFCC /* EZQueryResult+EZDeepLTranslateResponse.m in Sources */, diff --git a/Easydict/App/Assets.xcassets/tip_Normal.imageset/Contents.json b/Easydict/App/Assets.xcassets/tip_Normal.imageset/Contents.json new file mode 100644 index 000000000..f008b3dac --- /dev/null +++ b/Easydict/App/Assets.xcassets/tip_Normal.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "filename" : "tip_Normal.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "tip_Normal@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Easydict/App/Assets.xcassets/tip_Normal.imageset/tip_Normal.png b/Easydict/App/Assets.xcassets/tip_Normal.imageset/tip_Normal.png new file mode 100644 index 000000000..b424c640e Binary files /dev/null and b/Easydict/App/Assets.xcassets/tip_Normal.imageset/tip_Normal.png differ diff --git a/Easydict/App/Assets.xcassets/tip_Normal.imageset/tip_Normal@2x.png b/Easydict/App/Assets.xcassets/tip_Normal.imageset/tip_Normal@2x.png new file mode 100644 index 000000000..a8001c97e Binary files /dev/null and b/Easydict/App/Assets.xcassets/tip_Normal.imageset/tip_Normal@2x.png differ diff --git a/Easydict/App/Localizable.xcstrings b/Easydict/App/Localizable.xcstrings index 2e5f80e83..03fef3fcd 100644 --- a/Easydict/App/Localizable.xcstrings +++ b/Easydict/App/Localizable.xcstrings @@ -986,6 +986,23 @@ } } }, + "disable_tips_view" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Disable Tips View" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "关闭提示视图" + } + } + } + }, "disabled_app_list" : { "comment" : "disabled app list", "localizations" : { @@ -4377,6 +4394,158 @@ } } }, + "tips_edit_button" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Why does the edit button in the upper right corner flicker when selecting words in some applications?" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "为什么在某些应用取词时,右上角编辑按钮会出现闪烁?" + } + } + } + }, + "tips_more" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "See More" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "查看更多" + } + } + } + }, + "tips_mouse_hover" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Why can't I use mouse hover to select words in some applications?" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "为什么在某些应用中无法使用鼠标划词?" + } + } + } + }, + "tips_select_words" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Why can't I select words on some web pages in the browser?" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "为什么浏览器中某些网页无法取词?" + } + } + } + }, + "tips_solve" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Solve This" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "如何解决" + } + } + } + }, + "tips_still_pop_up" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Why does macOS still pop up asking for permissions even though I have given Easydict the Accessibility/Screen Recording permissions?" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已经给 Easydict 辅助功能/录屏权限 macOS 仍然弹窗要求给予权限?" + } + } + } + }, + "tips_text_empty" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Why is the text empty when I select words in some applications?" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "为什么在某些应用中取词文本为空?" + } + } + } + }, + "tips_title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tips" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "提示" + } + } + } + }, + "tips_word_selection_OCR" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Why do word selection and OCR need to enable system-related permissions?" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "为什么取词和 OCR 需要开启系统相关权限?" + } + } + } + }, "toggle_languages" : { "localizations" : { "en" : { diff --git a/Easydict/Swift/Feature/Configuration/Configuration+Defaults.swift b/Easydict/Swift/Feature/Configuration/Configuration+Defaults.swift index 0044070b1..dc03b33d3 100644 --- a/Easydict/Swift/Feature/Configuration/Configuration+Defaults.swift +++ b/Easydict/Swift/Feature/Configuration/Configuration+Defaults.swift @@ -102,6 +102,8 @@ extension Defaults.Keys { Key("EZConfiguration_kEnableBetaNewAppKey", default: false) } } + + static var disableTipsView = Key("disableTipsViewKey", default: false) } extension Defaults.Keys { diff --git a/Easydict/Swift/Feature/Configuration/Configuration.swift b/Easydict/Swift/Feature/Configuration/Configuration.swift index 3d8ce3dc1..20228a10d 100644 --- a/Easydict/Swift/Feature/Configuration/Configuration.swift +++ b/Easydict/Swift/Feature/Configuration/Configuration.swift @@ -104,6 +104,8 @@ class Configuration: NSObject { @DefaultsWrapper(.selectQueryTextWhenWindowActivate) var selectQueryTextWhenWindowActivate: Bool + @DefaultsWrapper(.disableTipsView) var disableTipsView: Bool + var disabledAutoSelect: Bool = false var isRecordingSelectTextShortcutKey: Bool = false diff --git a/Easydict/Swift/View/SettingView/SettingView.swift b/Easydict/Swift/View/SettingView/SettingView.swift index 888b8e413..7fc3f7af4 100644 --- a/Easydict/Swift/View/SettingView/SettingView.swift +++ b/Easydict/Swift/View/SettingView/SettingView.swift @@ -78,7 +78,7 @@ struct SettingView: View { case .disabled: 500 case .advanced: - 280 + 310 case .privacy: 320 case .about: diff --git a/Easydict/Swift/View/SettingView/Tabs/TabView/AdvancedTab.swift b/Easydict/Swift/View/SettingView/Tabs/TabView/AdvancedTab.swift index acfe0f381..dea07a23a 100644 --- a/Easydict/Swift/View/SettingView/Tabs/TabView/AdvancedTab.swift +++ b/Easydict/Swift/View/SettingView/Tabs/TabView/AdvancedTab.swift @@ -29,6 +29,13 @@ struct AdvancedTab: View { .tag(option) } } + Toggle(isOn: $disableTipsView) { + AdvancedTabItemView( + color: .yellow, + systemImage: "lightbulb.fill", + labelText: "disable_tips_view" + ) + } } Section { Toggle(isOn: $enableBetaFeature) { @@ -58,6 +65,7 @@ struct AdvancedTab: View { @Default(.defaultTTSServiceType) private var defaultTTSServiceType @Default(.enableBetaFeature) private var enableBetaFeature @Default(.enableBetaNewApp) private var enableBetaNewApp + @Default(.disableTipsView) private var disableTipsView } @available(macOS 13, *) diff --git a/Easydict/objc/Utility/EZCategory/NSString/NSString+EZUtils.h b/Easydict/objc/Utility/EZCategory/NSString/NSString+EZUtils.h index 90f3965ab..d422fb0c7 100644 --- a/Easydict/objc/Utility/EZCategory/NSString/NSString+EZUtils.h +++ b/Easydict/objc/Utility/EZCategory/NSString/NSString+EZUtils.h @@ -156,6 +156,11 @@ static NSArray *const EZDashCharacterList = @[ @"—", @"-", @"–" ]; - (NSString *)removeAlphabetAndNumbers; +#pragma mark - Check Empty String +#ifndef EZ_isEmptyString +FOUNDATION_EXPORT BOOL EZ_isEmptyString(id param); +#endif + @end NS_ASSUME_NONNULL_END diff --git a/Easydict/objc/Utility/EZCategory/NSString/NSString+EZUtils.m b/Easydict/objc/Utility/EZCategory/NSString/NSString+EZUtils.m index 9494781fe..333988292 100644 --- a/Easydict/objc/Utility/EZCategory/NSString/NSString+EZUtils.m +++ b/Easydict/objc/Utility/EZCategory/NSString/NSString+EZUtils.m @@ -20,6 +20,19 @@ @"「" : @"」", }; +BOOL EZ_isEmptyString(id param) { + if (!param) { + return YES; + } + if ([param isKindOfClass:[NSString class]]) { + NSString *str = param; + return (str.length == 0); + } + NSCAssert(NO, @"isEmptyString: param %@ is not NSString", param); + return YES; +} + + @implementation NSString (EZUtils) /// Check if it is a single letter of the alphabet, like 'a', 'A' @@ -224,7 +237,7 @@ - (BOOL)isEnglishWordWithLanguage:(EZLanguage)language { } - (NLLanguage)detectText { - NLTagger *tagger = [[NLTagger alloc] initWithTagSchemes:@[NLTagSchemeLanguage]]; + NLTagger *tagger = [[NLTagger alloc] initWithTagSchemes:@[ NLTagSchemeLanguage ]]; tagger.string = self; NLLanguage language = [tagger dominantLanguage]; return language; @@ -466,7 +479,7 @@ - (NSString *)suffixQuote { } return quotes; } - + - (NSString *)tryToRemovePrefixQuote { NSString *prefixQuote = [self prefixQuote]; diff --git a/Easydict/objc/ViewController/Cell/EZTableTipsCell.h b/Easydict/objc/ViewController/Cell/EZTableTipsCell.h new file mode 100644 index 000000000..8782c3ea0 --- /dev/null +++ b/Easydict/objc/ViewController/Cell/EZTableTipsCell.h @@ -0,0 +1,45 @@ +// +// EZTableTipsCell.h +// Easydict +// +// Created by Sharker on 2024/2/18. +// Copyright © 2024 izual. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, EZTipsCellType) { + EZTipsCellTypeNone = -1, + EZTipsCellTypeTextEmpty = 0, + EZTipsCellTypeMouseHover, + EZTipsCellTypeBeep, + EZTipsCellTypeEditButton, + EZTipsCellTypeMightSelecting, + EZTipsCellTypeWordSelectionOCR, + EZTipsCellTypeSelectWords, + EZTipsCellTypeStillPopup, +}; + +@interface EZTableTipsCell : NSTableRowView + +- (CGFloat)cellHeight; + + +- (instancetype)initWithFrame:(CGRect)frame type:(EZTipsCellType)type; + +/// update tips cell content with type +/// - Parameters: +/// - content: string value for content +/// - type: cell type default value is none +- (void)updateTipsContent:(NSString *)content type:(EZTipsCellType)type; + + +/// update tips cell of type +/// - Parameter type: cell type default value is none +- (void)updateTipsCellType:(EZTipsCellType)type; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Easydict/objc/ViewController/Cell/EZTableTipsCell.m b/Easydict/objc/ViewController/Cell/EZTableTipsCell.m new file mode 100644 index 000000000..15468578f --- /dev/null +++ b/Easydict/objc/ViewController/Cell/EZTableTipsCell.m @@ -0,0 +1,282 @@ +// +// EZTableTipsCell.m +// Easydict +// +// Created by Sharker on 2024/2/18. +// Copyright © 2024 izual. All rights reserved. +// + +#import "EZTableTipsCell.h" +#import "EZOpenLinkButton.h" +#import "NSImage+EZSymbolmage.h" +#import "EZLanguageManager.h" +#import "NSString+EZUtils.h" + +@interface EZTableTipsCell () +@property (nonatomic, strong) NSView *contentView; +@property (nonatomic, strong) NSImageView *tipsIconImageView; +@property (nonatomic, strong) NSTextField *tipsNameLabel; +@property (nonatomic, strong) NSTextField *tipsContentLabel; +@property (nonatomic, strong) EZOpenLinkButton *moreBtn; +@property (nonatomic, strong) EZOpenLinkButton *solveBtn; +@property (nonatomic, strong) NSDictionary *dataDict; +@property (nonatomic, strong) NSString *questionSolveURL; +@property (nonatomic, strong) NSString *seeMoreURL; +@property (nonatomic, assign) EZTipsCellType tipsType; +@end + +@implementation EZTableTipsCell + +- (instancetype)initWithFrame:(CGRect)frame type:(EZTipsCellType)type { + self = [super initWithFrame:frame]; + if (self) { + self.tipsType = type; + [self setupUI]; + [self updateQuestionContent]; + } + return self; +} + +- (void)updateTipsCellType:(EZTipsCellType)type { + [self updateTipsContent:@"" type:type]; +} + +- (void)updateTipsContent:(NSString *)content type:(EZTipsCellType)type { + if (!EZ_isEmptyString(content)) { + self.tipsContentLabel.stringValue = content; + } + self.tipsType = type; + [self updateQuestionContent]; +} + +- (void)setupUI { + // mas key + self.contentView.mas_key = @"topBarView"; + self.tipsIconImageView.mas_key = @"tipsIconImageView"; + self.tipsNameLabel.mas_key = @"tipsNameLabel"; + self.moreBtn.mas_key = @"moreBtn"; + self.solveBtn.mas_key = @"solveBtn"; + + CGSize iconSize = CGSizeMake(20, 20); + + // constraints + [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(0); + }]; + + [self.tipsIconImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(9); + make.top.mas_equalTo(9); + make.size.mas_equalTo(iconSize); + }]; + + [self.tipsNameLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(self.tipsIconImageView.mas_right).offset(6); + make.centerY.mas_equalTo(self.tipsIconImageView.mas_centerY).offset(1); + }]; + + [self.solveBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(9); + make.top.mas_equalTo(self.tipsContentLabel.mas_bottom).offset(9); + make.size.mas_equalTo(CGSizeMake(98, 32)); + }]; + + [self.moreBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(self.solveBtn.mas_right).offset(20); + make.top.mas_equalTo(self.solveBtn); + make.size.mas_equalTo(CGSizeMake(94, 32)); + }]; +} + +- (void)updateConstraints { + [self.tipsContentLabel mas_updateConstraints:^(MASConstraintMaker *make) { + make.left.mas_equalTo(9); + make.width.mas_lessThanOrEqualTo(self.bounds.size.width - 9); + make.top.mas_equalTo(self.tipsNameLabel.mas_bottom).offset(12); + }]; + + [super updateConstraints]; +} + +- (void)updateQuestionContent { + NSArray *questions = self.dataDict[@"questions"]; + NSInteger index = 0; + if (self.tipsType == EZTipsCellTypeNone) { + // random question and slove + index = arc4random() % questions.count; + } else { + // show special question + index = self.tipsType; + } + self.tipsContentLabel.stringValue = questions[index]; + NSArray *solves; + if ([EZLanguageManager.shared isSystemChineseFirstLanguage]) { + solves = self.dataDict[@"solveZh"]; + } else { + solves = self.dataDict[@"solveEn"]; + } + self.questionSolveURL = solves[index]; + self.solveBtn.link = self.questionSolveURL; +} + +- (CGFloat)cellHeight { + CGFloat cellHeight = 9 + 20 + 12 + self.tipsContentLabel.height + 9 + 32 + 6; + return cellHeight; +} + +#pragma mark - Accesstor +- (NSView *)contentView { + if (!_contentView) { + mm_weakify(self); + _contentView = [NSView mm_make:^(NSView *_Nonnull view) { + mm_strongify(self); + [self addSubview:view]; + view.wantsLayer = YES; + view.layer.cornerRadius = EZCornerRadius_8; + [view.layer excuteLight:^(CALayer *layer) { + layer.backgroundColor = [NSColor ez_titleBarBgLightColor].CGColor; + } dark:^(CALayer *layer) { + layer.backgroundColor = [NSColor ez_titleBarBgDarkColor].CGColor; + }]; + }]; + } + return _contentView; +} + +- (NSImageView *)tipsIconImageView { + if (!_tipsIconImageView) { + mm_weakify(self); + _tipsIconImageView = [NSImageView mm_make:^(NSImageView *imageView) { + mm_strongify(self); + [self.contentView addSubview:imageView]; + [imageView setImage:[NSImage imageNamed:@"tip_Normal"]]; + }]; + } + return _tipsIconImageView; +} + +- (NSTextField *)tipsNameLabel { + if (!_tipsNameLabel) { + mm_weakify(self); + _tipsNameLabel = [NSTextField mm_make:^(NSTextField *label) { + mm_strongify(self); + [self.contentView addSubview:label]; + label.stringValue = NSLocalizedString(@"tips_title", nil); + label.editable = NO; + label.bordered = NO; + label.backgroundColor = NSColor.clearColor; + label.alignment = NSTextAlignmentCenter; + label.font = [NSFont systemFontOfSize:14]; + [label excuteLight:^(NSTextField *label) { + label.textColor = [NSColor ez_resultTextLightColor]; + } dark:^(NSTextField *label) { + label.textColor = [NSColor ez_resultTextDarkColor]; + }]; + }]; + } + return _tipsNameLabel; +} + +- (NSTextField *)tipsContentLabel { + if (!_tipsContentLabel) { + mm_weakify(self); + _tipsContentLabel = [NSTextField mm_make:^(NSTextField *label) { + mm_strongify(self); + [self.contentView addSubview:label]; + label.editable = NO; + label.bordered = NO; + label.backgroundColor = NSColor.clearColor; + label.alignment = NSTextAlignmentLeft; + label.stringValue = self.dataDict[@"questions"][0]; + label.usesSingleLineMode = NO; + label.maximumNumberOfLines = 0; + [label excuteLight:^(NSTextField *label) { + label.textColor = [NSColor ez_resultTextLightColor]; + } dark:^(NSTextField *label) { + label.textColor = [NSColor ez_resultTextDarkColor]; + }]; + }]; + } + return _tipsContentLabel; +} + +- (EZOpenLinkButton *)moreBtn { + if (!_moreBtn) { + _moreBtn = [[EZOpenLinkButton alloc] init]; + [self addSubview:_moreBtn]; + NSImage *moreBtnImage = [NSImage ez_imageWithSymbolName:@"ellipsis.circle.fill"]; + _moreBtn.image = moreBtnImage; + _moreBtn.title = NSLocalizedString(@"tips_more", nil); + _moreBtn.imagePosition = NSImageLeft; + _moreBtn.edgeInsets = NSEdgeInsetsMake(0, 3, 0, 3); + [_moreBtn excuteLight:^(NSButton *button) { + button.image = [button.image imageWithTintColor:[NSColor ez_imageTintLightColor]]; + } dark:^(NSButton *button) { + button.image = [button.image imageWithTintColor:[NSColor ez_imageTintDarkColor]]; + }]; + _moreBtn.link = self.seeMoreURL; + } + return _moreBtn; +} + +- (EZOpenLinkButton *)solveBtn { + if (!_solveBtn) { + _solveBtn = [[EZOpenLinkButton alloc] init]; + [self addSubview:_solveBtn]; + NSImage *solveBtnImage = [NSImage ez_imageWithSymbolName:@"link.circle.fill"]; + _solveBtn.image = solveBtnImage; + _solveBtn.imagePosition = NSImageLeft; + _solveBtn.title = NSLocalizedString(@"tips_solve", nil); + _solveBtn.edgeInsets = NSEdgeInsetsMake(0, 3, 0, 3); + [_solveBtn excuteLight:^(NSButton *button) { + button.image = [button.image imageWithTintColor:[NSColor ez_imageTintLightColor]]; + } dark:^(NSButton *button) { + button.image = [button.image imageWithTintColor:[NSColor ez_imageTintDarkColor]]; + }]; + } + return _solveBtn; +} + +- (NSDictionary *)dataDict { + if (!_dataDict) { + _dataDict = @{ + @"questions" : @[ + NSLocalizedString(@"tips_text_empty", nil), + NSLocalizedString(@"tips_mouse_hover", nil), + NSLocalizedString(@"tips_edit_button", nil), + NSLocalizedString(@"tips_word_selection_OCR", nil), + NSLocalizedString(@"tips_select_words", nil), + NSLocalizedString(@"tips_still_pop_up", nil), + ], + @"solveEn" : @[ + @"https://github.com/tisfeng/Easydict/wiki/FAQ#why-is-the-text-empty-when-i-select-words-in-some-applications", + @"https://github.com/tisfeng/Easydict/wiki/FAQ#why-cant-i-use-mouse-hover-to-select-words-in-some-applications", + @"https://github.com/tisfeng/Easydict/wiki/FAQ#why-does-the-edit-button-in-the-upper-right-corner-flicker-when-selecting-words-in-some-applications", + @"https://github.com/tisfeng/Easydict/wiki/FAQ#why-do-word-selection-and-ocr-need-to-enable-system-related-permissions", + @"https://github.com/tisfeng/Easydict/wiki/FAQ#why-cant-i-select-words-on-some-web-pages-in-the-browser", + @"https://github.com/tisfeng/Easydict/wiki/FAQ#why-does-macos-still-pop-up-asking-for-permissions-even-though-i-have-given-easydict-the-accessibilityscreen-recording-permissions" + ], + @"solveZh" : @[ + @"https://github.com/tisfeng/Easydict/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98#%E4%B8%BA%E4%BB%80%E4%B9%88%E5%9C%A8%E6%9F%90%E4%BA%9B%E5%BA%94%E7%94%A8%E4%B8%AD%E5%8F%96%E8%AF%8D%E6%96%87%E6%9C%AC%E4%B8%BA%E7%A9%BA", + @"https://github.com/tisfeng/Easydict/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98#%E4%B8%BA%E4%BB%80%E4%B9%88%E5%9C%A8%E6%9F%90%E4%BA%9B%E5%BA%94%E7%94%A8%E4%B8%AD%E6%97%A0%E6%B3%95%E4%BD%BF%E7%94%A8%E9%BC%A0%E6%A0%87%E5%88%92%E8%AF%8D", + @"https://github.com/tisfeng/Easydict/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98#%E4%B8%BA%E4%BB%80%E4%B9%88%E5%9C%A8%E6%9F%90%E4%BA%9B%E5%BA%94%E7%94%A8%E5%8F%96%E8%AF%8D%E6%97%B6%E5%8F%B3%E4%B8%8A%E8%A7%92%E7%BC%96%E8%BE%91%E6%8C%89%E9%92%AE%E4%BC%9A%E5%87%BA%E7%8E%B0%E9%97%AA%E7%83%81", + @"https://github.com/tisfeng/Easydict/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98#%E4%B8%BA%E4%BB%80%E4%B9%88%E5%8F%96%E8%AF%8D%E5%92%8C-ocr-%E9%9C%80%E8%A6%81%E5%BC%80%E5%90%AF%E7%B3%BB%E7%BB%9F%E7%9B%B8%E5%85%B3%E6%9D%83%E9%99%90", + @"https://github.com/tisfeng/Easydict/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98#%E4%B8%BA%E4%BB%80%E4%B9%88%E6%B5%8F%E8%A7%88%E5%99%A8%E4%B8%AD%E6%9F%90%E4%BA%9B%E7%BD%91%E9%A1%B5%E6%97%A0%E6%B3%95%E5%8F%96%E8%AF%8D", + @"https://github.com/tisfeng/Easydict/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98#%E5%B7%B2%E7%BB%8F%E7%BB%99-easydict-%E8%BE%85%E5%8A%A9%E5%8A%9F%E8%83%BD%E5%BD%95%E5%B1%8F%E6%9D%83%E9%99%90-macos-%E4%BB%8D%E7%84%B6%E5%BC%B9%E7%AA%97%E8%A6%81%E6%B1%82%E7%BB%99%E4%BA%88%E6%9D%83%E9%99%90" + ], + }; + } + return _dataDict; +} + +- (NSString *)seeMoreURL { + if (!_seeMoreURL) { + if ([EZLanguageManager.shared isSystemChineseFirstLanguage]) { + _seeMoreURL = @"https://github.com/tisfeng/Easydict/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98"; + } else { + _seeMoreURL = @"https://github.com/tisfeng/Easydict/wiki/FAQ"; + } + } + return _seeMoreURL; +} +@end diff --git a/Easydict/objc/ViewController/View/CustomButton/EZButton/EZButton.h b/Easydict/objc/ViewController/View/CustomButton/EZButton/EZButton.h index 8426194ab..333c13991 100644 --- a/Easydict/objc/ViewController/View/CustomButton/EZButton/EZButton.h +++ b/Easydict/objc/ViewController/View/CustomButton/EZButton/EZButton.h @@ -65,6 +65,8 @@ typedef NS_ENUM(NSUInteger, EZButtonState) { @property (nonatomic, copy) NSAttributedString *attrTitle; +@property (nonatomic, assign) NSEdgeInsets edgeInsets; // setting button padding + @property (nonatomic, copy, nullable) void (^clickBlock)(EZButton *button); @property (nonatomic, copy, nullable) void (^mouseEnterBlock)(EZButton *button); diff --git a/Easydict/objc/ViewController/View/CustomButton/EZButton/EZButton.m b/Easydict/objc/ViewController/View/CustomButton/EZButton/EZButton.m index adcaa7d6a..7d6f94200 100644 --- a/Easydict/objc/ViewController/View/CustomButton/EZButton/EZButton.m +++ b/Easydict/objc/ViewController/View/CustomButton/EZButton/EZButton.m @@ -39,6 +39,12 @@ - (void)viewWillMoveToSuperview:(NSView *)newSuperview { [self updateButtonApperaceWithState:self.buttonState]; } +- (void)drawRect:(NSRect)dirtyRect { + NSRect originRect = self.bounds; + self.bounds = NSInsetRect(originRect, self.edgeInsets.left + self.edgeInsets.right, self.edgeInsets.top + self.edgeInsets.bottom); + [super drawRect:dirtyRect]; + self.bounds = originRect; +} #pragma mark - Mouse Actions diff --git a/Easydict/objc/ViewController/Window/BaseQueryWindow/EZBaseQueryViewController.h b/Easydict/objc/ViewController/Window/BaseQueryWindow/EZBaseQueryViewController.h index 42cd85c3a..83788c7d5 100644 --- a/Easydict/objc/ViewController/Window/BaseQueryWindow/EZBaseQueryViewController.h +++ b/Easydict/objc/ViewController/Window/BaseQueryWindow/EZBaseQueryViewController.h @@ -11,6 +11,7 @@ #import "EZQueryModel.h" #import "EZQueryResult.h" #import "EZTitlebar.h" +#import "EZTableTipsCell.h" NS_ASSUME_NONNULL_BEGIN @@ -64,6 +65,11 @@ NS_ASSUME_NONNULL_BEGIN - (void)receiveTitlebarAction:(EZTitlebarQuickAction)action; +- (void)updateActionType:(EZActionType)actionType; + +/// show tips view +- (void)showTipsView:(BOOL)isVisible; + @end NS_ASSUME_NONNULL_END diff --git a/Easydict/objc/ViewController/Window/BaseQueryWindow/EZBaseQueryViewController.m b/Easydict/objc/ViewController/Window/BaseQueryWindow/EZBaseQueryViewController.m index 6a5c0b963..a72a77804 100644 --- a/Easydict/objc/ViewController/Window/BaseQueryWindow/EZBaseQueryViewController.m +++ b/Easydict/objc/ViewController/Window/BaseQueryWindow/EZBaseQueryViewController.m @@ -31,6 +31,7 @@ static NSString *const EZQueryViewId = @"EZQueryViewId"; static NSString *const EZSelectLanguageCellId = @"EZSelectLanguageCellId"; +static NSString *const EZTableTipsCellId = @"EZTableTipsCellId"; static NSString *const EZResultViewId = @"EZResultViewId"; static NSString *const EZColumnId = @"EZColumnId"; @@ -54,6 +55,7 @@ @interface EZBaseQueryViewController ()