diff --git a/Resource/de.lproj/Localizable.strings b/Resource/de.lproj/Localizable.strings index 6477295c..a601656c 100644 --- a/Resource/de.lproj/Localizable.strings +++ b/Resource/de.lproj/Localizable.strings @@ -119,6 +119,7 @@ "language.de" = "Deutsch"; "language.ru" = "Русский"; "language.es" = "Español"; +"language.pt" = "Português"; // MARK: General UI "ui.app" = "App"; diff --git a/Resource/en.lproj/Localizable.strings b/Resource/en.lproj/Localizable.strings index 9a447a00..97dbb12f 100644 --- a/Resource/en.lproj/Localizable.strings +++ b/Resource/en.lproj/Localizable.strings @@ -119,6 +119,7 @@ "language.de" = "Deutsch"; "language.ru" = "Русский"; "language.es" = "Español"; +"language.pt" = "Português"; // MARK: General UI "ui.app" = "App"; diff --git a/Resource/es.lproj/Localizable.strings b/Resource/es.lproj/Localizable.strings index af512c57..9650a954 100644 --- a/Resource/es.lproj/Localizable.strings +++ b/Resource/es.lproj/Localizable.strings @@ -119,6 +119,7 @@ "language.de" = "Deutsch"; "language.ru" = "Русский"; "language.es" = "Español"; +"language.pt" = "Português"; // MARK: General UI "ui.app" = "Aplicación"; diff --git a/Resource/pt.lproj/Localizable.strings b/Resource/pt.lproj/Localizable.strings index d00b3e21..b5bcb634 100644 --- a/Resource/pt.lproj/Localizable.strings +++ b/Resource/pt.lproj/Localizable.strings @@ -33,7 +33,7 @@ "cpu.temperature" = "Temp"; "gpu.temperature" = "Temp GPU"; "cpu.info" = "Info"; -"cpu.physical_cores" = Núcleos Físicos"; +"cpu.physical_cores" = "Núcleos Físicos"; "cpu.logical_cores" = "Núcleos Lógicos"; "cpu.up_time" = "Tempo de Atividade"; "cpu.thermal_level" = "Nvl. Térmico"; @@ -81,7 +81,7 @@ "temp.kelvin" = "Kelvin"; // MARK: Text Display -"text_display" = Estilo de Texto"; +"text_display" = "Estilo de Texto"; "text_display.compact" = "compacto"; "text_display.single_line" = "uma linha"; diff --git a/Resource/ru.lproj/Localizable.strings b/Resource/ru.lproj/Localizable.strings index 79f07965..626ce729 100644 --- a/Resource/ru.lproj/Localizable.strings +++ b/Resource/ru.lproj/Localizable.strings @@ -119,6 +119,7 @@ "language.de" = "Deutsch"; "language.ru" = "Русский"; "language.es" = "Español"; +"language.pt" = "Português"; // MARK: General UI "ui.app" = "Приложение"; diff --git a/Resource/zh-Hans.lproj/Localizable.strings b/Resource/zh-Hans.lproj/Localizable.strings index 0b083b24..0113df83 100644 --- a/Resource/zh-Hans.lproj/Localizable.strings +++ b/Resource/zh-Hans.lproj/Localizable.strings @@ -119,6 +119,7 @@ "language.de" = "Deutsch"; "language.ru" = "Русский"; "language.es" = "Español"; +"language.pt" = "Português"; // MARK: General UI "ui.app" = "App"; diff --git a/SharedLibrary/Extension/Int.swift b/SharedLibrary/Extension/Int.swift index a276310d..d7d26ac3 100644 --- a/SharedLibrary/Extension/Int.swift +++ b/SharedLibrary/Extension/Int.swift @@ -18,4 +18,24 @@ public extension Int { } return count } + + var readableTimeInMin: String { + if self <= 0 { + return "0 min" + } + + var result = [String]() + let hour = self / 60 + let minute = self % 60 + + if hour > 0 { + result.append("\(hour) hr") + } + + if minute > 0 { + result.append("\(minute) min") + } + + return result.joined(separator: " ") + } } diff --git a/SharedLibrary/Info.plist b/SharedLibrary/Info.plist index 77bb44b3..0b9d7f97 100644 --- a/SharedLibrary/Info.plist +++ b/SharedLibrary/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.0 + $(MARKETING_VERSION) CFBundleVersion $(CURRENT_PROJECT_VERSION) NSHumanReadableCopyright diff --git a/SharedLibrary/Utilities/ByteUnit.swift b/SharedLibrary/Utilities/ByteUnit.swift index c26b74b4..0c66128f 100644 --- a/SharedLibrary/Utilities/ByteUnit.swift +++ b/SharedLibrary/Utilities/ByteUnit.swift @@ -38,7 +38,7 @@ public struct ByteUnit { public var readable: String { switch bytes { case 0..<(kilo * kilo): - return "\(String(format: "%.\(kilobytes >= 100 ? 0 : 1)f", kilobytes)) KB" + return "\(String(format: "%.\(0)f", kilobytes)) KB" case kilo..<(kilo * kilo * kilo): return "\(String(format: "%.\(megabytes >= 100 ? 0 : 1)f", megabytes)) MB" case (kilo * kilo * kilo)...UInt64.max: diff --git a/eul.xcodeproj/project.pbxproj b/eul.xcodeproj/project.pbxproj index 2081f5c1..69cf485c 100644 --- a/eul.xcodeproj/project.pbxproj +++ b/eul.xcodeproj/project.pbxproj @@ -89,7 +89,7 @@ 6C79AD382539F9030033845C /* MenuActionButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C79AD372539F9030033845C /* MenuActionButtonView.swift */; }; 6C7A8D8A25578F8100FF52ED /* LineChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C7A8D8925578F8100FF52ED /* LineChart.swift */; }; 6C7A8D8D255802FF00FF52ED /* EulComponentConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C7A8D8C255802FF00FF52ED /* EulComponentConfig.swift */; }; - 6C7A8D9125581E7D00FF52ED /* StatusComponentConfigStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C7A8D9025581E7D00FF52ED /* StatusComponentConfigStore.swift */; }; + 6C7A8D9125581E7D00FF52ED /* ComponentConfigStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C7A8D9025581E7D00FF52ED /* ComponentConfigStore.swift */; }; 6C7CF45725568E1E00CEC263 /* Localize_Swift in Frameworks */ = {isa = PBXBuildFile; productRef = 6C7CF45625568E1E00CEC263 /* Localize_Swift */; }; 6C7CF45D25568E6200CEC263 /* MemoryEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C7CF45C25568E6200CEC263 /* MemoryEntry.swift */; }; 6C7CF4642556910D00CEC263 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6C5F8542249FACE200CF0EF8 /* Assets.xcassets */; }; @@ -147,6 +147,8 @@ 6CDE6C7D24F2AB8800463114 /* NSMenuItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CDE6C7C24F2AB8800463114 /* NSMenuItem.swift */; }; 6CE33C7F25260E3D00831857 /* PreferenceRefreshRateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CE33C7E25260E3D00831857 /* PreferenceRefreshRateView.swift */; }; 6CE7969325166916008BEB2B /* SwiftyJSON in Frameworks */ = {isa = PBXBuildFile; productRef = 6CE7969225166916008BEB2B /* SwiftyJSON */; }; + 6CEF48A2255C33CE002E4D73 /* FramePreferenceKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CEF48A1255C33CE002E4D73 /* FramePreferenceKey.swift */; }; + 6CEF48A6255C366A002E4D73 /* SizePreferenceKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CEF48A5255C366A002E4D73 /* SizePreferenceKey.swift */; }; 6CEF771224DD94C8007C3640 /* BatteryStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CEF771124DD94C8007C3640 /* BatteryStore.swift */; }; 6CEF771424DD95D7007C3640 /* BatteryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CEF771324DD95D7007C3640 /* BatteryView.swift */; }; 6CF28D0925168B8200EBE9CB /* SystemKit in Frameworks */ = {isa = PBXBuildFile; productRef = 6CF28D0825168B8200EBE9CB /* SystemKit */; }; @@ -316,6 +318,7 @@ 6C1FA41124AA1DC100CA7F71 /* MemoryStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryStore.swift; sourceTree = ""; }; 6C2688EE2556762B00FB7306 /* SharedLibrary.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SharedLibrary.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6C2688F12556762B00FB7306 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6C2F1647255C1EAD0062F76F /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/Localizable.strings; sourceTree = ""; }; 6C33CEC82517634400345977 /* StatusMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusMenuView.swift; sourceTree = ""; }; 6C33CECA251767C400345977 /* ProgressBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressBarView.swift; sourceTree = ""; }; 6C33CECC25177CE300345977 /* CpuMenuBlockView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CpuMenuBlockView.swift; sourceTree = ""; }; @@ -367,7 +370,7 @@ 6C79AD372539F9030033845C /* MenuActionButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuActionButtonView.swift; sourceTree = ""; }; 6C7A8D8925578F8100FF52ED /* LineChart.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineChart.swift; sourceTree = ""; }; 6C7A8D8C255802FF00FF52ED /* EulComponentConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EulComponentConfig.swift; sourceTree = ""; }; - 6C7A8D9025581E7D00FF52ED /* StatusComponentConfigStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusComponentConfigStore.swift; sourceTree = ""; }; + 6C7A8D9025581E7D00FF52ED /* ComponentConfigStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComponentConfigStore.swift; sourceTree = ""; }; 6C7CF45C25568E6200CEC263 /* MemoryEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryEntry.swift; sourceTree = ""; }; 6C7CF46E25569B8100CEC263 /* BatteryWidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = BatteryWidgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 6C7CF47225569B8100CEC263 /* BatteryWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatteryWidget.swift; sourceTree = ""; }; @@ -420,6 +423,8 @@ 6CDE6C7C24F2AB8800463114 /* NSMenuItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSMenuItem.swift; sourceTree = ""; }; 6CE33C7C252601BB00831857 /* Int.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Int.swift; sourceTree = ""; }; 6CE33C7E25260E3D00831857 /* PreferenceRefreshRateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferenceRefreshRateView.swift; sourceTree = ""; }; + 6CEF48A1255C33CE002E4D73 /* FramePreferenceKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FramePreferenceKey.swift; sourceTree = ""; }; + 6CEF48A5255C366A002E4D73 /* SizePreferenceKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SizePreferenceKey.swift; sourceTree = ""; }; 6CEF771124DD94C8007C3640 /* BatteryStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatteryStore.swift; sourceTree = ""; }; 6CEF771324DD95D7007C3640 /* BatteryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatteryView.swift; sourceTree = ""; }; 6CF28D0C251758EE00EBE9CB /* StatusBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusBarView.swift; sourceTree = ""; }; @@ -555,15 +560,17 @@ 6C1FA40C24AA161900CA7F71 /* Schema */ = { isa = PBXGroup; children = ( + 6C572D80254EFD5B00EF9904 /* DiskList.swift */, 6CDE6C7724F112D700463114 /* EulComponent.swift */, 6C7A8D8C255802FF00FF52ED /* EulComponentConfig.swift */, 6CDBB4C225447B7500D01EA0 /* EulMenuComponent.swift */, + 6CEF48A1255C33CE002E4D73 /* FramePreferenceKey.swift */, 6C7DB6E524E82C5A00133B06 /* Preference.swift */, + 6C79AD352539EBE60033845C /* ProcessUsage.swift */, 6C1FA40D24AA162800CA7F71 /* Refreshable.swift */, 6CDE6C7324F0047600463114 /* SizeChangeView.swift */, + 6CEF48A5255C366A002E4D73 /* SizePreferenceKey.swift */, 6C7DB6E724E82C7700133B06 /* StringEnum.swift */, - 6C79AD352539EBE60033845C /* ProcessUsage.swift */, - 6C572D80254EFD5B00EF9904 /* DiskList.swift */, ); path = Schema; sourceTree = ""; @@ -770,17 +777,17 @@ isa = PBXGroup; children = ( 6CEF771124DD94C8007C3640 /* BatteryStore.swift */, + 6C7A8D9025581E7D00FF52ED /* ComponentConfigStore.swift */, + 6CDBB4C425447D8B00D01EA0 /* ComponentsStore.swift */, 6C1FA3F924A70E6700CA7F71 /* CpuStore.swift */, 6C79AD332539E6080033845C /* CpuTopStore.swift */, + 6C572D7E254EFD4700EF9904 /* DiskStore.swift */, 6C1FA40F24AA1D4400CA7F71 /* FanStore.swift */, 6C1FA41124AA1DC100CA7F71 /* MemoryStore.swift */, 6C7DB6D024E0300E00133B06 /* NetworkStore.swift */, 6C387DC6253B08F100CBB81B /* NetworkTopStore.swift */, 6C7DB6DB24E7FFE300133B06 /* PreferenceStore.swift */, 6C457391253AC69E00BB2584 /* UIStore.swift */, - 6CDBB4C425447D8B00D01EA0 /* ComponentsStore.swift */, - 6C572D7E254EFD4700EF9904 /* DiskStore.swift */, - 6C7A8D9025581E7D00FF52ED /* StatusComponentConfigStore.swift */, ); path = Store; sourceTree = ""; @@ -1018,6 +1025,7 @@ de, ru, es, + pt, ); mainGroup = 6C5F8532249FACE000CF0EF8; packageReferences = ( @@ -1196,6 +1204,7 @@ files = ( 6CDE6C7824F112D700463114 /* EulComponent.swift in Sources */, 6C7DB6DC24E7FFE300133B06 /* PreferenceStore.swift in Sources */, + 6CEF48A2255C33CE002E4D73 /* FramePreferenceKey.swift in Sources */, 6C5FBD50253C83520016F3A2 /* MenuActionTextView.swift in Sources */, 6C1FA40E24AA162800CA7F71 /* Refreshable.swift in Sources */, 6C572D7F254EFD4700EF9904 /* DiskStore.swift in Sources */, @@ -1233,7 +1242,8 @@ 6C1FA40B24AA139300CA7F71 /* NSNotification.swift in Sources */, 6C5DAD0A2556B2FF005F67C3 /* NetworkWidget.intentdefinition in Sources */, 6C79AD382539F9030033845C /* MenuActionButtonView.swift in Sources */, - 6C7A8D9125581E7D00FF52ED /* StatusComponentConfigStore.swift in Sources */, + 6C7A8D9125581E7D00FF52ED /* ComponentConfigStore.swift in Sources */, + 6CEF48A6255C366A002E4D73 /* SizePreferenceKey.swift in Sources */, 6C7DB6D524E7A75E00133B06 /* NetworkView.swift in Sources */, 6CDBB4C325447B7500D01EA0 /* EulMenuComponent.swift in Sources */, 6CDBB4C1254462B100D01EA0 /* PreferenceSectionView.swift in Sources */, @@ -1339,6 +1349,7 @@ DE4FCF352543102B00C985E7 /* de */, 6D4A9C042546317200B9BF25 /* ru */, B00D5BCE254ABAB900395E7E /* es */, + 6C2F1647255C1EAD0062F76F /* pt */, ); name = Localizable.strings; sourceTree = ""; @@ -1361,7 +1372,7 @@ CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = M8G2RFZVFV; DYLIB_COMPATIBILITY_VERSION = 1; @@ -1375,6 +1386,7 @@ "@loader_path/Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.15; + MARKETING_VERSION = 1.0.1; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.SharedLibrary; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; @@ -1391,7 +1403,7 @@ CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = M8G2RFZVFV; DYLIB_COMPATIBILITY_VERSION = 1; @@ -1405,6 +1417,7 @@ "@loader_path/Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.15; + MARKETING_VERSION = 1.0.1; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.SharedLibrary; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; @@ -1422,7 +1435,7 @@ CODE_SIGN_ENTITLEMENTS = MemoryWidget/MemoryWidget.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 21; + CURRENT_PROJECT_VERSION = 22; DEVELOPMENT_TEAM = M8G2RFZVFV; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = MemoryWidget/Info.plist; @@ -1432,7 +1445,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.4.2; + MARKETING_VERSION = 1.4.3; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.MemoryWidget; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -1448,7 +1461,7 @@ CODE_SIGN_ENTITLEMENTS = MemoryWidget/MemoryWidget.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 21; + CURRENT_PROJECT_VERSION = 22; DEVELOPMENT_TEAM = M8G2RFZVFV; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = MemoryWidget/Info.plist; @@ -1458,7 +1471,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.4.2; + MARKETING_VERSION = 1.4.3; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.MemoryWidget; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -1474,7 +1487,7 @@ CODE_SIGN_ENTITLEMENTS = NetworkWidget/NetworkWidget.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 21; + CURRENT_PROJECT_VERSION = 22; DEVELOPMENT_TEAM = M8G2RFZVFV; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = NetworkWidget/Info.plist; @@ -1484,7 +1497,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.4.2; + MARKETING_VERSION = 1.4.3; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.NetworkWidget; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -1500,7 +1513,7 @@ CODE_SIGN_ENTITLEMENTS = NetworkWidget/NetworkWidget.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 21; + CURRENT_PROJECT_VERSION = 22; DEVELOPMENT_TEAM = M8G2RFZVFV; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = NetworkWidget/Info.plist; @@ -1510,7 +1523,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.4.2; + MARKETING_VERSION = 1.4.3; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.NetworkWidget; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -1645,7 +1658,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 21; + CURRENT_PROJECT_VERSION = 22; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = M8G2RFZVFV; ENABLE_HARDENED_RUNTIME = YES; @@ -1657,7 +1670,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.15; - MARKETING_VERSION = 1.4.2; + MARKETING_VERSION = 1.4.3; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = ""; @@ -1676,7 +1689,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 21; + CURRENT_PROJECT_VERSION = 22; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = M8G2RFZVFV; ENABLE_HARDENED_RUNTIME = YES; @@ -1688,7 +1701,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.15; - MARKETING_VERSION = 1.4.2; + MARKETING_VERSION = 1.4.3; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = ""; @@ -1704,7 +1717,7 @@ CODE_SIGN_ENTITLEMENTS = BatteryWidget/BatteryWidget.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 21; + CURRENT_PROJECT_VERSION = 22; DEVELOPMENT_TEAM = M8G2RFZVFV; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = BatteryWidget/Info.plist; @@ -1714,7 +1727,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.4.2; + MARKETING_VERSION = 1.4.3; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.BatteryWidget; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -1730,7 +1743,7 @@ CODE_SIGN_ENTITLEMENTS = BatteryWidget/BatteryWidget.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 21; + CURRENT_PROJECT_VERSION = 22; DEVELOPMENT_TEAM = M8G2RFZVFV; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = BatteryWidget/Info.plist; @@ -1740,7 +1753,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.4.2; + MARKETING_VERSION = 1.4.3; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.BatteryWidget; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -1756,7 +1769,7 @@ CODE_SIGN_ENTITLEMENTS = CpuWidget/CpuWidget.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 21; + CURRENT_PROJECT_VERSION = 22; DEVELOPMENT_TEAM = M8G2RFZVFV; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = CpuWidget/Info.plist; @@ -1766,7 +1779,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.4.2; + MARKETING_VERSION = 1.4.3; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.CpuWidget; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -1782,7 +1795,7 @@ CODE_SIGN_ENTITLEMENTS = CpuWidget/CpuWidget.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 21; + CURRENT_PROJECT_VERSION = 22; DEVELOPMENT_TEAM = M8G2RFZVFV; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = CpuWidget/Info.plist; @@ -1792,7 +1805,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.4.2; + MARKETING_VERSION = 1.4.3; PRODUCT_BUNDLE_IDENTIFIER = com.gaosun.eul.CpuWidget; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; diff --git a/eul/Extension/View.swift b/eul/Extension/View.swift index fb97aae5..6ae06471 100644 --- a/eul/Extension/View.swift +++ b/eul/Extension/View.swift @@ -49,6 +49,6 @@ extension View { .environmentObject(PreferenceStore.shared) .environmentObject(sharedComponentsStore) .environmentObject(sharedMenuComponentsStore) - .environmentObject(StatusComponentConfigStore.shared) + .environmentObject(ComponentConfigStore.shared) } } diff --git a/eul/Schema/EulComponent.swift b/eul/Schema/EulComponent.swift index 13e72d7e..73810253 100644 --- a/eul/Schema/EulComponent.swift +++ b/eul/Schema/EulComponent.swift @@ -18,7 +18,7 @@ enum EulComponent: String, CaseIterable, Identifiable, Codable { "component.\(rawValue.lowercased())".localized() } - var graphAvailable: Bool { + var isGraphAvailable: Bool { guard self == .CPU || self == .Memory else { return false } diff --git a/eul/Schema/FramePreferenceKey.swift b/eul/Schema/FramePreferenceKey.swift new file mode 100644 index 00000000..3a16487a --- /dev/null +++ b/eul/Schema/FramePreferenceKey.swift @@ -0,0 +1,24 @@ +// +// FramePreferenceKey.swift +// eul +// +// Created by Gao Sun on 2020/11/11. +// Copyright © 2020 Gao Sun. All rights reserved. +// + +import SwiftUI + +struct FramePreferenceData: Equatable { + let index: Int + let frame: CGRect +} + +struct FramePreferenceKey: PreferenceKey { + typealias Value = [FramePreferenceData] + + static var defaultValue: [FramePreferenceData] = [] + + static func reduce(value: inout [FramePreferenceData], nextValue: () -> [FramePreferenceData]) { + value += nextValue() + } +} diff --git a/eul/Schema/SizeChangeView.swift b/eul/Schema/SizeChangeView.swift index 1d69f6d5..691b4aa9 100644 --- a/eul/Schema/SizeChangeView.swift +++ b/eul/Schema/SizeChangeView.swift @@ -14,14 +14,16 @@ typealias SizeChangeViewBuilder = (SizeChange) -> AnyView protocol SizeChangeView: View { var onSizeChange: SizeChange { get } - func reportSize(_ geometry: GeometryProxy) -> Color + func reportSize(_ geometry: GeometryProxy) -> AnyView } extension SizeChangeView { - func reportSize(_ geometry: GeometryProxy) -> Color { - DispatchQueue.main.async { - self.onSizeChange?(geometry.size) - } - return Color.clear + func reportSize(_ geometry: GeometryProxy) -> AnyView { + AnyView( + Color.clear.preference( + key: SizePreferenceKey.self, + value: [geometry.size] + ) + ) } } diff --git a/eul/Schema/SizePreferenceKey.swift b/eul/Schema/SizePreferenceKey.swift new file mode 100644 index 00000000..231592c8 --- /dev/null +++ b/eul/Schema/SizePreferenceKey.swift @@ -0,0 +1,19 @@ +// +// SizePreferenceKey.swift +// eul +// +// Created by Gao Sun on 2020/11/11. +// Copyright © 2020 Gao Sun. All rights reserved. +// + +import SwiftUI + +struct SizePreferenceKey: PreferenceKey { + typealias Value = [CGSize] + + static var defaultValue: [CGSize] = [] + + static func reduce(value: inout [CGSize], nextValue: () -> [CGSize]) { + value += nextValue() + } +} diff --git a/eul/StatusBar/StatusBarItem.swift b/eul/StatusBar/StatusBarItem.swift index 28e81303..4eef3cb7 100644 --- a/eul/StatusBar/StatusBarItem.swift +++ b/eul/StatusBar/StatusBarItem.swift @@ -20,15 +20,17 @@ class StatusBarItem: NSObject, NSMenuDelegate { private var statusView: NSHostingView? private var menuView: NSHostingView? private var shouldCloseObserver: NSObjectProtocol? + private var visibilityTimer: Timer? var isVisible: Bool { get { item.isVisible } set { item.isVisible = newValue if newValue { - DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + visibilityTimer?.invalidate() + visibilityTimer = Timer.scheduledTimer(withTimeInterval: 1.5, repeats: false, block: { _ in self.checkStatusItemVisibility() - } + }) } } } @@ -90,6 +92,7 @@ class StatusBarItem: NSObject, NSMenuDelegate { let customItem = NSMenuItem() menuView = StatusBarMenuHostingView(rootView: menuBuilder(onMenuSizeChange)) menuView?.translatesAutoresizingMaskIntoConstraints = false + menuView?.setFrameSize(NSSize(width: 1, height: 1)) customItem.view = menuView statusBarMenu.addItem(customItem) } diff --git a/eul/Store/StatusComponentConfigStore.swift b/eul/Store/ComponentConfigStore.swift similarity index 88% rename from eul/Store/StatusComponentConfigStore.swift rename to eul/Store/ComponentConfigStore.swift index 0c60ca70..ceaf28fa 100644 --- a/eul/Store/StatusComponentConfigStore.swift +++ b/eul/Store/ComponentConfigStore.swift @@ -1,5 +1,5 @@ // -// StatusComponentConfigStore.swift +// ComponentConfigStore.swift // eul // // Created by Gao Sun on 2020/11/8. @@ -10,9 +10,9 @@ import Combine import Foundation import SwiftyJSON -class StatusComponentConfigStore: ObservableObject { - static let shared = StatusComponentConfigStore() - private let userDefaultsKey = "statusComponentConfig" +class ComponentConfigStore: ObservableObject { + static let shared = ComponentConfigStore() + private let userDefaultsKey = "componentConfig" private var cancellable: AnyCancellable? @Published var configDict: [EulComponent: EulComponentConfig] = [:] diff --git a/eul/Store/CpuStore.swift b/eul/Store/CpuStore.swift index 75b02c4e..5ab27ff2 100644 --- a/eul/Store/CpuStore.swift +++ b/eul/Store/CpuStore.swift @@ -41,7 +41,7 @@ class CpuStore: ObservableObject, Refreshable { private func getUsage() { let usage = Info.system.usageCPU() usageCPU = usage - usageString = String(format: "%.1f%%", usage.system + usage.user) + usageString = String(format: "%.0f%%", usage.system + usage.user) usageHistory = (usageHistory + [usage.system + usage.user]).suffix(10) } diff --git a/eul/ViewModifier/StableWidth.swift b/eul/ViewModifier/StableWidth.swift index d282c766..c5c77743 100644 --- a/eul/ViewModifier/StableWidth.swift +++ b/eul/ViewModifier/StableWidth.swift @@ -9,8 +9,18 @@ import SwiftUI extension View { - func stableWidth(_ factor: CGFloat = 10) -> some View { - modifier(StableWidth(factor: factor)) + func stableWidth(_ factor: CGFloat = 8, minWidth: CGFloat? = nil) -> some View { + modifier(StableWidth(factor: factor, minWidth: minWidth)) + } +} + +private struct CGFloatPreferenceKey: PreferenceKey { + typealias Value = [CGFloat] + + static var defaultValue: [CGFloat] = [] + + static func reduce(value: inout [CGFloat], nextValue: () -> [CGFloat]) { + value += nextValue() } } @@ -18,12 +28,24 @@ struct StableWidth: ViewModifier { @State private var idealWidth: CGFloat? var factor: CGFloat + var minWidth: CGFloat? - func getSize(_ proxy: GeometryProxy) -> some View { - DispatchQueue.main.async { [self] in - idealWidth = factor * ceil(proxy.size.width / factor) + var computedIdealWidth: CGFloat? { + if let idealWidth = idealWidth { + if let minWidth = minWidth { + return max(idealWidth, minWidth) + } + return idealWidth } - return Color.clear + + return nil + } + + func getSize(_ proxy: GeometryProxy) -> some View { + Color.clear.preference( + key: CGFloatPreferenceKey.self, + value: [factor * ceil(proxy.size.width / factor)] + ) } func body(content: Content) -> some View { @@ -33,7 +55,10 @@ struct StableWidth: ViewModifier { .fixedSize() .background(GeometryReader { getSize($0) }) } - .frame(idealWidth: idealWidth) + .frame(idealWidth: computedIdealWidth) .fixedSize() + .onPreferenceChange(CGFloatPreferenceKey.self, perform: { value in + idealWidth = value.first + }) } } diff --git a/eul/Views/Menu/BatteryMenuBlockView.swift b/eul/Views/Menu/BatteryMenuBlockView.swift index 461041d4..3a5acc84 100644 --- a/eul/Views/Menu/BatteryMenuBlockView.swift +++ b/eul/Views/Menu/BatteryMenuBlockView.swift @@ -22,14 +22,14 @@ struct BatteryMenuBlockView: View { .menuSection() Spacer() if io.isCharging && io.timeToFullCharge >= 0 { - Text("\(io.timeToFullCharge) min") + Text(io.timeToFullCharge.readableTimeInMin) .displayText() Text("battery.to_full_charge".localized()) .miniSection() .padding(.trailing, 4) } if !io.isCharging && !io.isCharged && io.timeToEmpty >= 0 { - Text("\(io.timeToEmpty) min") + Text(io.timeToEmpty.readableTimeInMin) .displayText() Text("battery.to_empty".localized()) .miniSection() diff --git a/eul/Views/Menu/StatusMenuView.swift b/eul/Views/Menu/StatusMenuView.swift index d8db6ce7..efb5b3a5 100644 --- a/eul/Views/Menu/StatusMenuView.swift +++ b/eul/Views/Menu/StatusMenuView.swift @@ -35,5 +35,10 @@ struct StatusMenuView: SizeChangeView { .fixedSize() .animation(.none) .background(GeometryReader { self.reportSize($0) }) + .onPreferenceChange(SizePreferenceKey.self, perform: { value in + if let size = value.first { + onSizeChange?(size) + } + }) } } diff --git a/eul/Views/Preference/PreferenceComponentsView.swift b/eul/Views/Preference/PreferenceComponentsView.swift index 2cb429be..f9e4da50 100644 --- a/eul/Views/Preference/PreferenceComponentsView.swift +++ b/eul/Views/Preference/PreferenceComponentsView.swift @@ -18,12 +18,12 @@ extension Preference { @GestureState var offsetWidth: CGFloat = 0 func updateFrame(geometry: GeometryProxy, index: Int) -> some View { - if !componentsStore.isActiveComponentToggling { - DispatchQueue.main.async { - self.frames[index] = geometry.frame(in: CoordinateSpace.named(coordinateSpace)) - } - } - return Color.clear + Color.clear.preference( + key: FramePreferenceKey.self, + value: componentsStore.isActiveComponentToggling + ? [] + : [FramePreferenceData(index: index, frame: geometry.frame(in: CoordinateSpace.named(coordinateSpace)))] + ) } var body: some View { @@ -177,6 +177,11 @@ extension Preference { } } } + .onPreferenceChange(FramePreferenceKey.self, perform: { value in + for data in value { + self.frames[data.index] = data.frame + } + }) } } } diff --git a/eul/Views/Preference/PreferenceMenuViewView.swift b/eul/Views/Preference/PreferenceMenuViewView.swift index add20807..10e7e599 100644 --- a/eul/Views/Preference/PreferenceMenuViewView.swift +++ b/eul/Views/Preference/PreferenceMenuViewView.swift @@ -18,12 +18,12 @@ extension Preference { @GestureState var offsetHeight: CGFloat = 0 func updateFrame(geometry: GeometryProxy, index: Int) -> some View { - if !componentsStore.isActiveComponentToggling { - DispatchQueue.main.async { - self.frames[index] = geometry.frame(in: CoordinateSpace.named(coordinateSpace)) - } - } - return Color.clear + Color.clear.preference( + key: FramePreferenceKey.self, + value: componentsStore.isActiveComponentToggling + ? [] + : [FramePreferenceData(index: index, frame: geometry.frame(in: CoordinateSpace.named(coordinateSpace)))] + ) } var body: some View { @@ -187,6 +187,11 @@ extension Preference { } } .padding(.vertical, 8) + .onPreferenceChange(FramePreferenceKey.self, perform: { value in + for data in value { + self.frames[data.index] = data.frame + } + }) } } } diff --git a/eul/Views/StatusBar/CpuView.swift b/eul/Views/StatusBar/CpuView.swift index 33d96b6a..68b64c17 100644 --- a/eul/Views/StatusBar/CpuView.swift +++ b/eul/Views/StatusBar/CpuView.swift @@ -11,10 +11,10 @@ import SwiftUI struct CpuView: View { @EnvironmentObject var cpuStore: CpuStore @EnvironmentObject var preferenceStore: PreferenceStore - @EnvironmentObject var statusComponentConfigStore: StatusComponentConfigStore + @EnvironmentObject var componentConfigStore: ComponentConfigStore var config: EulComponentConfig { - statusComponentConfigStore.configDict[.CPU] ?? EulComponentConfig(component: .CPU) + componentConfigStore.configDict[.CPU] ?? EulComponentConfig(component: .CPU) } var texts: [String] { diff --git a/eul/Views/StatusBar/NetworkView.swift b/eul/Views/StatusBar/NetworkView.swift index 97d82bcc..6e268b81 100644 --- a/eul/Views/StatusBar/NetworkView.swift +++ b/eul/Views/StatusBar/NetworkView.swift @@ -24,7 +24,7 @@ struct NetworkView: View { .frame(width: 13, height: 13) } StatusBarTextView(texts: texts) - .stableWidth(20) + .stableWidth(20, minWidth: 40) } } } diff --git a/eul/Views/StatusBar/StatusBarView.swift b/eul/Views/StatusBar/StatusBarView.swift index e9d93428..f20a212e 100644 --- a/eul/Views/StatusBar/StatusBarView.swift +++ b/eul/Views/StatusBar/StatusBarView.swift @@ -31,5 +31,10 @@ struct StatusBarView: SizeChangeView { } .fixedSize() .background(GeometryReader { self.reportSize($0) }) + .onPreferenceChange(SizePreferenceKey.self, perform: { value in + if let size = value.first { + onSizeChange?(size) + } + }) } }