Skip to content

Commit

Permalink
Merge pull request #39 from zenangst/feature/full-disk-access
Browse files Browse the repository at this point in the history
Implement handling of restricted applications
  • Loading branch information
zenangst authored Oct 8, 2018
2 parents 315303a + 6b28cc6 commit ef3c08e
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 18 deletions.
2 changes: 1 addition & 1 deletion Resources/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.7.0</string>
<string>0.8.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSApplicationCategoryType</key>
Expand Down
13 changes: 13 additions & 0 deletions Sources/Applications/Data Sources/ApplicationsDataSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,19 @@ class ApplicationsDataSource: NSObject, NSCollectionViewDataSource {
view.iconView.image = self.iconController.icon(for: model)
view.titleLabel.stringValue = model.name
view.update(with: model.appearance)

switch model.appearance {
case .dark:
view.subtitleLabel.stringValue = "Dark appearance"
case .light:
view.subtitleLabel.stringValue = "Light appearance"
case .system:
view.subtitleLabel.stringValue = "System appearance"
}

if model.restricted {
view.subtitleLabel.stringValue = "🔐 Locked"
}
}
}
}
14 changes: 10 additions & 4 deletions Sources/Applications/Logic/ApplicationsLogicController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ class ApplicationsLogicController {

private func processApplications(_ appUrls: [URL], at directoryUrl: URL) throws -> [Application] {
var applications = [Application]()

let shell = Shell()
let sip = shell.execute(command: "csrutil status").contains("enabled")
let libraryDirectory = try FileManager.default.url(for: .libraryDirectory,
in: .userDomainMask,
appropriateFor: nil,
Expand All @@ -113,20 +114,25 @@ class ApplicationsLogicController {
var resolvedAppPreferenceUrl = appPreferenceUrl
var applicationPlist: NSDictionary? = nil

if let plist = NSDictionary.init(contentsOfFile: appContainerPreferenceUrl.path) {
if FileManager.default.fileExists(atPath: appContainerPreferenceUrl.path),
let plist = NSDictionary.init(contentsOfFile: appContainerPreferenceUrl.path) {
applicationPlist = plist
resolvedAppPreferenceUrl = appContainerPreferenceUrl
} else if let plist = NSDictionary.init(contentsOfFile: appPreferenceUrl.path) {
applicationPlist = plist
}

guard let resolvedPlist = applicationPlist else { continue }
// Check if Gray has enough priviliges to change appearance for application
let restricted = sip &&
FileManager.default.fileExists(atPath: appContainerPreferenceUrl.path) &&
NSDictionary.init(contentsOfFile: appContainerPreferenceUrl.path) == nil

let app = Application(bundleIdentifier: bundleIdentifier,
name: bundleName,
url: url,
preferencesUrl: resolvedAppPreferenceUrl,
appearance: resolvedPlist.appearance())
appearance: applicationPlist?.appearance() ?? .system,
restricted: restricted)
applications.append(app)
}
return applications.sorted(by: { $0.name.lowercased() < $1.name.lowercased() })
Expand Down
1 change: 1 addition & 0 deletions Sources/Applications/Models/Application.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ struct Application: Hashable {
let url: URL
let preferencesUrl: URL
let appearance: Appearance
let restricted: Bool
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,19 @@ class ApplicationsCollectionViewController: NSViewController, NSCollectionViewDe
view.addSubview(collectionView, pin: true)
}

private func showPermissionsDialog(for application: Application, handler completion : (Bool)->Void) {
let alert = NSAlert()
alert.messageText = "Additional privileges needed"
alert.informativeText = """
To be able to change the appearance of apps like Mail, Messages, Safari and Home, you need to grant permission Full Disk Access.
"""
alert.alertStyle = .informational
alert.addButton(withTitle: "Open Security & Preferences")
alert.addButton(withTitle: "OK")
completion(alert.runModal() == .alertFirstButtonReturn)
}

// MARK: - NSCollectionViewDelegate

func collectionView(_ collectionView: NSCollectionView, didSelectItemsAt indexPaths: Set<IndexPath>) {
Expand Down Expand Up @@ -68,11 +81,20 @@ class ApplicationsCollectionViewController: NSViewController, NSCollectionViewDe
context.duration = duration
context.allowsImplicitAnimation = true
item.view.animator().layer?.setAffineTransform(.identity)
item.update(with: newAppearance, duration: 0.5) { [weak self] in
guard let strongSelf = self else { return }
strongSelf.delegate?.applicationCollectionViewController(strongSelf,
toggleAppearance: newAppearance,
application: application)
}, completionHandler: {
if application.restricted {
self.showPermissionsDialog(for: application) { result in
guard result else { return }
let url = URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_AllFiles")!
NSWorkspace.shared.open(url)
}
} else {
item.update(with: newAppearance, duration: 0.5) { [weak self] in
guard let strongSelf = self else { return }
strongSelf.delegate?.applicationCollectionViewController(strongSelf,
toggleAppearance: newAppearance,
application: application)
}
}
})
})
Expand Down
6 changes: 0 additions & 6 deletions Sources/Applications/Views/ApplicationGridView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,16 @@ class ApplicationGridView: NSCollectionViewItem {
view.animator().layer?.backgroundColor = NSColor(named: "Dark")?.cgColor
titleLabel.animator().textColor = .white
subtitleLabel.animator().textColor = .controlAccentColor
subtitleLabel.animator().stringValue = "Dark appearance"
view.layer?.borderWidth = 0.0
case .system:
view.animator().layer?.backgroundColor = NSColor.gray.cgColor
titleLabel.animator().textColor = .white
subtitleLabel.animator().textColor = .lightGray
subtitleLabel.animator().stringValue = "System appearance"
view.layer?.borderWidth = 0.0
case .light:
view.animator().layer?.backgroundColor = .white
titleLabel.animator().textColor = .black
subtitleLabel.animator().textColor = .controlAccentColor
subtitleLabel.animator().stringValue = "Light appearance"
view.layer?.borderColor = NSColor.gray.withAlphaComponent(0.25).cgColor
view.layer?.borderWidth = 1.5
}
Expand All @@ -104,13 +101,11 @@ class ApplicationGridView: NSCollectionViewItem {
view.layer?.backgroundColor = NSColor(named: "Dark")?.cgColor
titleLabel.textColor = .white
subtitleLabel.textColor = .controlAccentColor
subtitleLabel.stringValue = "Dark appearance"
view.layer?.borderWidth = 0.0
case .light:
view.layer?.backgroundColor = NSColor(named: "Light")?.cgColor
titleLabel.textColor = .black
subtitleLabel.textColor = .controlAccentColor
subtitleLabel.stringValue = "Light appearance"
view.layer?.borderColor = NSColor.gray.withAlphaComponent(0.25).cgColor
view.layer?.borderWidth = 1.5
case .system:
Expand All @@ -129,7 +124,6 @@ class ApplicationGridView: NSCollectionViewItem {
default:
break
}
subtitleLabel.stringValue = "System appearance"
}
}
}
Expand Down
2 changes: 0 additions & 2 deletions Sources/SystemPreferences/Logic/SystemLogicController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,6 @@ class SystemLogicController {
procNotFound:
if retryOnInternalError {
self.requestPermission(retryOnInternalError: false, then: process)
} else {

}
default:
break
Expand Down

0 comments on commit ef3c08e

Please sign in to comment.