From e2e16a364978d9cf8223cb23907aa18eabe33d96 Mon Sep 17 00:00:00 2001 From: phlpsong Date: Wed, 17 Jan 2024 22:28:56 +0800 Subject: [PATCH 01/18] feat: add disabled app tab --- Easydict.xcodeproj/project.pbxproj | 11 +- Easydict/App/Easydict-Bridging-Header.h | 1 + .../NewApp/View/SettingView/SettingView.swift | 5 + .../View/SettingView/Tabs/DisabledTab.swift | 241 ++++++++++++++++++ 4 files changed, 255 insertions(+), 3 deletions(-) create mode 100644 Easydict/NewApp/View/SettingView/Tabs/DisabledTab.swift diff --git a/Easydict.xcodeproj/project.pbxproj b/Easydict.xcodeproj/project.pbxproj index 9bb89217d..dd7aefbb4 100644 --- a/Easydict.xcodeproj/project.pbxproj +++ b/Easydict.xcodeproj/project.pbxproj @@ -231,6 +231,7 @@ 0A057D6D2B499A000025C51D /* ServiceTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A057D6C2B499A000025C51D /* ServiceTab.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 /* DisabledTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A8685C72B552A590022534F /* DisabledTab.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 */; }; @@ -706,6 +707,7 @@ 0A057D6C2B499A000025C51D /* ServiceTab.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceTab.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 /* DisabledTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisabledTab.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 = ""; }; @@ -2077,6 +2079,7 @@ EAED41EA2B54A4900005FE0A /* ServiceConfiguration */, 278540332B3DE04F004E9488 /* GeneralTab.swift */, 0A057D6C2B499A000025C51D /* ServiceTab.swift */, + 0A8685C72B552A590022534F /* DisabledTab.swift */, 276742042B3DC230002A2C75 /* PrivacyTab.swift */, 276742052B3DC230002A2C75 /* AboutTab.swift */, ); @@ -2320,7 +2323,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 +2482,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 = ( @@ -2691,6 +2695,7 @@ 17BCAEF82B0DFF9000A7D372 /* EZNiuTransTranslate.m in Sources */, 039F5506294B6E29004AB940 /* EZSettingViewController.m in Sources */, 03BD281E29481C0400F5891A /* EZAudioPlayer.m in Sources */, + 0A8685C82B552A590022534F /* DisabledTab.swift in Sources */, 03E02A2629250D1D00A10260 /* EZEventMonitor.m in Sources */, 03B0233429231FA6001C7E63 /* MMConsoleLogFormatter.m in Sources */, 037852B9295D49F900D0E2CF /* EZTableRowView.m in Sources */, 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/NewApp/View/SettingView/SettingView.swift b/Easydict/NewApp/View/SettingView/SettingView.swift index a7e27c991..7667688d1 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) + DisabledTab() + .tabItem { Label("disabled_app_list", systemImage: "nosign") } + .tag(SettingTab.disabled.rawValue) + PrivacyTab() .tabItem { Label("privacy", systemImage: "hand.raised.square") } .tag(SettingTab.privacy) diff --git a/Easydict/NewApp/View/SettingView/Tabs/DisabledTab.swift b/Easydict/NewApp/View/SettingView/Tabs/DisabledTab.swift new file mode 100644 index 000000000..f0c42b8a9 --- /dev/null +++ b/Easydict/NewApp/View/SettingView/Tabs/DisabledTab.swift @@ -0,0 +1,241 @@ +// +// DisabledTab.swift +// Easydict +// +// Created by phlpsong on 2024/1/15. +// Copyright © 2024 izual. All rights reserved. +// + +import Combine +import SwiftUI + +class DisableViewModel: ObservableObject { + @Published var appModelList: [EZAppModel] = [] + + @Published var selectedAppModel: EZAppModel? = nil + + @Published var isImporting = false + + func fetchDisabledApps() { + appModelList = EZLocalStorage.shared().selectTextTypeAppModelList + } + + func removeDisabledApp() { + appModelList = appModelList.filter { $0.appBundleID != selectedAppModel?.appBundleID } + EZLocalStorage.shared().selectTextTypeAppModelList = appModelList + } + + func newAppSelected(for url: URL) { + guard let newSelectApp = newBlockApps(url: url) else { return } + + appModelList.append(newSelectApp) + EZLocalStorage.shared().selectTextTypeAppModelList = appModelList + } + + func newBlockApps(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 DisabledTab: View { + + @ObservedObject var viewModel = DisableViewModel() + + var appListView: some View { + VStack(spacing: 0) { + List { + ForEach(viewModel.appModelList, id: \.self) { app in + BlockAppItemView(with: app) + .tag(app) + .environmentObject(viewModel) + } + .listRowSeparator(.hidden) + } + .listStyle(.plain) + + ListToolbar() + .environmentObject(viewModel) + .fileImporter( + isPresented: $viewModel.isImporting, + allowedContentTypes: [.application], + allowsMultipleSelection: true + ) { result in + switch result { + case let .success(urls): + urls.forEach { url in + let gotAccess = url.startAccessingSecurityScopedResource() + if !gotAccess { return } + viewModel.newAppSelected(for: url) + url.stopAccessingSecurityScopedResource() + } + case let .failure(error): + print("error: \(error)") + } + } + } + .frame(maxWidth: 420) + .clipShape(RoundedRectangle(cornerRadius: 8)) + .padding([.bottom]) + } + + var body: some View { + VStack { + Text("disabled_title") + .padding() + + appListView + } + .task { + viewModel.fetchDisabledApps() + } + } +} + +@available(macOS 13.0, *) +struct ListToolbar: View { + @Environment(\.colorScheme) private var colorScheme + + @EnvironmentObject var viewModel: DisableViewModel + + var bgColor: Color { + Color(nsColor: colorScheme == .light ? NSColor.controlBackgroundColor : NSColor.controlBackgroundColor) + } + + var body: some View { + VStack(spacing: 0) { + Divider() + HStack(spacing: 0) { + ListButton(imageName: "plus") { + viewModel.isImporting.toggle() + } + Divider() + ListButton(imageName: "minus") { + viewModel.removeDisabledApp() + } + Spacer() + } + .padding(2) + } + .frame(height: 28) + .background(bgColor) + } +} + +@available(macOS 13.0, *) +struct ListButton: View { + var imageName: String + var action: () -> Void + + var body: some View { + Button(action: { + action() + }) { + Image(systemName: imageName) + } + .buttonStyle(BorderlessButtonStyle()) + .contentShape(Rectangle()) + .frame(width: 24, height: 24) + } +} + +@available(macOS 13.0, *) +struct BlockAppItemView: View { + var app: EZAppModel + + @ObservedObject var appFetcher: AppFetcher + + @Environment(\.colorScheme) private var colorScheme + + @EnvironmentObject var viewModel: DisableViewModel + + private var tableColor: Color { + Color(nsColor: colorScheme == .light ? .ez_tableRowViewBgLight() : .ez_tableRowViewBgDark()) + } + + init(with appModel: EZAppModel) { + app = appModel + appFetcher = AppFetcher(appBundleId: app.appBundleID) + } + + var body: some View { + HStack(alignment: .center) { + Image(nsImage: appFetcher.appIcon ?? NSImage()) + .resizable() + .frame(width: 24, height: 24) + + Text(appFetcher.appName) + + Spacer() + } + .frame(maxWidth: .infinity) + .contentShape(Rectangle()) + .padding(.vertical, 4) + .overlay { + TapHandler { + let selectedAppModel = viewModel.selectedAppModel + if selectedAppModel == nil || selectedAppModel != app { + viewModel.selectedAppModel = app + } else { + viewModel.selectedAppModel = nil + } + } + } + .listRowBackground(viewModel.selectedAppModel == app ? Color("service_cell_highlight") : .clear) + } +} + +@available(macOS 13.0, *) +class AppFetcher: ObservableObject { + @Published var appIcon: NSImage? = nil + @Published var appName = "" + + init(appBundleId: String) { + let workspace = NSWorkspace.shared + guard let appURL = workspace.urlForApplication(withBundleIdentifier: appBundleId) else { + return + } + print("path: \(appURL.path())") + appIcon = getApplicationIcon(forAppBundleIdentifier: appBundleId) + + guard let appBundle = Bundle(url: appURL) else { + return + } + appName = appBundle.applicationName + } + + func getApplicationIcon(forAppBundleIdentifier bundleIdentifier: String) -> NSImage? { + let workspace = NSWorkspace.shared + + // If the app is not running, try to get the icon from the app bundle + if let appPath = NSWorkspace.shared.urlForApplication(withBundleIdentifier: bundleIdentifier) { + let icon = workspace.icon(forFile: appPath.path(percentEncoded: false)) + return icon + } + + return nil + } +} + +extension Bundle { + var applicationName: String { + if let displayName: String = infoDictionary?["CFBundleDisplayName"] as? String { + return displayName + } else if let name: String = infoDictionary?["CFBundleName"] as? String { + return name + } + if let executableURL { + return executableURL.deletingLastPathComponent().lastPathComponent + } + return "" + } +} + +@available(macOS 13.0, *) +#Preview { + DisabledTab() +} From 00c211ecf9267ff221a6e6f533302cd17e491cf2 Mon Sep 17 00:00:00 2001 From: phlpsong Date: Thu, 18 Jan 2024 23:08:27 +0800 Subject: [PATCH 02/18] fix: refactor app list issues --- Easydict.xcodeproj/project.pbxproj | 12 + .../Utility/Swift/Bundle/Bundle+AppInfo.swift | 23 ++ .../NewApp/View/SettingView/SettingView.swift | 6 +- .../View/SettingView/Tabs/DisabledTab.swift | 209 ++++++++---------- 4 files changed, 136 insertions(+), 114 deletions(-) create mode 100644 Easydict/Feature/Utility/Swift/Bundle/Bundle+AppInfo.swift diff --git a/Easydict.xcodeproj/project.pbxproj b/Easydict.xcodeproj/project.pbxproj index dd7aefbb4..41e4ce22e 100644 --- a/Easydict.xcodeproj/project.pbxproj +++ b/Easydict.xcodeproj/project.pbxproj @@ -229,6 +229,7 @@ 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 /* DisabledTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A8685C72B552A590022534F /* DisabledTab.swift */; }; @@ -705,6 +706,7 @@ 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 /* DisabledTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisabledTab.swift; sourceTree = ""; }; @@ -1823,6 +1825,7 @@ 03CF88602B137ECB0030C199 /* Swift */ = { isa = PBXGroup; children = ( + 0A2A05A42B59755F00EEA142 /* Bundle */, 0A2BA9622B4A3CBB002872A4 /* Notification */, 0A2BA95E2B49A967002872A4 /* Binding */, 03FD68BC2B1E14B500FD388E /* String */, @@ -2003,6 +2006,14 @@ path = String; sourceTree = ""; }; + 0A2A05A42B59755F00EEA142 /* Bundle */ = { + isa = PBXGroup; + children = ( + 0A2A05A52B59757100EEA142 /* Bundle+AppInfo.swift */, + ); + path = Bundle; + sourceTree = ""; + }; 0A2BA95E2B49A967002872A4 /* Binding */ = { isa = PBXGroup; children = ( @@ -2656,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 */, 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..8e99cb95a --- /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 = infoDictionary?["CFBundleDisplayName"] as? String { + return displayName + } else if let name: String = infoDictionary?["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 7667688d1..cebd339d0 100644 --- a/Easydict/NewApp/View/SettingView/SettingView.swift +++ b/Easydict/NewApp/View/SettingView/SettingView.swift @@ -31,9 +31,9 @@ struct SettingView: View { .tabItem { Label("service", systemImage: "briefcase") } .tag(SettingTab.service) - DisabledTab() + DisabledAppTab() .tabItem { Label("disabled_app_list", systemImage: "nosign") } - .tag(SettingTab.disabled.rawValue) + .tag(SettingTab.disabled) PrivacyTab() .tabItem { Label("privacy", systemImage: "hand.raised.square") } @@ -59,7 +59,7 @@ struct SettingView: View { let originalFrame = window.frame let newSize = switch selection { - case .general, .privacy, .about: + case .general, .privacy, .about, .disabled: CGSize(width: 500, height: 520) case .service: CGSize(width: 800, height: 520) diff --git a/Easydict/NewApp/View/SettingView/Tabs/DisabledTab.swift b/Easydict/NewApp/View/SettingView/Tabs/DisabledTab.swift index f0c42b8a9..12e5403e8 100644 --- a/Easydict/NewApp/View/SettingView/Tabs/DisabledTab.swift +++ b/Easydict/NewApp/View/SettingView/Tabs/DisabledTab.swift @@ -9,10 +9,10 @@ import Combine import SwiftUI -class DisableViewModel: ObservableObject { +class DisabledAppViewModel: ObservableObject { @Published var appModelList: [EZAppModel] = [] - @Published var selectedAppModel: EZAppModel? = nil + @Published var selectedAppModels: Set = [] @Published var isImporting = false @@ -20,19 +20,24 @@ class DisableViewModel: ObservableObject { appModelList = EZLocalStorage.shared().selectTextTypeAppModelList } - func removeDisabledApp() { - appModelList = appModelList.filter { $0.appBundleID != selectedAppModel?.appBundleID } + func saveDisabledApps() { EZLocalStorage.shared().selectTextTypeAppModelList = appModelList } - func newAppSelected(for url: URL) { - guard let newSelectApp = newBlockApps(url: url) else { return } + func removeDisabledApp() { + appModelList = appModelList.filter { !selectedAppModels.contains($0) } + saveDisabledApps() + selectedAppModels = [] + } + func newAppSelected(for url: URL) { + guard let newSelectApp = newDisabledApp(from: url) else { return } + guard !appModelList.contains(newSelectApp) else { return } appModelList.append(newSelectApp) - EZLocalStorage.shared().selectTextTypeAppModelList = appModelList + saveDisabledApps() } - func newBlockApps(url: URL) -> EZAppModel? { + func newDisabledApp(from url: URL) -> EZAppModel? { let appModel = EZAppModel() guard let bundle = Bundle(url: url) else { return nil } appModel.appBundleID = bundle.bundleIdentifier ?? "" @@ -42,45 +47,56 @@ class DisableViewModel: ObservableObject { } @available(macOS 13.0, *) -struct DisabledTab: View { - - @ObservedObject var viewModel = DisableViewModel() +struct DisabledAppTab: View { + @Environment(\.colorScheme) private var colorScheme - var appListView: some View { - VStack(spacing: 0) { - List { - ForEach(viewModel.appModelList, id: \.self) { app in - BlockAppItemView(with: app) - .tag(app) - .environmentObject(viewModel) - } - .listRowSeparator(.hidden) - } - .listStyle(.plain) - - ListToolbar() - .environmentObject(viewModel) - .fileImporter( - isPresented: $viewModel.isImporting, - allowedContentTypes: [.application], - allowsMultipleSelection: true - ) { result in - switch result { - case let .success(urls): - urls.forEach { url in - let gotAccess = url.startAccessingSecurityScopedResource() - if !gotAccess { return } - viewModel.newAppSelected(for: url) - url.stopAccessingSecurityScopedResource() - } - case let .failure(error): - print("error: \(error)") + @ObservedObject var disabledAppViewModel = DisabledAppViewModel() + + var listToolbar: some View { + ListToolbar() + .fileImporter( + isPresented: $disabledAppViewModel.isImporting, + allowedContentTypes: [.application], + allowsMultipleSelection: true + ) { result in + switch result { + case let .success(urls): + urls.forEach { url in + let gotAccess = url.startAccessingSecurityScopedResource() + if !gotAccess { return } + disabledAppViewModel.newAppSelected(for: url) + url.stopAccessingSecurityScopedResource() } + case let .failure(error): + print("fileImporter error: \(error)") } + } + } + + 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 } - .frame(maxWidth: 420) .clipShape(RoundedRectangle(cornerRadius: 8)) - .padding([.bottom]) + .padding(.bottom) + .padding(.horizontal, 40) + .onTapGesture { + disabledAppViewModel.selectedAppModels = [] + } } var body: some View { @@ -88,41 +104,37 @@ struct DisabledTab: View { Text("disabled_title") .padding() - appListView + appListViewWithToolbar } + .environmentObject(disabledAppViewModel) .task { - viewModel.fetchDisabledApps() + disabledAppViewModel.fetchDisabledApps() } } } @available(macOS 13.0, *) struct ListToolbar: View { - @Environment(\.colorScheme) private var colorScheme - - @EnvironmentObject var viewModel: DisableViewModel - - var bgColor: Color { - Color(nsColor: colorScheme == .light ? NSColor.controlBackgroundColor : NSColor.controlBackgroundColor) - } + @EnvironmentObject private var disabledAppViewModel: DisabledAppViewModel var body: some View { VStack(spacing: 0) { Divider() HStack(spacing: 0) { ListButton(imageName: "plus") { - viewModel.isImporting.toggle() + disabledAppViewModel.isImporting.toggle() } Divider() ListButton(imageName: "minus") { - viewModel.removeDisabledApp() + disabledAppViewModel.removeDisabledApp() } + .disabled(disabledAppViewModel.selectedAppModels.isEmpty) Spacer() } .padding(2) } .frame(height: 28) - .background(bgColor) + .background(Color(.controlBackgroundColor)) } } @@ -136,36 +148,37 @@ struct ListButton: View { action() }) { Image(systemName: imageName) + .resizable() + .scaledToFit() + .frame(width: 12, height: 12) + .padding(6) + .contentShape(Rectangle()) } .buttonStyle(BorderlessButtonStyle()) - .contentShape(Rectangle()) - .frame(width: 24, height: 24) } } @available(macOS 13.0, *) struct BlockAppItemView: View { - var app: EZAppModel - - @ObservedObject var appFetcher: AppFetcher + @StateObject private var appFetcher: AppFetcher - @Environment(\.colorScheme) private var colorScheme + @EnvironmentObject var disabledAppViewModel: DisabledAppViewModel - @EnvironmentObject var viewModel: DisableViewModel - - private var tableColor: Color { - Color(nsColor: colorScheme == .light ? .ez_tableRowViewBgLight() : .ez_tableRowViewBgDark()) + private var listRowBgColor: Color { + disabledAppViewModel.selectedAppModels.contains { + $0.appBundleID == appFetcher.appModel.appBundleID + } ? Color("service_cell_highlight") : .clear } init(with appModel: EZAppModel) { - app = appModel - appFetcher = AppFetcher(appBundleId: app.appBundleID) + _appFetcher = StateObject(wrappedValue: AppFetcher(appModel: appModel)) } var body: some View { HStack(alignment: .center) { Image(nsImage: appFetcher.appIcon ?? NSImage()) .resizable() + .scaledToFit() .frame(width: 24, height: 24) Text(appFetcher.appName) @@ -175,67 +188,41 @@ struct BlockAppItemView: View { .frame(maxWidth: .infinity) .contentShape(Rectangle()) .padding(.vertical, 4) - .overlay { - TapHandler { - let selectedAppModel = viewModel.selectedAppModel - if selectedAppModel == nil || selectedAppModel != app { - viewModel.selectedAppModel = app - } else { - viewModel.selectedAppModel = nil - } - } + .padding(.leading, 6) + .task { + appFetcher.getAppBundleInfo() } - .listRowBackground(viewModel.selectedAppModel == app ? Color("service_cell_highlight") : .clear) } } @available(macOS 13.0, *) class AppFetcher: ObservableObject { @Published var appIcon: NSImage? = nil + @Published var appName = "" - init(appBundleId: String) { - let workspace = NSWorkspace.shared - guard let appURL = workspace.urlForApplication(withBundleIdentifier: appBundleId) else { - return - } - print("path: \(appURL.path())") - appIcon = getApplicationIcon(forAppBundleIdentifier: appBundleId) + var appModel: EZAppModel - guard let appBundle = Bundle(url: appURL) else { - return - } - appName = appBundle.applicationName + init(appModel: EZAppModel) { + self.appModel = appModel } - func getApplicationIcon(forAppBundleIdentifier bundleIdentifier: String) -> NSImage? { + func getAppBundleInfo() { + let appBundleId = appModel.appBundleID let workspace = NSWorkspace.shared - - // If the app is not running, try to get the icon from the app bundle - if let appPath = NSWorkspace.shared.urlForApplication(withBundleIdentifier: bundleIdentifier) { - let icon = workspace.icon(forFile: appPath.path(percentEncoded: false)) - return icon - } - - return nil - } -} - -extension Bundle { - var applicationName: String { - if let displayName: String = infoDictionary?["CFBundleDisplayName"] as? String { - return displayName - } else if let name: String = infoDictionary?["CFBundleName"] as? String { - return name - } - if let executableURL { - return executableURL.deletingLastPathComponent().lastPathComponent - } - return "" + 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 { - DisabledTab() + DisabledAppTab() } From 90c026d769cc5a42ee34aa20b1dfcd87ca9b4abb Mon Sep 17 00:00:00 2001 From: phlpsong Date: Thu, 18 Jan 2024 23:27:22 +0800 Subject: [PATCH 03/18] fix: refactor disabled app tab --- Easydict.xcodeproj/project.pbxproj | 8 ++-- ...DisabledTab.swift => DisabledAppTab.swift} | 40 ++++++++++--------- 2 files changed, 26 insertions(+), 22 deletions(-) rename Easydict/NewApp/View/SettingView/Tabs/{DisabledTab.swift => DisabledAppTab.swift} (87%) diff --git a/Easydict.xcodeproj/project.pbxproj b/Easydict.xcodeproj/project.pbxproj index 41e4ce22e..c1c23e80f 100644 --- a/Easydict.xcodeproj/project.pbxproj +++ b/Easydict.xcodeproj/project.pbxproj @@ -232,7 +232,7 @@ 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 /* DisabledTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A8685C72B552A590022534F /* DisabledTab.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 */; }; @@ -709,7 +709,7 @@ 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 /* DisabledTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisabledTab.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 = ""; }; @@ -2090,7 +2090,7 @@ EAED41EA2B54A4900005FE0A /* ServiceConfiguration */, 278540332B3DE04F004E9488 /* GeneralTab.swift */, 0A057D6C2B499A000025C51D /* ServiceTab.swift */, - 0A8685C72B552A590022534F /* DisabledTab.swift */, + 0A8685C72B552A590022534F /* DisabledAppTab.swift */, 276742042B3DC230002A2C75 /* PrivacyTab.swift */, 276742052B3DC230002A2C75 /* AboutTab.swift */, ); @@ -2707,7 +2707,7 @@ 17BCAEF82B0DFF9000A7D372 /* EZNiuTransTranslate.m in Sources */, 039F5506294B6E29004AB940 /* EZSettingViewController.m in Sources */, 03BD281E29481C0400F5891A /* EZAudioPlayer.m in Sources */, - 0A8685C82B552A590022534F /* DisabledTab.swift 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/NewApp/View/SettingView/Tabs/DisabledTab.swift b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift similarity index 87% rename from Easydict/NewApp/View/SettingView/Tabs/DisabledTab.swift rename to Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift index 12e5403e8..3ba038389 100644 --- a/Easydict/NewApp/View/SettingView/Tabs/DisabledTab.swift +++ b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift @@ -1,5 +1,5 @@ // -// DisabledTab.swift +// DisabledAppTab.swift // Easydict // // Created by phlpsong on 2024/1/15. @@ -30,14 +30,23 @@ class DisabledAppViewModel: ObservableObject { selectedAppModels = [] } - func newAppSelected(for url: URL) { - guard let newSelectApp = newDisabledApp(from: url) else { return } - guard !appModelList.contains(newSelectApp) else { return } - appModelList.append(newSelectApp) + 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 newDisabledApp(from url: URL) -> EZAppModel? { + func disabledAppModel(from url: URL) -> EZAppModel? { let appModel = EZAppModel() guard let bundle = Bundle(url: url) else { return nil } appModel.appBundleID = bundle.bundleIdentifier ?? "" @@ -48,8 +57,6 @@ class DisabledAppViewModel: ObservableObject { @available(macOS 13.0, *) struct DisabledAppTab: View { - @Environment(\.colorScheme) private var colorScheme - @ObservedObject var disabledAppViewModel = DisabledAppViewModel() var listToolbar: some View { @@ -61,18 +68,13 @@ struct DisabledAppTab: View { ) { result in switch result { case let .success(urls): - urls.forEach { url in - let gotAccess = url.startAccessingSecurityScopedResource() - if !gotAccess { return } - disabledAppViewModel.newAppSelected(for: url) - url.stopAccessingSecurityScopedResource() - } + disabledAppViewModel.newAppURLsSelected(from: urls) case let .failure(error): print("fileImporter error: \(error)") } } } - + var appListView: some View { List(selection: $disabledAppViewModel.selectedAppModels) { ForEach(disabledAppViewModel.appModelList, id: \.self) { app in @@ -93,7 +95,7 @@ struct DisabledAppTab: View { } .clipShape(RoundedRectangle(cornerRadius: 8)) .padding(.bottom) - .padding(.horizontal, 40) + .padding(.horizontal, 35) .onTapGesture { disabledAppViewModel.selectedAppModels = [] } @@ -106,8 +108,9 @@ struct DisabledAppTab: View { appListViewWithToolbar } + .frame(maxWidth: 500) .environmentObject(disabledAppViewModel) - .task { + .onAppear { disabledAppViewModel.fetchDisabledApps() } } @@ -187,6 +190,7 @@ struct BlockAppItemView: View { } .frame(maxWidth: .infinity) .contentShape(Rectangle()) + .listRowBackground(listRowBgColor) .padding(.vertical, 4) .padding(.leading, 6) .task { @@ -212,7 +216,7 @@ class AppFetcher: ObservableObject { 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)) From 34cb578cf7f7f207a913db8d6e9db1fd58048912 Mon Sep 17 00:00:00 2001 From: phlpsong Date: Fri, 19 Jan 2024 10:37:03 +0800 Subject: [PATCH 04/18] fix: remove list row bg color --- Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift index 3ba038389..5893730ef 100644 --- a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift +++ b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift @@ -167,12 +167,6 @@ struct BlockAppItemView: View { @EnvironmentObject var disabledAppViewModel: DisabledAppViewModel - private var listRowBgColor: Color { - disabledAppViewModel.selectedAppModels.contains { - $0.appBundleID == appFetcher.appModel.appBundleID - } ? Color("service_cell_highlight") : .clear - } - init(with appModel: EZAppModel) { _appFetcher = StateObject(wrappedValue: AppFetcher(appModel: appModel)) } @@ -190,7 +184,6 @@ struct BlockAppItemView: View { } .frame(maxWidth: .infinity) .contentShape(Rectangle()) - .listRowBackground(listRowBgColor) .padding(.vertical, 4) .padding(.leading, 6) .task { From 502a3468be5645fdcdd607232fa4655a8df529a5 Mon Sep 17 00:00:00 2001 From: phlpsong Date: Fri, 19 Jan 2024 11:18:54 +0800 Subject: [PATCH 05/18] fix: bundle application name issue --- Easydict/Feature/Utility/Swift/Bundle/Bundle+AppInfo.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Easydict/Feature/Utility/Swift/Bundle/Bundle+AppInfo.swift b/Easydict/Feature/Utility/Swift/Bundle/Bundle+AppInfo.swift index 8e99cb95a..c095084cb 100644 --- a/Easydict/Feature/Utility/Swift/Bundle/Bundle+AppInfo.swift +++ b/Easydict/Feature/Utility/Swift/Bundle/Bundle+AppInfo.swift @@ -10,9 +10,9 @@ import Foundation extension Bundle { var applicationName: String { - if let displayName: String = infoDictionary?["CFBundleDisplayName"] as? String { + if let displayName: String = object(forInfoDictionaryKey: "CFBundleDisplayName") as? String { return displayName - } else if let name: String = infoDictionary?["CFBundleName"] as? String { + } else if let name: String = object(forInfoDictionaryKey: "CFBundleName") as? String { return name } if let executableURL { From ff36390afd2b4b6ccf97071c0125aa4375dcb17f Mon Sep 17 00:00:00 2001 From: phlpsong Date: Fri, 19 Jan 2024 12:18:10 +0800 Subject: [PATCH 06/18] fix: update code for review comments --- Easydict/App/Localizable.xcstrings | 17 +++++++++++++++ .../SettingView/Tabs/DisabledAppTab.swift | 21 ++++++++++++------- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/Easydict/App/Localizable.xcstrings b/Easydict/App/Localizable.xcstrings index 2114e3a63..55c00671f 100644 --- a/Easydict/App/Localizable.xcstrings +++ b/Easydict/App/Localizable.xcstrings @@ -2415,6 +2415,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/NewApp/View/SettingView/Tabs/DisabledAppTab.swift b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift index 5893730ef..d12c0f4cd 100644 --- a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift +++ b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift @@ -16,6 +16,12 @@ class DisabledAppViewModel: ObservableObject { @Published var isImporting = false + @Published var isShowImportErrorAlert = false + + init() { + fetchDisabledApps() + } + func fetchDisabledApps() { appModelList = EZLocalStorage.shared().selectTextTypeAppModelList } @@ -57,7 +63,7 @@ class DisabledAppViewModel: ObservableObject { @available(macOS 13.0, *) struct DisabledAppTab: View { - @ObservedObject var disabledAppViewModel = DisabledAppViewModel() + @StateObject var disabledAppViewModel = DisabledAppViewModel() var listToolbar: some View { ListToolbar() @@ -71,8 +77,12 @@ struct DisabledAppTab: View { 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 { @@ -110,14 +120,11 @@ struct DisabledAppTab: View { } .frame(maxWidth: 500) .environmentObject(disabledAppViewModel) - .onAppear { - disabledAppViewModel.fetchDisabledApps() - } } } @available(macOS 13.0, *) -struct ListToolbar: View { +private struct ListToolbar: View { @EnvironmentObject private var disabledAppViewModel: DisabledAppViewModel var body: some View { @@ -142,7 +149,7 @@ struct ListToolbar: View { } @available(macOS 13.0, *) -struct ListButton: View { +private struct ListButton: View { var imageName: String var action: () -> Void @@ -162,7 +169,7 @@ struct ListButton: View { } @available(macOS 13.0, *) -struct BlockAppItemView: View { +private struct BlockAppItemView: View { @StateObject private var appFetcher: AppFetcher @EnvironmentObject var disabledAppViewModel: DisabledAppViewModel From 75d3b565339798b22f4bf06fb9647f9dc7c62253 Mon Sep 17 00:00:00 2001 From: phlpsong Date: Fri, 19 Jan 2024 13:01:26 +0800 Subject: [PATCH 07/18] fix: update app item view model --- .../View/SettingView/Tabs/DisabledAppTab.swift | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift index d12c0f4cd..3692ad44d 100644 --- a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift +++ b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift @@ -170,22 +170,22 @@ private struct ListButton: View { @available(macOS 13.0, *) private struct BlockAppItemView: View { - @StateObject private var appFetcher: AppFetcher + @StateObject private var appItemViewModel: AppItemViewModel @EnvironmentObject var disabledAppViewModel: DisabledAppViewModel init(with appModel: EZAppModel) { - _appFetcher = StateObject(wrappedValue: AppFetcher(appModel: appModel)) + _appItemViewModel = StateObject(wrappedValue: AppItemViewModel(appModel: appModel)) } var body: some View { HStack(alignment: .center) { - Image(nsImage: appFetcher.appIcon ?? NSImage()) + Image(nsImage: appItemViewModel.appIcon ?? NSImage()) .resizable() .scaledToFit() .frame(width: 24, height: 24) - Text(appFetcher.appName) + Text(appItemViewModel.appName) Spacer() } @@ -193,14 +193,11 @@ private struct BlockAppItemView: View { .contentShape(Rectangle()) .padding(.vertical, 4) .padding(.leading, 6) - .task { - appFetcher.getAppBundleInfo() - } } } @available(macOS 13.0, *) -class AppFetcher: ObservableObject { +private class AppItemViewModel: ObservableObject { @Published var appIcon: NSImage? = nil @Published var appName = "" @@ -209,6 +206,7 @@ class AppFetcher: ObservableObject { init(appModel: EZAppModel) { self.appModel = appModel + getAppBundleInfo() } func getAppBundleInfo() { From ceb5e3648b6b111dc26ffa636544dcd86c74a003 Mon Sep 17 00:00:00 2001 From: phlpsong Date: Fri, 19 Jan 2024 13:16:06 +0800 Subject: [PATCH 08/18] fix: remove item view model --- .../SettingView/Tabs/DisabledAppTab.swift | 33 +++++++------------ 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift index 3692ad44d..62c131753 100644 --- a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift +++ b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift @@ -88,7 +88,7 @@ struct DisabledAppTab: View { var appListView: some View { List(selection: $disabledAppViewModel.selectedAppModels) { ForEach(disabledAppViewModel.appModelList, id: \.self) { app in - BlockAppItemView(with: app) + BlockAppItemView(appModel: app) .tag(app) } .listRowSeparator(.hidden) @@ -170,22 +170,22 @@ private struct ListButton: View { @available(macOS 13.0, *) private struct BlockAppItemView: View { - @StateObject private var appItemViewModel: AppItemViewModel - @EnvironmentObject var disabledAppViewModel: DisabledAppViewModel - init(with appModel: EZAppModel) { - _appItemViewModel = StateObject(wrappedValue: AppItemViewModel(appModel: appModel)) - } + var appModel: EZAppModel + + @State private var appIcon: NSImage = .init() + + @State private var appName = "" var body: some View { HStack(alignment: .center) { - Image(nsImage: appItemViewModel.appIcon ?? NSImage()) + Image(nsImage: appIcon) .resizable() .scaledToFit() .frame(width: 24, height: 24) - Text(appItemViewModel.appName) + Text(appName) Spacer() } @@ -193,20 +193,9 @@ private struct BlockAppItemView: View { .contentShape(Rectangle()) .padding(.vertical, 4) .padding(.leading, 6) - } -} - -@available(macOS 13.0, *) -private class AppItemViewModel: ObservableObject { - @Published var appIcon: NSImage? = nil - - @Published var appName = "" - - var appModel: EZAppModel - - init(appModel: EZAppModel) { - self.appModel = appModel - getAppBundleInfo() + .onAppear { + getAppBundleInfo() + } } func getAppBundleInfo() { From 8f8cf1bbd987178907325d6ea149ce725e6eb84d Mon Sep 17 00:00:00 2001 From: phlpsong Date: Fri, 19 Jan 2024 14:10:09 +0800 Subject: [PATCH 09/18] fix: refactor disable app item view --- .../SettingView/Tabs/DisabledAppTab.swift | 47 ++++++++++--------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift index 62c131753..1853c41fb 100644 --- a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift +++ b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift @@ -88,7 +88,7 @@ struct DisabledAppTab: View { var appListView: some View { List(selection: $disabledAppViewModel.selectedAppModels) { ForEach(disabledAppViewModel.appModelList, id: \.self) { app in - BlockAppItemView(appModel: app) + BlockAppItemView(with: app) .tag(app) } .listRowSeparator(.hidden) @@ -172,11 +172,33 @@ private struct ListButton: View { private struct BlockAppItemView: View { @EnvironmentObject var disabledAppViewModel: DisabledAppViewModel - var appModel: EZAppModel + let appIcon: NSImage + let appName: String - @State private var appIcon: NSImage = .init() + 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 + } - @State private var appName = "" + 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) { @@ -193,23 +215,6 @@ private struct BlockAppItemView: View { .contentShape(Rectangle()) .padding(.vertical, 4) .padding(.leading, 6) - .onAppear { - 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 } } From 67aac61f5368a4d25544a22dc7f1a99da048f623 Mon Sep 17 00:00:00 2001 From: tisfeng Date: Fri, 19 Jan 2024 23:41:48 +0800 Subject: [PATCH 10/18] perf: adjust add & minus bg color --- .../Contents.json | 38 +++++++++++++++++++ Easydict/App/Localizable.xcstrings | 3 ++ .../SettingView/Tabs/DisabledAppTab.swift | 2 +- 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 Easydict/App/Assets.xcassets/setting_add_minus_bg.colorset/Contents.json diff --git a/Easydict/App/Assets.xcassets/setting_add_minus_bg.colorset/Contents.json b/Easydict/App/Assets.xcassets/setting_add_minus_bg.colorset/Contents.json new file mode 100644 index 000000000..a83dbf8e7 --- /dev/null +++ b/Easydict/App/Assets.xcassets/setting_add_minus_bg.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/Localizable.xcstrings b/Easydict/App/Localizable.xcstrings index 55c00671f..aacf0329e 100644 --- a/Easydict/App/Localizable.xcstrings +++ b/Easydict/App/Localizable.xcstrings @@ -1,6 +1,9 @@ { "sourceLanguage" : "en", "strings" : { + "" : { + + }, "about" : { "comment" : "about", "localizations" : { diff --git a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift index 1853c41fb..646882a08 100644 --- a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift +++ b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift @@ -144,7 +144,7 @@ private struct ListToolbar: View { .padding(2) } .frame(height: 28) - .background(Color(.controlBackgroundColor)) + .background(Color("setting_add_minus_bg")) } } From 2187752a7a567cefa4277aef0a4bc656d7d1b658 Mon Sep 17 00:00:00 2001 From: tisfeng Date: Fri, 19 Jan 2024 23:55:44 +0800 Subject: [PATCH 11/18] perf: add a border for list --- .../App/Assets.xcassets/Colors/Contents.json | 6 +++ .../Contents.json | 0 .../Contents.json | 0 .../Contents.json | 38 +++++++++++++++++++ .../SettingView/Tabs/DisabledAppTab.swift | 4 ++ 5 files changed, 48 insertions(+) create mode 100644 Easydict/App/Assets.xcassets/Colors/Contents.json rename Easydict/App/Assets.xcassets/{ => Colors}/service_cell_highlight.colorset/Contents.json (100%) rename Easydict/App/Assets.xcassets/{ => Colors}/setting_add_minus_bg.colorset/Contents.json (100%) create mode 100644 Easydict/App/Assets.xcassets/Colors/setting_list_border.colorset/Contents.json 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/service_cell_highlight.colorset/Contents.json b/Easydict/App/Assets.xcassets/Colors/service_cell_highlight.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.colorset/Contents.json diff --git a/Easydict/App/Assets.xcassets/setting_add_minus_bg.colorset/Contents.json b/Easydict/App/Assets.xcassets/Colors/setting_add_minus_bg.colorset/Contents.json similarity index 100% rename from Easydict/App/Assets.xcassets/setting_add_minus_bg.colorset/Contents.json rename to Easydict/App/Assets.xcassets/Colors/setting_add_minus_bg.colorset/Contents.json diff --git a/Easydict/App/Assets.xcassets/Colors/setting_list_border.colorset/Contents.json b/Easydict/App/Assets.xcassets/Colors/setting_list_border.colorset/Contents.json new file mode 100644 index 000000000..d60e3bb57 --- /dev/null +++ b/Easydict/App/Assets.xcassets/Colors/setting_list_border.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/NewApp/View/SettingView/Tabs/DisabledAppTab.swift b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift index 646882a08..baa241c10 100644 --- a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift +++ b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift @@ -104,6 +104,10 @@ struct DisabledAppTab: View { listToolbar } .clipShape(RoundedRectangle(cornerRadius: 8)) + .overlay(content: { + RoundedRectangle(cornerRadius: 8) + .stroke(Color("setting_list_border"), lineWidth: 0.5) + }) .padding(.bottom) .padding(.horizontal, 35) .onTapGesture { From d7dbab7bb8cc5f04767cd7d5082d617828d1d74b Mon Sep 17 00:00:00 2001 From: tisfeng Date: Sat, 20 Jan 2024 00:36:05 +0800 Subject: [PATCH 12/18] perf: adjust custom color name --- .../Contents.json | 0 .../Contents.json | 0 .../Contents.json | 0 .../NewApp/View/SettingView/Tabs/DisabledAppTab.swift | 8 +++++--- Easydict/NewApp/View/SettingView/Tabs/ServiceTab.swift | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) rename Easydict/App/Assets.xcassets/Colors/{setting_add_minus_bg.colorset => add_minus_bg_color.colorset}/Contents.json (100%) rename Easydict/App/Assets.xcassets/Colors/{setting_list_border.colorset => list_border_color.colorset}/Contents.json (100%) rename Easydict/App/Assets.xcassets/Colors/{service_cell_highlight.colorset => service_cell_highlight_color.colorset}/Contents.json (100%) diff --git a/Easydict/App/Assets.xcassets/Colors/setting_add_minus_bg.colorset/Contents.json b/Easydict/App/Assets.xcassets/Colors/add_minus_bg_color.colorset/Contents.json similarity index 100% rename from Easydict/App/Assets.xcassets/Colors/setting_add_minus_bg.colorset/Contents.json rename to Easydict/App/Assets.xcassets/Colors/add_minus_bg_color.colorset/Contents.json diff --git a/Easydict/App/Assets.xcassets/Colors/setting_list_border.colorset/Contents.json b/Easydict/App/Assets.xcassets/Colors/list_border_color.colorset/Contents.json similarity index 100% rename from Easydict/App/Assets.xcassets/Colors/setting_list_border.colorset/Contents.json rename to Easydict/App/Assets.xcassets/Colors/list_border_color.colorset/Contents.json diff --git a/Easydict/App/Assets.xcassets/Colors/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/Colors/service_cell_highlight.colorset/Contents.json rename to Easydict/App/Assets.xcassets/Colors/service_cell_highlight_color.colorset/Contents.json diff --git a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift index baa241c10..793b87d3b 100644 --- a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift +++ b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift @@ -106,7 +106,7 @@ struct DisabledAppTab: View { .clipShape(RoundedRectangle(cornerRadius: 8)) .overlay(content: { RoundedRectangle(cornerRadius: 8) - .stroke(Color("setting_list_border"), lineWidth: 0.5) + .stroke(Color("list_border_color"), lineWidth: 0.5) }) .padding(.bottom) .padding(.horizontal, 35) @@ -148,7 +148,7 @@ private struct ListToolbar: View { .padding(2) } .frame(height: 28) - .background(Color("setting_add_minus_bg")) + .background(Color("add_minus_bg_color")) } } @@ -164,9 +164,11 @@ private struct ListButton: View { Image(systemName: imageName) .resizable() .scaledToFit() - .frame(width: 12, height: 12) + .frame(width: 10, height: 10) .padding(6) .contentShape(Rectangle()) + .foregroundStyle(Color(.secondaryLabelColor)) + .font(.system(size: 14, weight: .semibold)) } .buttonStyle(BorderlessButtonStyle()) } 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 d9ad76b5ad5d4cf42846e4580e5ad2d3d1aaedc9 Mon Sep 17 00:00:00 2001 From: tisfeng Date: Sat, 20 Jan 2024 00:49:44 +0800 Subject: [PATCH 13/18] perf: show minus image color according to enable state --- .../NewApp/View/SettingView/Tabs/DisabledAppTab.swift | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift index 793b87d3b..b33918990 100644 --- a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift +++ b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift @@ -135,14 +135,15 @@ private struct ListToolbar: View { VStack(spacing: 0) { Divider() HStack(spacing: 0) { - ListButton(imageName: "plus") { + ListButton(imageName: "plus", enabled: true) { disabledAppViewModel.isImporting.toggle() } Divider() - ListButton(imageName: "minus") { + let isNoSelectedApps = disabledAppViewModel.selectedAppModels.isEmpty + ListButton(imageName: "minus", enabled: !isNoSelectedApps) { disabledAppViewModel.removeDisabledApp() } - .disabled(disabledAppViewModel.selectedAppModels.isEmpty) + .disabled(isNoSelectedApps) Spacer() } .padding(2) @@ -155,6 +156,7 @@ private struct ListToolbar: View { @available(macOS 13.0, *) private struct ListButton: View { var imageName: String + var enabled: Bool var action: () -> Void var body: some View { @@ -167,7 +169,7 @@ private struct ListButton: View { .frame(width: 10, height: 10) .padding(6) .contentShape(Rectangle()) - .foregroundStyle(Color(.secondaryLabelColor)) + .foregroundStyle(enabled ? Color(.secondaryLabelColor) : Color(.quaternaryLabelColor)) .font(.system(size: 14, weight: .semibold)) } .buttonStyle(BorderlessButtonStyle()) From 250c01ca52c5e40875c0baa720de4d51c9c12e32 Mon Sep 17 00:00:00 2001 From: tisfeng Date: Sat, 20 Jan 2024 01:37:39 +0800 Subject: [PATCH 14/18] perf: adjust disabled tab UI --- .../View/SettingView/Tabs/DisabledAppTab.swift | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift index b33918990..3e0d9d6d1 100644 --- a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift +++ b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift @@ -11,11 +11,8 @@ import SwiftUI class DisabledAppViewModel: ObservableObject { @Published var appModelList: [EZAppModel] = [] - @Published var selectedAppModels: Set = [] - @Published var isImporting = false - @Published var isShowImportErrorAlert = false init() { @@ -108,8 +105,8 @@ struct DisabledAppTab: View { RoundedRectangle(cornerRadius: 8) .stroke(Color("list_border_color"), lineWidth: 0.5) }) - .padding(.bottom) - .padding(.horizontal, 35) + .padding(.horizontal, 25) + .padding(.bottom, 25) .onTapGesture { disabledAppViewModel.selectedAppModels = [] } @@ -118,11 +115,11 @@ struct DisabledAppTab: View { var body: some View { VStack { Text("disabled_title") - .padding() + .padding(.top, 18) + .padding(.bottom, 8) appListViewWithToolbar } - .frame(maxWidth: 500) .environmentObject(disabledAppViewModel) } } @@ -138,7 +135,7 @@ private struct ListToolbar: View { ListButton(imageName: "plus", enabled: true) { disabledAppViewModel.isImporting.toggle() } - Divider() + Divider().padding(.vertical, 1) let isNoSelectedApps = disabledAppViewModel.selectedAppModels.isEmpty ListButton(imageName: "minus", enabled: !isNoSelectedApps) { disabledAppViewModel.removeDisabledApp() @@ -167,9 +164,9 @@ private struct ListButton: View { .resizable() .scaledToFit() .frame(width: 10, height: 10) - .padding(6) + .padding(.horizontal, 8) .contentShape(Rectangle()) - .foregroundStyle(enabled ? Color(.secondaryLabelColor) : Color(.quaternaryLabelColor)) + .foregroundStyle(enabled ? Color(.secondaryLabelColor) : Color(.tertiaryLabelColor)) .font(.system(size: 14, weight: .semibold)) } .buttonStyle(BorderlessButtonStyle()) From 37d53e74ddaf082cd4f4903af8187642a3bbb3db Mon Sep 17 00:00:00 2001 From: phlpsong Date: Sat, 20 Jan 2024 09:36:22 +0800 Subject: [PATCH 15/18] fix: add disabled title horizontal padding --- Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift index 3e0d9d6d1..ee2752800 100644 --- a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift +++ b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift @@ -115,6 +115,7 @@ struct DisabledAppTab: View { var body: some View { VStack { Text("disabled_title") + .padding(.horizontal) .padding(.top, 18) .padding(.bottom, 8) From 93e2fe6dcc973bfa76b90c84e6ae0be8acc572b0 Mon Sep 17 00:00:00 2001 From: phlpsong Date: Sat, 20 Jan 2024 14:59:12 +0800 Subject: [PATCH 16/18] fix: code refactor --- .../SettingView/Tabs/DisabledAppTab.swift | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift index ee2752800..86a161507 100644 --- a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift +++ b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift @@ -9,7 +9,7 @@ import Combine import SwiftUI -class DisabledAppViewModel: ObservableObject { +private class DisabledAppViewModel: ObservableObject { @Published var appModelList: [EZAppModel] = [] @Published var selectedAppModels: Set = [] @Published var isImporting = false @@ -60,7 +60,7 @@ class DisabledAppViewModel: ObservableObject { @available(macOS 13.0, *) struct DisabledAppTab: View { - @StateObject var disabledAppViewModel = DisabledAppViewModel() + @StateObject private var disabledAppViewModel = DisabledAppViewModel() var listToolbar: some View { ListToolbar() @@ -133,15 +133,16 @@ private struct ListToolbar: View { VStack(spacing: 0) { Divider() HStack(spacing: 0) { - ListButton(imageName: "plus", enabled: true) { + ListButton(systemName: "plus") { disabledAppViewModel.isImporting.toggle() } - Divider().padding(.vertical, 1) - let isNoSelectedApps = disabledAppViewModel.selectedAppModels.isEmpty - ListButton(imageName: "minus", enabled: !isNoSelectedApps) { + .environment(\.isEnabled, true) + Divider() + .padding(.vertical, 1) + ListButton(systemName: "minus") { disabledAppViewModel.removeDisabledApp() } - .disabled(isNoSelectedApps) + .environment(\.isEnabled, !disabledAppViewModel.selectedAppModels.isEmpty) Spacer() } .padding(2) @@ -153,24 +154,25 @@ private struct ListToolbar: View { @available(macOS 13.0, *) private struct ListButton: View { - var imageName: String - var enabled: Bool + @Environment(\.isEnabled) private var isEnabled: Bool + var systemName: String var action: () -> Void var body: some View { Button(action: { action() }) { - Image(systemName: imageName) + Image(systemName: systemName) .resizable() .scaledToFit() .frame(width: 10, height: 10) .padding(.horizontal, 8) .contentShape(Rectangle()) - .foregroundStyle(enabled ? Color(.secondaryLabelColor) : Color(.tertiaryLabelColor)) + .foregroundStyle(isEnabled ? Color(.secondaryLabelColor) : Color(.tertiaryLabelColor)) .font(.system(size: 14, weight: .semibold)) } .buttonStyle(BorderlessButtonStyle()) + .disabled(isEnabled) } } From d49ee5fd2b6ccd33349a4168bec7397aea0489e8 Mon Sep 17 00:00:00 2001 From: phlpsong Date: Sat, 20 Jan 2024 15:21:08 +0800 Subject: [PATCH 17/18] fix: disabled environment --- Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift index 86a161507..b7121c403 100644 --- a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift +++ b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift @@ -136,13 +136,13 @@ private struct ListToolbar: View { ListButton(systemName: "plus") { disabledAppViewModel.isImporting.toggle() } - .environment(\.isEnabled, true) + .disabled(false) Divider() .padding(.vertical, 1) ListButton(systemName: "minus") { disabledAppViewModel.removeDisabledApp() } - .environment(\.isEnabled, !disabledAppViewModel.selectedAppModels.isEmpty) + .disabled(!disabledAppViewModel.selectedAppModels.isEmpty) Spacer() } .padding(2) @@ -172,7 +172,6 @@ private struct ListButton: View { .font(.system(size: 14, weight: .semibold)) } .buttonStyle(BorderlessButtonStyle()) - .disabled(isEnabled) } } From 86d8858063e17c0cbc13b86be2f45d191c66e0af Mon Sep 17 00:00:00 2001 From: phlpsong Date: Sat, 20 Jan 2024 15:24:46 +0800 Subject: [PATCH 18/18] fix: disable issue --- Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift index b7121c403..a121652c7 100644 --- a/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift +++ b/Easydict/NewApp/View/SettingView/Tabs/DisabledAppTab.swift @@ -142,7 +142,7 @@ private struct ListToolbar: View { ListButton(systemName: "minus") { disabledAppViewModel.removeDisabledApp() } - .disabled(!disabledAppViewModel.selectedAppModels.isEmpty) + .disabled(disabledAppViewModel.selectedAppModels.isEmpty) Spacer() } .padding(2)