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)
+ }
+ })
}
}