From 1ccb0beee0c3248acbed459a362b7f701447bce2 Mon Sep 17 00:00:00 2001 From: Lessica Date: Fri, 2 Feb 2024 13:32:35 +0800 Subject: [PATCH] add new module: screen Signed-off-by: Lessica --- .bartycrouch.toml | 12 +- Reveil.xcodeproj/project.pbxproj | 8 ++ Reveil/BartyCrouch.swift | 15 +-- .../Details/ScreenInformationListView.swift | 37 ++++++ Reveil/Pages/DetailsView.swift | 9 +- Reveil/ViewModels/Dashboard.swift | 2 + Reveil/ViewModels/Enums/EntryKey.swift | 2 + .../Modules/DeviceInformation.swift | 55 --------- .../Modules/ScreenInformation.swift | 108 ++++++++++++++++++ Reveil/en.lproj/Localizable.strings | 15 +++ Reveil/es.lproj/Localizable.strings | 15 +++ Reveil/zh-Hans.lproj/Localizable.strings | 15 +++ 12 files changed, 215 insertions(+), 78 deletions(-) create mode 100644 Reveil/Pages/Details/ScreenInformationListView.swift create mode 100644 Reveil/ViewModels/Modules/ScreenInformation.swift diff --git a/.bartycrouch.toml b/.bartycrouch.toml index 71f45a2..0b7fdbd 100644 --- a/.bartycrouch.toml +++ b/.bartycrouch.toml @@ -2,7 +2,7 @@ tasks = ["interfaces", "code", "transform", "normalize"] [update.interfaces] -paths = ["."] +paths = ["Reveil"] subpathsToIgnore = [".git", "carthage", "pods", "build", ".build", "docs"] defaultToBase = false ignoreEmptyStrings = false @@ -12,7 +12,7 @@ ignoreKeys = ["#bartycrouch-ignore!", "#bc-ignore!", "#i!"] [update.code] codePaths = ["."] subpathsToIgnore = [".git", "carthage", "pods", "build", ".build", "docs"] -localizablePaths = ["."] +localizablePaths = ["Reveil"] defaultToKeys = false additive = false customFunction = "LocalizedStringResource" @@ -22,9 +22,9 @@ ignoreKeys = ["#bartycrouch-ignore!", "#bc-ignore!", "#i!"] overrideComments = false [update.transform] -codePaths = ["."] +codePaths = ["Reveil"] subpathsToIgnore = [".git", "carthage", "pods", "build", ".build", "docs"] -localizablePaths = ["."] +localizablePaths = ["Reveil"] transformer = "foundation" supportedLanguageEnumPath = "." typeName = "BartyCrouch" @@ -32,7 +32,7 @@ translateMethodName = "translate" separateWithEmptyLine = true [update.normalize] -paths = ["."] +paths = ["Reveil"] subpathsToIgnore = [".git", "carthage", "pods", "build", ".build", "docs"] sourceLocale = "en" harmonizeWithSource = true @@ -40,7 +40,7 @@ sortByKeys = true separateWithEmptyLine = true [lint] -paths = ["."] +paths = ["Reveil"] subpathsToIgnore = [".git", "carthage", "pods", "build", ".build", "docs"] duplicateKeys = true emptyValues = true diff --git a/Reveil.xcodeproj/project.pbxproj b/Reveil.xcodeproj/project.pbxproj index ed5670d..ca1da6d 100644 --- a/Reveil.xcodeproj/project.pbxproj +++ b/Reveil.xcodeproj/project.pbxproj @@ -11,6 +11,8 @@ 0F08193A2ADAEA3400BB626C /* PinStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F0819392ADAEA3400BB626C /* PinStorage.swift */; }; 0F08193D2ADAF1C600BB626C /* DictionaryCoder in Frameworks */ = {isa = PBXBuildFile; productRef = 0F08193C2ADAF1C600BB626C /* DictionaryCoder */; }; 0F08193F2ADEB35500BB626C /* EntryKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F08193E2ADEB35500BB626C /* EntryKey.swift */; }; + 0F0B385E2B6CAEFF00E2E1F2 /* ScreenInformation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F0B385D2B6CAEFF00E2E1F2 /* ScreenInformation.swift */; }; + 0F0B38602B6CAFFF00E2E1F2 /* ScreenInformationListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F0B385F2B6CAFFF00E2E1F2 /* ScreenInformationListView.swift */; }; 0F1659342AF9FB5000268572 /* SecurityPresets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F1659332AF9FB5000268572 /* SecurityPresets.swift */; }; 0F1659372AF9FCF600268572 /* PortItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F1659362AF9FCF600268572 /* PortItem.swift */; }; 0F16593A2AF9FD4500268572 /* URLSchemeItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F1659392AF9FD4500268572 /* URLSchemeItem.swift */; }; @@ -206,6 +208,8 @@ 0F0819372ADAE97200BB626C /* PinStorage.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = PinStorage.plist; sourceTree = ""; }; 0F0819392ADAEA3400BB626C /* PinStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinStorage.swift; sourceTree = ""; }; 0F08193E2ADEB35500BB626C /* EntryKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntryKey.swift; sourceTree = ""; }; + 0F0B385D2B6CAEFF00E2E1F2 /* ScreenInformation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenInformation.swift; sourceTree = ""; }; + 0F0B385F2B6CAFFF00E2E1F2 /* ScreenInformationListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenInformationListView.swift; sourceTree = ""; }; 0F1659332AF9FB5000268572 /* SecurityPresets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecurityPresets.swift; sourceTree = ""; }; 0F1659362AF9FCF600268572 /* PortItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PortItem.swift; sourceTree = ""; }; 0F1659392AF9FD4500268572 /* URLSchemeItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSchemeItem.swift; sourceTree = ""; }; @@ -517,6 +521,7 @@ isa = PBXGroup; children = ( CC21B5302ACD5523003EC114 /* DeviceInformationListView.swift */, + 0F0B385F2B6CAFFF00E2E1F2 /* ScreenInformationListView.swift */, CC21B5342ACD6112003EC114 /* OperatingSystemListView.swift */, CC21B53C2ACDA80F003EC114 /* CPUInformationListView.swift */, CC21B54A2ACE8160003EC114 /* MemoryInformationListView.swift */, @@ -604,6 +609,7 @@ isa = PBXGroup; children = ( CC21B51D2ACD4AAB003EC114 /* DeviceInformation.swift */, + 0F0B385D2B6CAEFF00E2E1F2 /* ScreenInformation.swift */, CC21B5322ACD5FB9003EC114 /* OperatingSystem.swift */, CC21B53A2ACDA7E1003EC114 /* CPUInformation.swift */, CC21B5482ACE809D003EC114 /* MemoryInformation.swift */, @@ -1028,11 +1034,13 @@ CCA095F52AED419B00F5E55F /* EmulatorChecker.swift in Sources */, CC21B5572AD04EAB003EC114 /* NetworkInterfaces.swift in Sources */, CC21B54D2ACF24E2003EC114 /* DiskSpace.swift in Sources */, + 0F0B385E2B6CAEFF00E2E1F2 /* ScreenInformation.swift in Sources */, 0F2CA1282AE946B200C76A78 /* SecurityView.swift in Sources */, CC3F94252B4C506B00E67A19 /* View+ListSectionSeparator.swift in Sources */, 0FD0D26C2AE0D39C001DD1E8 /* EntryExporter.swift in Sources */, CC21B4CA2ACAF5DA003EC114 /* CPUActivity.swift in Sources */, CC549F072AFA9F1800219CF8 /* EntryUpdater.swift in Sources */, + 0F0B38602B6CAFFF00E2E1F2 /* ScreenInformationListView.swift in Sources */, CC0052642B13458000DBF808 /* BatteryInformation.swift in Sources */, CCA095ED2AED419B00F5E55F /* FishHookChecker.swift in Sources */, CC21B52E2ACD4FD5003EC114 /* DetailsListView.swift in Sources */, diff --git a/Reveil/BartyCrouch.swift b/Reveil/BartyCrouch.swift index b530009..41c316b 100644 --- a/Reveil/BartyCrouch.swift +++ b/Reveil/BartyCrouch.swift @@ -5,22 +5,9 @@ import Foundation enum BartyCrouch { enum SupportedLanguage: String { - // TODO: remove unsupported languages from the following cases list & add any missing languages -// case arabic = "ar" case chineseSimplified = "zh-Hans" -// case chineseTraditional = "zh-Hant" case english = "en" -// case french = "fr" -// case german = "de" -// case hindi = "hi" -// case italian = "it" -// case japanese = "ja" -// case korean = "ko" -// case malay = "ms" -// case portuguese = "pt-BR" -// case russian = "ru" -// case spanish = "es" -// case turkish = "tr" + case spanish = "es" } static func translate(key: String, translations: [SupportedLanguage: String], comment _: String? = nil) -> String { diff --git a/Reveil/Pages/Details/ScreenInformationListView.swift b/Reveil/Pages/Details/ScreenInformationListView.swift new file mode 100644 index 0000000..03f1ca9 --- /dev/null +++ b/Reveil/Pages/Details/ScreenInformationListView.swift @@ -0,0 +1,37 @@ +// +// ScreenInformationListView.swift +// Reveil +// +// Created by Lessica on 2023/10/4. +// + +import SwiftUI + +struct ScreenInformationListView: View, ModuleListView { + let module: Module = ScreenInformation.shared + let globalName: String = String(describing: ScreenInformation.self) + + init() {} + + init?(entryKey: EntryKey) { + guard module.updatableEntryKeys.contains(entryKey) else { + return nil + } + } + + var body: some View { + DetailsListView(basicEntries: module.basicEntries) + .navigationTitle(module.moduleName) + } + + func eventOccurred(globalTimer timer: GlobalTimer) { } +} + +// MARK: - Previews + +struct ScreenInformationListView_Previews: PreviewProvider { + static var previews: some View { + ScreenInformationListView() + .environmentObject(HighlightedEntryKey()) + } +} diff --git a/Reveil/Pages/DetailsView.swift b/Reveil/Pages/DetailsView.swift index 84f4e3e..58bd965 100644 --- a/Reveil/Pages/DetailsView.swift +++ b/Reveil/Pages/DetailsView.swift @@ -20,12 +20,15 @@ struct DetailsView: View { static func createDetailsList() -> some View { Group { Group { - createEntry(title: DeviceInformation.shared.moduleName, icon: "desktopcomputer") { - DeviceInformationListView() - } createEntry(title: Security.shared.moduleName, icon: "lock.shield") { SecurityView() } + createEntry(title: DeviceInformation.shared.moduleName, icon: "iphone") { + DeviceInformationListView() + } + createEntry(title: ScreenInformation.shared.moduleName, icon: "desktopcomputer") { + ScreenInformationListView() + } createEntry(title: OperatingSystem.shared.moduleName, icon: "gearshape") { OperatingSystemListView() } diff --git a/Reveil/ViewModels/Dashboard.swift b/Reveil/ViewModels/Dashboard.swift index 7ce5aa8..c2cd88c 100644 --- a/Reveil/ViewModels/Dashboard.swift +++ b/Reveil/ViewModels/Dashboard.swift @@ -21,6 +21,7 @@ final class Dashboard: ObservableObject { var registeredModules: [Module] = [ DeviceInformation.shared, + ScreenInformation.shared, OperatingSystem.shared, CPUInformation.shared, MemoryInformation.shared, @@ -34,6 +35,7 @@ final class Dashboard: ObservableObject { var registeredModuleListViewTypes: [any ModuleListView.Type] = [ DeviceInformationListView.self, + ScreenInformationListView.self, OperatingSystemListView.self, CPUInformationListView.self, MemoryInformationListView.self, diff --git a/Reveil/ViewModels/Enums/EntryKey.swift b/Reveil/ViewModels/Enums/EntryKey.swift index 054f2ef..28e4ea1 100644 --- a/Reveil/ViewModels/Enums/EntryKey.swift +++ b/Reveil/ViewModels/Enums/EntryKey.swift @@ -20,6 +20,8 @@ enum EntryKey: Codable, Equatable, Hashable, RawRepresentable { case BootromVersion case RadioTech case HostName + + // Screen Information case DisplayResolution case ScreenPhysicalResolution case ScreenPhysicalScale diff --git a/Reveil/ViewModels/Modules/DeviceInformation.swift b/Reveil/ViewModels/Modules/DeviceInformation.swift index a409fcd..d33090e 100644 --- a/Reveil/ViewModels/Modules/DeviceInformation.swift +++ b/Reveil/ViewModels/Modules/DeviceInformation.swift @@ -81,26 +81,6 @@ final class DeviceInformation: Module { return techName } - private let mainScreen = UIScreen.main - - private lazy var displaySizeDescription: String = { - let displayWidth = Int(mainScreen.fixedCoordinateSpace.bounds.width * mainScreen.scale) - let displayHeight = Int(mainScreen.fixedCoordinateSpace.bounds.height * mainScreen.scale) - return "\(displayWidth)×\(displayHeight)" - }() - - private lazy var physicalSizeDescription: String = { - let physicalWidth = Int(mainScreen.nativeBounds.width) - let physicalHeight = Int(mainScreen.nativeBounds.height) - return "\(physicalWidth)×\(physicalHeight)" - }() - - private lazy var logicalSizeDescription: String = { - let logicalWidth = Int(mainScreen.fixedCoordinateSpace.bounds.width) - let logicalHeight = Int(mainScreen.fixedCoordinateSpace.bounds.height) - return "\(logicalWidth)×\(logicalHeight)" - }() - lazy var basicEntries: [BasicEntry] = updatableEntryKeys.compactMap { basicEntry(key: $0) } let usageEntry: UsageEntry? = nil @@ -118,11 +98,6 @@ final class DeviceInformation: Module { .BootromVersion, .RadioTech, .HostName, - .DisplayResolution, - .ScreenPhysicalResolution, - .ScreenPhysicalScale, - .ScreenLogicalResolution, - .ScreenLogicalScale, ] func basicEntry(key: EntryKey, style _: ValueStyle = .detailed) -> BasicEntry? { @@ -165,36 +140,6 @@ final class DeviceInformation: Module { name: NSLocalizedString("HOST_NAME", comment: "Host Name"), value: System.hostName() ?? BasicEntry.unknownValue ) - case .DisplayResolution: - return BasicEntry( - key: .DisplayResolution, - name: NSLocalizedString("DISPLAY_RESOLUTION", comment: "Display Resolution"), - value: displaySizeDescription - ) - case .ScreenPhysicalResolution: - return BasicEntry( - key: .ScreenPhysicalResolution, - name: NSLocalizedString("SCREEN_PHYSICAL_RESOLUTION", comment: "Screen Physical Resolution"), - value: physicalSizeDescription - ) - case .ScreenPhysicalScale: - return BasicEntry( - key: .ScreenPhysicalScale, - name: NSLocalizedString("SCREEN_PHYSICAL_SCALE", comment: "Screen Physical Scale"), - value: String(format: "%.3f", mainScreen.nativeScale) - ) - case .ScreenLogicalResolution: - return BasicEntry( - key: .ScreenLogicalResolution, - name: NSLocalizedString("SCREEN_LOGICAL_RESOLUTION", comment: "Screen Logical Resolution"), - value: logicalSizeDescription - ) - case .ScreenLogicalScale: - return BasicEntry( - key: .ScreenLogicalScale, - name: NSLocalizedString("SCREEN_LOGICAL_SCALE", comment: "Screen Logical Scale"), - value: String(format: "%.3f", mainScreen.scale) - ) default: break } diff --git a/Reveil/ViewModels/Modules/ScreenInformation.swift b/Reveil/ViewModels/Modules/ScreenInformation.swift new file mode 100644 index 0000000..3fa4d19 --- /dev/null +++ b/Reveil/ViewModels/Modules/ScreenInformation.swift @@ -0,0 +1,108 @@ +// +// ScreenInformation.swift +// Reveil +// +// Created by Lessica on 2023/10/4. +// + +import UIKit + +final class ScreenInformation: Module { + static let shared = ScreenInformation() + private init() {} + + let moduleName = NSLocalizedString("SCREEN_INFORMATION", comment: "Screen Information") + + private let mainScreen = UIScreen.main + + private lazy var displaySizeDescription: String = { + let displayWidth = Int(mainScreen.fixedCoordinateSpace.bounds.width * mainScreen.scale) + let displayHeight = Int(mainScreen.fixedCoordinateSpace.bounds.height * mainScreen.scale) + return "\(displayWidth)×\(displayHeight)" + }() + + private lazy var physicalSizeDescription: String = { + let physicalWidth = Int(mainScreen.nativeBounds.width) + let physicalHeight = Int(mainScreen.nativeBounds.height) + return "\(physicalWidth)×\(physicalHeight)" + }() + + private lazy var logicalSizeDescription: String = { + let logicalWidth = Int(mainScreen.fixedCoordinateSpace.bounds.width) + let logicalHeight = Int(mainScreen.fixedCoordinateSpace.bounds.height) + return "\(logicalWidth)×\(logicalHeight)" + }() + + lazy var basicEntries: [BasicEntry] = updatableEntryKeys.compactMap { basicEntry(key: $0) } + + let usageEntry: UsageEntry? = nil + + func reloadData() {} + + func updateEntries() { + basicEntries.forEach { updateBasicEntry($0) } + } + + let updatableEntryKeys: [EntryKey] = [ + .DisplayResolution, + .ScreenPhysicalResolution, + .ScreenPhysicalScale, + .ScreenLogicalResolution, + .ScreenLogicalScale, + ] + + func basicEntry(key: EntryKey, style: ValueStyle = .detailed) -> BasicEntry? { + switch key { + case .DisplayResolution: + return BasicEntry( + key: .DisplayResolution, + name: NSLocalizedString("DISPLAY_RESOLUTION", comment: "Display Resolution"), + value: displaySizeDescription + ) + case .ScreenPhysicalResolution: + return BasicEntry( + key: .ScreenPhysicalResolution, + name: style == .dashboard ? NSLocalizedString("SCREEN_PHYSICAL_RESOLUTION", comment: "Screen Physical Resolution") : NSLocalizedString("PHYSICAL_RESOLUTION", comment: "Physical Resolution"), + value: physicalSizeDescription + ) + case .ScreenPhysicalScale: + return BasicEntry( + key: .ScreenPhysicalScale, + name: style == .dashboard ? NSLocalizedString("SCREEN_PHYSICAL_SCALE", comment: "Screen Physical Scale") : NSLocalizedString("PHYSICAL_SCALE", comment: "Physical Scale"), + value: String(format: "%.3f", mainScreen.nativeScale) + ) + case .ScreenLogicalResolution: + return BasicEntry( + key: .ScreenLogicalResolution, + name: style == .dashboard ? NSLocalizedString("SCREEN_LOGICAL_RESOLUTION", comment: "Screen Logical Resolution") : NSLocalizedString("LOGICAL_RESOLUTION", comment: "Logical Resolution"), + value: logicalSizeDescription + ) + case .ScreenLogicalScale: + return BasicEntry( + key: .ScreenLogicalScale, + name: style == .dashboard ? NSLocalizedString("SCREEN_LOGICAL_SCALE", comment: "Screen Logical Scale") : NSLocalizedString("LOGICAL_SCALE", comment: "Logical Scale"), + value: String(format: "%.3f", mainScreen.scale) + ) + default: + break + } + return nil + } + + func updateBasicEntry(_ basicEntry: BasicEntry, style _: ValueStyle = .detailed) { + switch basicEntry.key { + case .HostName: + basicEntry.value = System.hostName() ?? BasicEntry.unknownValue + default: + break + } + } + + func usageEntry(key _: EntryKey, style _: ValueStyle = .detailed) -> UsageEntry? { nil } + + func updateUsageEntry(_: UsageEntry, style _: ValueStyle) {} + + func trafficEntryIO(key _: EntryKey, style _: ValueStyle) -> TrafficEntryIO? { nil } + + func updateTrafficEntryIO(_: TrafficEntryIO, style _: ValueStyle) {} +} diff --git a/Reveil/en.lproj/Localizable.strings b/Reveil/en.lproj/Localizable.strings index 6c17720..17eceec 100644 --- a/Reveil/en.lproj/Localizable.strings +++ b/Reveil/en.lproj/Localizable.strings @@ -430,6 +430,12 @@ /* %@/s */ "LINE_SPEED_FMT" = "%@/s"; +/* Logical Resolution */ +"LOGICAL_RESOLUTION" = "Logical Resolution"; + +/* Logical Scale */ +"LOGICAL_SCALE" = "Logical Scale"; + /* Lookups */ "LOOKUPS" = "Lookups"; @@ -808,6 +814,12 @@ /* Physical Memory */ "PHYSICAL_MEMORY" = "Physical Memory"; +/* Physical Resolution */ +"PHYSICAL_RESOLUTION" = "Physical Resolution"; + +/* Physical Scale */ +"PHYSICAL_SCALE" = "Physical Scale"; + /* Pin */ "PIN" = "Pin"; @@ -856,6 +868,9 @@ /* Scanning… */ "SCANNING" = "Scanning…"; +/* Screen Information */ +"SCREEN_INFORMATION" = "Screen Information"; + /* Screen Logical Resolution */ "SCREEN_LOGICAL_RESOLUTION" = "Screen Logical Resolution"; diff --git a/Reveil/es.lproj/Localizable.strings b/Reveil/es.lproj/Localizable.strings index 58d50eb..2521871 100644 --- a/Reveil/es.lproj/Localizable.strings +++ b/Reveil/es.lproj/Localizable.strings @@ -430,6 +430,12 @@ /* %@/s */ "LINE_SPEED_FMT" = "%@/s"; +/* TODO: Logical Resolution */ +"LOGICAL_RESOLUTION" = "Logical Resolution"; + +/* TODO: Logical Scale */ +"LOGICAL_SCALE" = "Logical Scale"; + /* Lookups */ "LOOKUPS" = "Búsquedas"; @@ -808,6 +814,12 @@ /* Physical Memory */ "PHYSICAL_MEMORY" = "Memoria Física"; +/* TODO: Physical Resolution */ +"PHYSICAL_RESOLUTION" = "Physical Resolution"; + +/* TODO: Physical Scale */ +"PHYSICAL_SCALE" = "Physical Scale"; + /* Pin */ "PIN" = "Pin"; @@ -856,6 +868,9 @@ /* Scanning… */ "SCANNING" = "Escaneando…"; +/* TODO: Screen Information */ +"SCREEN_INFORMATION" = "Screen Information"; + /* TODO: Screen Logical Resolution */ "SCREEN_LOGICAL_RESOLUTION" = "Screen Logical Resolution"; diff --git a/Reveil/zh-Hans.lproj/Localizable.strings b/Reveil/zh-Hans.lproj/Localizable.strings index f7bd171..bc91405 100644 --- a/Reveil/zh-Hans.lproj/Localizable.strings +++ b/Reveil/zh-Hans.lproj/Localizable.strings @@ -430,6 +430,12 @@ /* %@/s */ "LINE_SPEED_FMT" = "%@ 每秒"; +/* Logical Resolution */ +"LOGICAL_RESOLUTION" = "逻辑分辨率"; + +/* Logical Scale */ +"LOGICAL_SCALE" = "逻辑缩放率"; + /* Lookups */ "LOOKUPS" = "查询数"; @@ -808,6 +814,12 @@ /* Physical Memory */ "PHYSICAL_MEMORY" = "物理内存"; +/* Physical Resolution */ +"PHYSICAL_RESOLUTION" = "物理分辨率"; + +/* Physical Scale */ +"PHYSICAL_SCALE" = "物理缩放率"; + /* Pin */ "PIN" = "收藏"; @@ -856,6 +868,9 @@ /* Scanning… */ "SCANNING" = "扫描中"; +/* Screen Information */ +"SCREEN_INFORMATION" = "屏幕信息"; + /* Screen Logical Resolution */ "SCREEN_LOGICAL_RESOLUTION" = "屏幕逻辑分辨率";