Displaying Info.plist and entitlements
This commit is contained in:
parent
c02cb61aea
commit
07ece653e9
@ -15,6 +15,10 @@
|
|||||||
7A72231529DCABE400503F78 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A72231429DCABE400503F78 /* ContentView.swift */; };
|
7A72231529DCABE400503F78 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A72231429DCABE400503F78 /* ContentView.swift */; };
|
||||||
7A72231729DCABE500503F78 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7A72231629DCABE500503F78 /* Assets.xcassets */; };
|
7A72231729DCABE500503F78 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7A72231629DCABE500503F78 /* Assets.xcassets */; };
|
||||||
7A72231A29DCABE500503F78 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7A72231929DCABE500503F78 /* Preview Assets.xcassets */; };
|
7A72231A29DCABE500503F78 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7A72231929DCABE500503F78 /* Preview Assets.xcassets */; };
|
||||||
|
7AF0C51829EDCF59008D4084 /* URL+ExtendedAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF0C51729EDCF59008D4084 /* URL+ExtendedAttributes.swift */; };
|
||||||
|
7AF0C51A29EF43C2008D4084 /* OutlineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF0C51929EF43C2008D4084 /* OutlineView.swift */; };
|
||||||
|
7AF0C51C29EF43CD008D4084 /* TreeItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF0C51B29EF43CD008D4084 /* TreeItem.swift */; };
|
||||||
|
7AF0C53B29F72151008D4084 /* PlistView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF0C53A29F72151008D4084 /* PlistView.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
@ -28,6 +32,10 @@
|
|||||||
7A72231629DCABE500503F78 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
7A72231629DCABE500503F78 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
7A72231929DCABE500503F78 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
|
7A72231929DCABE500503F78 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
|
||||||
7A72231B29DCABE500503F78 /* reSign.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = reSign.entitlements; sourceTree = "<group>"; };
|
7A72231B29DCABE500503F78 /* reSign.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = reSign.entitlements; sourceTree = "<group>"; };
|
||||||
|
7AF0C51729EDCF59008D4084 /* URL+ExtendedAttributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+ExtendedAttributes.swift"; sourceTree = "<group>"; };
|
||||||
|
7AF0C51929EF43C2008D4084 /* OutlineView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutlineView.swift; sourceTree = "<group>"; };
|
||||||
|
7AF0C51B29EF43CD008D4084 /* TreeItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TreeItem.swift; sourceTree = "<group>"; };
|
||||||
|
7AF0C53A29F72151008D4084 /* PlistView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlistView.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@ -44,6 +52,7 @@
|
|||||||
7A064BE129DE0FA900C5D978 /* Models */ = {
|
7A064BE129DE0FA900C5D978 /* Models */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
7AF0C51B29EF43CD008D4084 /* TreeItem.swift */,
|
||||||
7A064BE329DE107000C5D978 /* Category.swift */,
|
7A064BE329DE107000C5D978 /* Category.swift */,
|
||||||
);
|
);
|
||||||
path = Models;
|
path = Models;
|
||||||
@ -52,7 +61,9 @@
|
|||||||
7A064BE529DE17A800C5D978 /* Views */ = {
|
7A064BE529DE17A800C5D978 /* Views */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
7AF0C51929EF43C2008D4084 /* OutlineView.swift */,
|
||||||
7A064BE829DE18C700C5D978 /* SignInfoView.swift */,
|
7A064BE829DE18C700C5D978 /* SignInfoView.swift */,
|
||||||
|
7AF0C53A29F72151008D4084 /* PlistView.swift */,
|
||||||
);
|
);
|
||||||
path = Views;
|
path = Views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -76,6 +87,7 @@
|
|||||||
7A72231129DCABE400503F78 /* reSign */ = {
|
7A72231129DCABE400503F78 /* reSign */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
7AF0C51629EDCF3B008D4084 /* Extensions */,
|
||||||
7A064BE529DE17A800C5D978 /* Views */,
|
7A064BE529DE17A800C5D978 /* Views */,
|
||||||
7A064BE129DE0FA900C5D978 /* Models */,
|
7A064BE129DE0FA900C5D978 /* Models */,
|
||||||
7A72231229DCABE400503F78 /* reSignApp.swift */,
|
7A72231229DCABE400503F78 /* reSignApp.swift */,
|
||||||
@ -97,6 +109,14 @@
|
|||||||
path = "Preview Content";
|
path = "Preview Content";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
7AF0C51629EDCF3B008D4084 /* Extensions */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
7AF0C51729EDCF59008D4084 /* URL+ExtendedAttributes.swift */,
|
||||||
|
);
|
||||||
|
path = Extensions;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
@ -168,11 +188,15 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
7A72231529DCABE400503F78 /* ContentView.swift in Sources */,
|
7A72231529DCABE400503F78 /* ContentView.swift in Sources */,
|
||||||
|
7AF0C53B29F72151008D4084 /* PlistView.swift in Sources */,
|
||||||
|
7AF0C51C29EF43CD008D4084 /* TreeItem.swift in Sources */,
|
||||||
|
7AF0C51829EDCF59008D4084 /* URL+ExtendedAttributes.swift in Sources */,
|
||||||
7A064BEB29DF5BB800C5D978 /* AppPackage.swift in Sources */,
|
7A064BEB29DF5BB800C5D978 /* AppPackage.swift in Sources */,
|
||||||
7A064BE929DE18C700C5D978 /* SignInfoView.swift in Sources */,
|
7A064BE929DE18C700C5D978 /* SignInfoView.swift in Sources */,
|
||||||
7A064BED29E2C91D00C5D978 /* Certificate.swift in Sources */,
|
7A064BED29E2C91D00C5D978 /* Certificate.swift in Sources */,
|
||||||
7A72231329DCABE400503F78 /* reSignApp.swift in Sources */,
|
7A72231329DCABE400503F78 /* reSignApp.swift in Sources */,
|
||||||
7A064BE429DE107000C5D978 /* Category.swift in Sources */,
|
7A064BE429DE107000C5D978 /* Category.swift in Sources */,
|
||||||
|
7AF0C51A29EF43C2008D4084 /* OutlineView.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -46,6 +46,8 @@ class AppPackage {
|
|||||||
var designatedRequirements: String?
|
var designatedRequirements: String?
|
||||||
var implicitRequirements: String?
|
var implicitRequirements: String?
|
||||||
var certificates: [Certificate]?
|
var certificates: [Certificate]?
|
||||||
|
var infoPlist: [String: Any] = [:]
|
||||||
|
var entitlements: [String: Any] = [:]
|
||||||
|
|
||||||
init(url: URL) {
|
init(url: URL) {
|
||||||
|
|
||||||
@ -105,9 +107,8 @@ class AppPackage {
|
|||||||
designatedRequirements = try getRequirements(from: signingInfo, key: kSecCodeInfoDesignatedRequirement)
|
designatedRequirements = try getRequirements(from: signingInfo, key: kSecCodeInfoDesignatedRequirement)
|
||||||
implicitRequirements = try getRequirements(from: signingInfo, key: kSecCodeInfoImplicitDesignatedRequirement)
|
implicitRequirements = try getRequirements(from: signingInfo, key: kSecCodeInfoImplicitDesignatedRequirement)
|
||||||
certificates = try getCertificates(from: signingInfo)
|
certificates = try getCertificates(from: signingInfo)
|
||||||
|
infoPlist = signingInfo[kSecCodeInfoPList as String] as? [String: Any] ?? [:]
|
||||||
let infoPlist = signingInfo[kSecCodeInfoPList as String]
|
entitlements = signingInfo[kSecCodeInfoEntitlementsDict as String] as? [String: Any] ?? [:]
|
||||||
print(infoPlist)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -54,8 +54,8 @@ struct ContentView: View {
|
|||||||
} else {
|
} else {
|
||||||
switch selection?.type {
|
switch selection?.type {
|
||||||
case .signInfo: SignInfoView(appPackage: appPackage!)
|
case .signInfo: SignInfoView(appPackage: appPackage!)
|
||||||
case .infoPlist: Text("Info.plist")
|
case .infoPlist: PlistView(infoPlist: appPackage!.infoPlist)
|
||||||
case .entitlements: Text("Entitlements")
|
case .entitlements: PlistView(infoPlist: appPackage!.entitlements)
|
||||||
case .resign: Text("ReSign")
|
case .resign: Text("ReSign")
|
||||||
default: EmptyView()
|
default: EmptyView()
|
||||||
}
|
}
|
||||||
|
|||||||
93
reSign/Extensions/URL+ExtendedAttributes.swift
Normal file
93
reSign/Extensions/URL+ExtendedAttributes.swift
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
//
|
||||||
|
// URL+ExtendedAttributes.swift
|
||||||
|
// reSign
|
||||||
|
//
|
||||||
|
// Created by Selim Mustafaev on 17.04.2023.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension URL {
|
||||||
|
|
||||||
|
/// Get extended attribute.
|
||||||
|
func extendedAttribute(forName name: String) throws -> Data? {
|
||||||
|
|
||||||
|
let data = try self.withUnsafeFileSystemRepresentation { fileSystemPath -> Data? in
|
||||||
|
|
||||||
|
// Determine attribute size:
|
||||||
|
let length = getxattr(fileSystemPath, name, nil, 0, 0, 0)
|
||||||
|
|
||||||
|
guard length >= 0 else {
|
||||||
|
if length == ENOATTR {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
throw URL.posixError(errno)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create buffer with required size:
|
||||||
|
var data = Data(count: length)
|
||||||
|
|
||||||
|
// Retrieve attribute:
|
||||||
|
let result = data.withUnsafeMutableBytes { [count = data.count] in
|
||||||
|
getxattr(fileSystemPath, name, $0.baseAddress, count, 0, 0)
|
||||||
|
}
|
||||||
|
guard result >= 0 else { throw URL.posixError(errno) }
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set extended attribute.
|
||||||
|
func setExtendedAttribute(data: Data, forName name: String) throws {
|
||||||
|
|
||||||
|
try self.withUnsafeFileSystemRepresentation { fileSystemPath in
|
||||||
|
let result = data.withUnsafeBytes {
|
||||||
|
setxattr(fileSystemPath, name, $0.baseAddress, data.count, 0, 0)
|
||||||
|
}
|
||||||
|
guard result >= 0 else { throw URL.posixError(errno) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove extended attribute.
|
||||||
|
func removeExtendedAttribute(forName name: String) throws {
|
||||||
|
|
||||||
|
try self.withUnsafeFileSystemRepresentation { fileSystemPath in
|
||||||
|
let result = removexattr(fileSystemPath, name, 0)
|
||||||
|
guard result >= 0 else { throw URL.posixError(errno) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get list of all extended attributes.
|
||||||
|
func listExtendedAttributes() throws -> [String] {
|
||||||
|
|
||||||
|
let list = try self.withUnsafeFileSystemRepresentation { fileSystemPath -> [String] in
|
||||||
|
let length = listxattr(fileSystemPath, nil, 0, 0)
|
||||||
|
guard length >= 0 else { throw URL.posixError(errno) }
|
||||||
|
|
||||||
|
// Create buffer with required size:
|
||||||
|
var namebuf = Array<CChar>(repeating: 0, count: length)
|
||||||
|
|
||||||
|
// Retrieve attribute list:
|
||||||
|
let result = listxattr(fileSystemPath, &namebuf, namebuf.count, 0)
|
||||||
|
guard result >= 0 else { throw URL.posixError(errno) }
|
||||||
|
|
||||||
|
// Extract attribute names:
|
||||||
|
let list = namebuf.split(separator: 0).compactMap {
|
||||||
|
$0.withUnsafeBufferPointer {
|
||||||
|
$0.withMemoryRebound(to: UInt8.self) {
|
||||||
|
String(bytes: $0, encoding: .utf8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper function to create an NSError from a Unix errno.
|
||||||
|
private static func posixError(_ err: Int32) -> NSError {
|
||||||
|
return NSError(domain: NSPOSIXErrorDomain, code: Int(err),
|
||||||
|
userInfo: [NSLocalizedDescriptionKey: String(cString: strerror(err))])
|
||||||
|
}
|
||||||
|
}
|
||||||
89
reSign/Models/TreeItem.swift
Normal file
89
reSign/Models/TreeItem.swift
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
//
|
||||||
|
// TreeItem.swift
|
||||||
|
// OutlineTest
|
||||||
|
//
|
||||||
|
// Created by Мустафаев Селим Мустафаевич on 11.04.2023.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
enum DictValue: CustomStringConvertible {
|
||||||
|
|
||||||
|
case string(value: String)
|
||||||
|
case number(value: Int)
|
||||||
|
case bool(value: Bool)
|
||||||
|
case array(value: [DictNode])
|
||||||
|
case dictionary(value: [DictNode])
|
||||||
|
case unknown
|
||||||
|
|
||||||
|
var description: String {
|
||||||
|
switch self {
|
||||||
|
case .string(let value): return value
|
||||||
|
case .number(let value): return String(value)
|
||||||
|
case .bool(let value): return value ? "True" : "False"
|
||||||
|
case .array(let value): return "\(value.count) item(s)"
|
||||||
|
case .dictionary(let value): return "\(value.count) item(s)"
|
||||||
|
case .unknown: return "Unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var type: String {
|
||||||
|
switch self {
|
||||||
|
case .string: return "String"
|
||||||
|
case .number: return "Number"
|
||||||
|
case .bool: return "Boolean"
|
||||||
|
case .array: return "Array"
|
||||||
|
case .dictionary: return "Dictionary"
|
||||||
|
case .unknown: return "Unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var isReal: Bool {
|
||||||
|
switch self {
|
||||||
|
case .string, .number, .bool: return true
|
||||||
|
default: return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DictNode: Identifiable {
|
||||||
|
|
||||||
|
var name: String?
|
||||||
|
var value: DictValue?
|
||||||
|
var children: [DictNode] = []
|
||||||
|
|
||||||
|
init(name: String?, value: Any?) {
|
||||||
|
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
switch value {
|
||||||
|
case let stringVal as String:
|
||||||
|
self.value = .string(value: stringVal)
|
||||||
|
case let numVal as Int:
|
||||||
|
self.value = .number(value: numVal)
|
||||||
|
case let boolVal as Bool:
|
||||||
|
self.value = .bool(value: boolVal)
|
||||||
|
case let dict as [String: Any]:
|
||||||
|
self.children = dict.map { DictNode(name: $0.key, value: $0.value) }
|
||||||
|
self.value = .dictionary(value: self.children)
|
||||||
|
case let array as [Any]:
|
||||||
|
self.children = array.enumerated().map { (index, element) in
|
||||||
|
DictNode(name: "Item \(index)", value: element)
|
||||||
|
}
|
||||||
|
self.value = .array(value: self.children)
|
||||||
|
default:
|
||||||
|
self.value = .unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init(dict: [String: Any]) {
|
||||||
|
|
||||||
|
self.name = "Root"
|
||||||
|
self.children = dict.map { DictNode(name: $0.key, value: $0.value) }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var id: String {
|
||||||
|
name ?? ""
|
||||||
|
}
|
||||||
|
}
|
||||||
109
reSign/Views/OutlineView.swift
Normal file
109
reSign/Views/OutlineView.swift
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
//
|
||||||
|
// OutlineView.swift
|
||||||
|
// OutlineTest
|
||||||
|
//
|
||||||
|
// Created by Мустафаев Селим Мустафаевич on 12.04.2023.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct OutlineView: NSViewRepresentable {
|
||||||
|
|
||||||
|
|
||||||
|
let datasource: OutlineViewDataSource
|
||||||
|
|
||||||
|
init(rootNode: DictNode) {
|
||||||
|
self.datasource = OutlineViewDataSource(data: rootNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeNSView(context: Context) -> some NSView {
|
||||||
|
let view = NSOutlineView()
|
||||||
|
view.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
view.dataSource = datasource
|
||||||
|
view.delegate = datasource
|
||||||
|
view.usesAlternatingRowBackgroundColors = true
|
||||||
|
view.addTableColumn(createColumn(id: "Key", minWidth: 250))
|
||||||
|
view.addTableColumn(createColumn(id: "Type", minWidth: 30))
|
||||||
|
view.addTableColumn(createColumn(id: "Value", minWidth: 150))
|
||||||
|
|
||||||
|
let scroll = NSScrollView()
|
||||||
|
scroll.documentView = view
|
||||||
|
scroll.hasHorizontalScroller = false
|
||||||
|
scroll.hasVerticalScroller = true
|
||||||
|
|
||||||
|
return scroll
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateNSView(_ nsView: NSViewType, context: Context) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func createColumn(id: String, minWidth: CGFloat) -> NSTableColumn {
|
||||||
|
let column = NSTableColumn(identifier: NSUserInterfaceItemIdentifier(rawValue: id))
|
||||||
|
column.title = id
|
||||||
|
column.minWidth = minWidth
|
||||||
|
return column
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc class OutlineViewDataSource: NSObject, NSOutlineViewDataSource, NSOutlineViewDelegate {
|
||||||
|
|
||||||
|
let data: DictNode
|
||||||
|
|
||||||
|
init(data: DictNode) {
|
||||||
|
self.data = data
|
||||||
|
}
|
||||||
|
|
||||||
|
func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
|
||||||
|
guard let item = item as? DictNode else {
|
||||||
|
return data.children[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
return item.children[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
|
||||||
|
guard let item = item as? DictNode else {
|
||||||
|
return data.children.count
|
||||||
|
}
|
||||||
|
|
||||||
|
return item.children.count
|
||||||
|
}
|
||||||
|
|
||||||
|
func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
|
||||||
|
guard let item = item as? DictNode else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return !item.children.isEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
|
||||||
|
guard let item = item as? DictNode else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let value: String
|
||||||
|
switch tableColumn?.identifier.rawValue {
|
||||||
|
case "Key": value = item.name ?? ""
|
||||||
|
case "Type": value = item.value?.type ?? ""
|
||||||
|
case "Value": value = item.value?.description ?? ""
|
||||||
|
default: value = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
let shouldDeEmphasize = item.value?.isReal != true
|
||||||
|
&& tableColumn?.identifier.rawValue == "Value"
|
||||||
|
|
||||||
|
let text = NSTextField(labelWithString: value)
|
||||||
|
text.textColor = shouldDeEmphasize ? .secondaryLabelColor : .labelColor
|
||||||
|
let cell = NSTableCellView()
|
||||||
|
cell.addSubview(text)
|
||||||
|
text.drawsBackground = false
|
||||||
|
text.isBordered = false
|
||||||
|
text.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
cell.addConstraint(NSLayoutConstraint(item: text, attribute: .centerY, relatedBy: .equal, toItem: cell, attribute: .centerY, multiplier: 1, constant: 0))
|
||||||
|
cell.addConstraint(NSLayoutConstraint(item: text, attribute: .left, relatedBy: .equal, toItem: cell, attribute: .left, multiplier: 1, constant: 13))
|
||||||
|
cell.addConstraint(NSLayoutConstraint(item: text, attribute: .right, relatedBy: .equal, toItem: cell, attribute: .right, multiplier: 1, constant: -13))
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
}
|
||||||
23
reSign/Views/PlistView.swift
Normal file
23
reSign/Views/PlistView.swift
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
//
|
||||||
|
// PlistView.swift
|
||||||
|
// reSign
|
||||||
|
//
|
||||||
|
// Created by Selim Mustafaev on 24.04.2023.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct PlistView: View {
|
||||||
|
|
||||||
|
var infoPlist: [String: Any]
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
OutlineView(rootNode: DictNode(dict: infoPlist))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct InfoPlistView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
PlistView(infoPlist: [:])
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user