├── .gitignore
├── Assets
├── AppIcon.png
└── Screenshot.png
├── Browsing
├── Base.lproj
│ └── SafariExtensionViewController.xib
├── Browsing.entitlements
├── BrowsingIcon.swift
├── Compass.pdf
├── IconFactory.swift
├── Info.plist
├── Mask.pdf
├── SafariExtensionHandler.swift
├── SafariExtensionViewController.swift
└── Unavailable.pdf
├── Gemfile
├── Gemfile.lock
├── IsItPrivate.xcodeproj
├── project.pbxproj
└── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── IsItPrivate
├── AboutWindow
│ ├── AboutWindowController.swift
│ ├── AboutWindowController.xib
│ └── ActionLabel.swift
├── AppDelegate.swift
├── DefaultWindow
│ ├── Base.lproj
│ │ └── Main.storyboard
│ ├── ExtensionStateManager.swift
│ ├── PreferencesViewController.swift
│ ├── TutorialViewController.swift
│ └── ViewController.swift
├── Extensions
│ └── NSViewController+Extension.swift
└── Resources
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon-128x128-@1x.png
│ │ ├── Icon-128x128-@2x.png
│ │ ├── Icon-16x16-@1x.png
│ │ ├── Icon-16x16-@2x.png
│ │ ├── Icon-256x256-@1x.png
│ │ ├── Icon-256x256-@2x.png
│ │ ├── Icon-32x32-@1x.png
│ │ ├── Icon-32x32-@2x.png
│ │ ├── Icon-512x512-@1x.png
│ │ └── Icon-512x512-@2x.png
│ ├── Contents.json
│ ├── Safari_Preferences.imageset
│ │ ├── Contents.json
│ │ ├── Safari_Preferences_Dark.png
│ │ ├── Safari_Preferences_Light-1.png
│ │ └── Safari_Preferences_Light.png
│ ├── Tutorial_Normal.imageset
│ │ ├── Contents.json
│ │ ├── Tutorial_Normal_Dark.png
│ │ ├── Tutorial_Normal_Light-1.png
│ │ └── Tutorial_Normal_Light.png
│ └── Tutorial_Private.imageset
│ │ ├── Contents.json
│ │ ├── Tutorial_Private_Dark.png
│ │ ├── Tutorial_Private_Light-1.png
│ │ └── Tutorial_Private_Light.png
│ ├── Info.plist
│ └── IsItPrivate.entitlements
├── LICENSE
├── PRIVACY.md
├── README.md
└── fastlane
├── Appfile
├── Fastfile
├── README.md
└── actions
└── appicon.rb
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/swift
3 |
4 | ### Swift ###
5 | # Xcode
6 | #
7 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
8 |
9 | ## Build generated
10 | build/
11 | DerivedData/
12 |
13 | ## Various settings
14 | *.pbxuser
15 | !default.pbxuser
16 | *.mode1v3
17 | !default.mode1v3
18 | *.mode2v3
19 | !default.mode2v3
20 | *.perspectivev3
21 | !default.perspectivev3
22 | xcuserdata/
23 |
24 | ## Other
25 | *.moved-aside
26 | *.xccheckout
27 | *.xcscmblueprint
28 |
29 | ## Obj-C/Swift specific
30 | *.hmap
31 | *.ipa
32 | *.dSYM.zip
33 | *.dSYM
34 |
35 | ## Playgrounds
36 | timeline.xctimeline
37 | playground.xcworkspace
38 |
39 | # Swift Package Manager
40 | #
41 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
42 | # Packages/
43 | # Package.pins
44 | # Package.resolved
45 | .build/
46 |
47 | # CocoaPods
48 | #
49 | # We recommend against adding the Pods directory to your .gitignore. However
50 | # you should judge for yourself, the pros and cons are mentioned at:
51 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
52 | #
53 | # Pods/
54 | #
55 | # Add this line if you want to avoid checking in source code from the Xcode workspace
56 | # *.xcworkspace
57 |
58 | # Carthage
59 | #
60 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
61 | # Carthage/Checkouts
62 |
63 | Carthage/Build
64 |
65 | # fastlane
66 | #
67 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
68 | # screenshots whenever they are needed.
69 | # For more information about the recommended setup visit:
70 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
71 |
72 | fastlane/report.xml
73 | fastlane/Preview.html
74 | fastlane/screenshots/**/*.png
75 | fastlane/test_output
76 |
77 | # Code Injection
78 | #
79 | # After new code Injection tools there's a generated folder /iOSInjectionProject
80 | # https://github.com/johnno1962/injectionforxcode
81 |
82 | iOSInjectionProject/
83 |
84 |
85 | # End of https://www.gitignore.io/api/swift
--------------------------------------------------------------------------------
/Assets/AppIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/Assets/AppIcon.png
--------------------------------------------------------------------------------
/Assets/Screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/Assets/Screenshot.png
--------------------------------------------------------------------------------
/Browsing/Base.lproj/SafariExtensionViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/Browsing/Browsing.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.files.user-selected.read-only
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Browsing/BrowsingIcon.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BrowsingIcon.swift
3 | // Browsing
4 | //
5 | // Created by Florian Fittschen on 22.10.18.
6 | // Copyright © 2018 Florian Fittschen. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import AppKit.NSImage
11 |
12 | enum BrowsingIcon: String {
13 | case Mask
14 | case Compass
15 | case Unavailable
16 | }
17 |
18 | extension BrowsingIcon {
19 | var url: URL {
20 | return URL(fileURLWithPath: Bundle.main.path(forResource: rawValue, ofType: "pdf")!)
21 | }
22 |
23 | var label: String {
24 | switch self {
25 | case .Compass:
26 | return "Private Browsing: Off"
27 | case .Mask:
28 | return "Private Browsing: On"
29 | case .Unavailable:
30 | return "Private Browsing: ?"
31 | }
32 | }
33 |
34 | var image: NSImage {
35 | return NSImage(contentsOf: url)!
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Browsing/Compass.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/Browsing/Compass.pdf
--------------------------------------------------------------------------------
/Browsing/IconFactory.swift:
--------------------------------------------------------------------------------
1 | //
2 | // IconFactory.swift
3 | // Browsing
4 | //
5 | // Created by Florian Fittschen on 22.10.18.
6 | // Copyright © 2018 Florian Fittschen. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import SafariServices
11 |
12 | struct IconFactory {
13 | static func icon(for window: SFSafariWindow, _ completionHandler: @escaping (BrowsingIcon?) -> Void) {
14 | window.getActiveTab { tab in
15 | IconFactory.icon(for: tab, completionHandler)
16 | }
17 | }
18 |
19 | static func icon(for tab: SFSafariTab?, _ completionHandler: @escaping (BrowsingIcon?) -> Void) {
20 | guard let tab = tab else {
21 | completionHandler(nil)
22 | return
23 | }
24 | tab.getActivePage { page in
25 | IconFactory.icon(for: page, completionHandler)
26 | }
27 | }
28 |
29 | static func icon(for page: SFSafariPage?, _ completionHandler: @escaping (BrowsingIcon?) -> Void) {
30 | guard let page = page else {
31 | completionHandler(nil)
32 | return
33 | }
34 | page.getPropertiesWithCompletionHandler { properties in
35 | IconFactory.icon(for: properties, completionHandler)
36 | }
37 | }
38 |
39 | static func icon(for properties: SFSafariPageProperties?, _ completionHandler: @escaping (BrowsingIcon?) -> Void) {
40 | guard let properties = properties else {
41 | completionHandler(nil)
42 | return
43 | }
44 | let icon: BrowsingIcon = properties.usesPrivateBrowsing ? .Mask : .Compass
45 | completionHandler(icon)
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Browsing/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | Private Browsing Detector
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | XPC!
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 2
23 | ITSAppUsesNonExemptEncryption
24 |
25 | LSMinimumSystemVersion
26 | $(MACOSX_DEPLOYMENT_TARGET)
27 | NSExtension
28 |
29 | NSExtensionPointIdentifier
30 | com.apple.Safari.extension
31 | NSExtensionPrincipalClass
32 | $(PRODUCT_MODULE_NAME).SafariExtensionHandler
33 | SFSafariToolbarItem
34 |
35 | Action
36 | Popover
37 | Identifier
38 | Button
39 | Image
40 | Compass.pdf
41 | Label
42 | Private Browsing: ?
43 |
44 | SFSafariWebsiteAccess
45 |
46 | Level
47 | All
48 |
49 |
50 | NSHumanReadableCopyright
51 | Copyright © 2018 Florian Fittschen. All rights reserved.
52 | NSHumanReadableDescription
53 | Adds a toolbar item that changes its icon to quickly identify if Private Browsing is enabled in the current Safari window.
54 |
55 |
56 |
--------------------------------------------------------------------------------
/Browsing/Mask.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/Browsing/Mask.pdf
--------------------------------------------------------------------------------
/Browsing/SafariExtensionHandler.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SafariExtensionHandler.swift
3 | // Browsing
4 | //
5 | // Created by Florian Fittschen on 19.10.18.
6 | // Copyright © 2018 Florian Fittschen. All rights reserved.
7 | //
8 |
9 | import SafariServices
10 |
11 | class SafariExtensionHandler: SFSafariExtensionHandler {
12 |
13 | override func messageReceived(withName messageName: String, from page: SFSafariPage, userInfo: [String : Any]?) {
14 | // This method will be called when a content script provided by your extension calls safari.extension.dispatchMessage("message").
15 |
16 | page.getPropertiesWithCompletionHandler { properties in
17 | NSLog("The extension received a message (\(messageName)) from a script injected into (\(String(describing: properties?.url))) with userInfo (\(userInfo ?? [:]))")
18 | }
19 | }
20 |
21 | override func toolbarItemClicked(in window: SFSafariWindow) {
22 | // This method will be called when your toolbar item is clicked.
23 | NSLog("The extension's toolbar item was clicked")
24 | }
25 |
26 | override func validateToolbarItem(in window: SFSafariWindow, validationHandler: @escaping ((Bool, String) -> Void)) {
27 | // This is called when Safari's state changed in some way that would require the extension's toolbar item to be validated again.
28 | NSLog("The extension's toolbar item was validated")
29 |
30 | IconFactory.icon(for: window) { icon in
31 | guard let icon = icon else { return }
32 | NSLog("Icon for window: \(icon)")
33 | window.getToolbarItem { toolbarItem in
34 | toolbarItem?.setImage(icon.image)
35 | toolbarItem?.setLabel(icon.label)
36 | }
37 | }
38 |
39 | validationHandler(true, "")
40 | }
41 |
42 | override func popoverViewController() -> SFSafariExtensionViewController {
43 | return SafariExtensionViewController.shared
44 | }
45 |
46 | override func popoverWillShow(in window: SFSafariWindow) {
47 | IconFactory.icon(for: window) { icon in
48 | guard let icon = icon else { return }
49 | SafariExtensionViewController.shared.configureLabel(with: icon)
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Browsing/SafariExtensionViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SafariExtensionViewController.swift
3 | // Browsing
4 | //
5 | // Created by Florian Fittschen on 19.10.18.
6 | // Copyright © 2018 Florian Fittschen. All rights reserved.
7 | //
8 |
9 | import SafariServices
10 |
11 | class SafariExtensionViewController: SFSafariExtensionViewController {
12 |
13 | @IBOutlet private weak var textField: NSTextField!
14 |
15 | static let shared: SafariExtensionViewController = {
16 | let shared = SafariExtensionViewController()
17 | shared.preferredContentSize = NSSize(width: 160, height: 42)
18 | return shared
19 | }()
20 |
21 | func configureLabel(with icon: BrowsingIcon) {
22 | NSLog("Label for Popover: \(icon.label)")
23 | textField.stringValue = icon.label
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Browsing/Unavailable.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/Browsing/Unavailable.pdf
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gem 'fastlane'
4 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | CFPropertyList (3.0.1)
5 | addressable (2.8.0)
6 | public_suffix (>= 2.0.2, < 5.0)
7 | atomos (0.1.3)
8 | babosa (1.0.2)
9 | claide (1.0.3)
10 | colored (1.2)
11 | colored2 (3.1.2)
12 | commander-fastlane (4.4.6)
13 | highline (~> 1.7.2)
14 | declarative (0.0.10)
15 | declarative-option (0.1.0)
16 | digest-crc (0.4.1)
17 | domain_name (0.5.20190701)
18 | unf (>= 0.0.5, < 1.0.0)
19 | dotenv (2.7.5)
20 | emoji_regex (1.0.1)
21 | excon (0.71.0)
22 | faraday (0.15.4)
23 | multipart-post (>= 1.2, < 3)
24 | faraday-cookie_jar (0.0.6)
25 | faraday (>= 0.7.4)
26 | http-cookie (~> 1.0.0)
27 | faraday_middleware (0.13.1)
28 | faraday (>= 0.7.4, < 1.0)
29 | fastimage (2.1.7)
30 | fastlane (2.131.0)
31 | CFPropertyList (>= 2.3, < 4.0.0)
32 | addressable (>= 2.3, < 3.0.0)
33 | babosa (>= 1.0.2, < 2.0.0)
34 | bundler (>= 1.12.0, < 3.0.0)
35 | colored
36 | commander-fastlane (>= 4.4.6, < 5.0.0)
37 | dotenv (>= 2.1.1, < 3.0.0)
38 | emoji_regex (>= 0.1, < 2.0)
39 | excon (>= 0.45.0, < 1.0.0)
40 | faraday (~> 0.9)
41 | faraday-cookie_jar (~> 0.0.6)
42 | faraday_middleware (~> 0.9)
43 | fastimage (>= 2.1.0, < 3.0.0)
44 | gh_inspector (>= 1.1.2, < 2.0.0)
45 | google-api-client (>= 0.21.2, < 0.24.0)
46 | google-cloud-storage (>= 1.15.0, < 2.0.0)
47 | highline (>= 1.7.2, < 2.0.0)
48 | json (< 3.0.0)
49 | jwt (~> 2.1.0)
50 | mini_magick (>= 4.9.4, < 5.0.0)
51 | multi_xml (~> 0.5)
52 | multipart-post (~> 2.0.0)
53 | plist (>= 3.1.0, < 4.0.0)
54 | public_suffix (~> 2.0.0)
55 | rubyzip (>= 1.2.2, < 2.0.0)
56 | security (= 0.1.3)
57 | simctl (~> 1.6.3)
58 | slack-notifier (>= 2.0.0, < 3.0.0)
59 | terminal-notifier (>= 2.0.0, < 3.0.0)
60 | terminal-table (>= 1.4.5, < 2.0.0)
61 | tty-screen (>= 0.6.3, < 1.0.0)
62 | tty-spinner (>= 0.8.0, < 1.0.0)
63 | word_wrap (~> 1.0.0)
64 | xcodeproj (>= 1.8.1, < 2.0.0)
65 | xcpretty (~> 0.3.0)
66 | xcpretty-travis-formatter (>= 0.0.3)
67 | gh_inspector (1.1.3)
68 | google-api-client (0.23.9)
69 | addressable (~> 2.5, >= 2.5.1)
70 | googleauth (>= 0.5, < 0.7.0)
71 | httpclient (>= 2.8.1, < 3.0)
72 | mime-types (~> 3.0)
73 | representable (~> 3.0)
74 | retriable (>= 2.0, < 4.0)
75 | signet (~> 0.9)
76 | google-cloud-core (1.3.1)
77 | google-cloud-env (~> 1.0)
78 | google-cloud-env (1.2.1)
79 | faraday (~> 0.11)
80 | google-cloud-storage (1.16.0)
81 | digest-crc (~> 0.4)
82 | google-api-client (~> 0.23)
83 | google-cloud-core (~> 1.2)
84 | googleauth (>= 0.6.2, < 0.10.0)
85 | googleauth (0.6.7)
86 | faraday (~> 0.12)
87 | jwt (>= 1.4, < 3.0)
88 | memoist (~> 0.16)
89 | multi_json (~> 1.11)
90 | os (>= 0.9, < 2.0)
91 | signet (~> 0.7)
92 | highline (1.7.10)
93 | http-cookie (1.0.3)
94 | domain_name (~> 0.5)
95 | httpclient (2.8.3)
96 | json (2.3.1)
97 | jwt (2.1.0)
98 | memoist (0.16.0)
99 | mime-types (3.3)
100 | mime-types-data (~> 3.2015)
101 | mime-types-data (3.2019.0904)
102 | mini_magick (4.9.5)
103 | multi_json (1.13.1)
104 | multi_xml (0.6.0)
105 | multipart-post (2.0.0)
106 | nanaimo (0.2.6)
107 | naturally (2.2.0)
108 | os (1.0.1)
109 | plist (3.5.0)
110 | public_suffix (2.0.5)
111 | representable (3.0.4)
112 | declarative (< 0.1.0)
113 | declarative-option (< 0.2.0)
114 | uber (< 0.2.0)
115 | retriable (3.1.2)
116 | rouge (2.0.7)
117 | rubyzip (1.3.0)
118 | security (0.1.3)
119 | signet (0.11.0)
120 | addressable (~> 2.3)
121 | faraday (~> 0.9)
122 | jwt (>= 1.5, < 3.0)
123 | multi_json (~> 1.10)
124 | simctl (1.6.6)
125 | CFPropertyList
126 | naturally
127 | slack-notifier (2.3.2)
128 | terminal-notifier (2.0.0)
129 | terminal-table (1.8.0)
130 | unicode-display_width (~> 1.1, >= 1.1.1)
131 | tty-cursor (0.7.0)
132 | tty-screen (0.7.0)
133 | tty-spinner (0.9.1)
134 | tty-cursor (~> 0.7)
135 | uber (0.1.0)
136 | unf (0.1.4)
137 | unf_ext
138 | unf_ext (0.0.7.6)
139 | unicode-display_width (1.6.0)
140 | word_wrap (1.0.0)
141 | xcodeproj (1.12.0)
142 | CFPropertyList (>= 2.3.3, < 4.0)
143 | atomos (~> 0.1.3)
144 | claide (>= 1.0.2, < 2.0)
145 | colored2 (~> 3.1)
146 | nanaimo (~> 0.2.6)
147 | xcpretty (0.3.0)
148 | rouge (~> 2.0.7)
149 | xcpretty-travis-formatter (1.0.0)
150 | xcpretty (~> 0.2, >= 0.0.7)
151 |
152 | PLATFORMS
153 | ruby
154 |
155 | DEPENDENCIES
156 | fastlane
157 |
158 | BUNDLED WITH
159 | 2.0.2
160 |
--------------------------------------------------------------------------------
/IsItPrivate.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 041DE6AC217DC0C5006AF8AD /* Mask.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 041DE6AB217DC0C5006AF8AD /* Mask.pdf */; };
11 | 041DE6B0217DC0F0006AF8AD /* Compass.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 041DE6AF217DC0F0006AF8AD /* Compass.pdf */; };
12 | 041DE6B4217DD3A2006AF8AD /* IconFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 041DE6B3217DD3A2006AF8AD /* IconFactory.swift */; };
13 | 041DE6B6217DD7C0006AF8AD /* BrowsingIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 041DE6B5217DD7C0006AF8AD /* BrowsingIcon.swift */; };
14 | 041DE6BA217DE480006AF8AD /* Unavailable.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 041DE6B9217DE480006AF8AD /* Unavailable.pdf */; };
15 | 049AFCEA2179E00300AC25DC /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 049AFCE92179E00300AC25DC /* AppDelegate.swift */; };
16 | 049AFCEC2179E00300AC25DC /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 049AFCEB2179E00300AC25DC /* ViewController.swift */; };
17 | 049AFCEE2179E00400AC25DC /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 049AFCED2179E00400AC25DC /* Assets.xcassets */; };
18 | 049AFCF12179E00400AC25DC /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 049AFCEF2179E00400AC25DC /* Main.storyboard */; };
19 | 049AFD0E2179E03500AC25DC /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 049AFD0D2179E03500AC25DC /* Cocoa.framework */; };
20 | 049AFD112179E03500AC25DC /* SafariExtensionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 049AFD102179E03500AC25DC /* SafariExtensionHandler.swift */; };
21 | 049AFD132179E03500AC25DC /* SafariExtensionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 049AFD122179E03500AC25DC /* SafariExtensionViewController.swift */; };
22 | 049AFD162179E03500AC25DC /* SafariExtensionViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 049AFD142179E03500AC25DC /* SafariExtensionViewController.xib */; };
23 | 049AFD1F2179E03500AC25DC /* Browsing.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 049AFD0B2179E03500AC25DC /* Browsing.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
24 | 04A9DD5C2181F97600655766 /* PreferencesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04A9DD5B2181F97600655766 /* PreferencesViewController.swift */; };
25 | 04A9DD5F2181F98700655766 /* TutorialViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04A9DD5D2181F98700655766 /* TutorialViewController.swift */; };
26 | 04A9DD622182FBB900655766 /* ExtensionStateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04A9DD612182FBB900655766 /* ExtensionStateManager.swift */; };
27 | 04A9DD64218301C700655766 /* NSViewController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04A9DD63218301C700655766 /* NSViewController+Extension.swift */; };
28 | 04A9DD672183284D00655766 /* AboutWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04A9DD652183284D00655766 /* AboutWindowController.swift */; };
29 | 04A9DD682183284D00655766 /* AboutWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 04A9DD662183284D00655766 /* AboutWindowController.xib */; };
30 | 04A9DD6A21832EC200655766 /* ActionLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04A9DD6921832EC200655766 /* ActionLabel.swift */; };
31 | /* End PBXBuildFile section */
32 |
33 | /* Begin PBXContainerItemProxy section */
34 | 049AFD1D2179E03500AC25DC /* PBXContainerItemProxy */ = {
35 | isa = PBXContainerItemProxy;
36 | containerPortal = 049AFCDE2179E00300AC25DC /* Project object */;
37 | proxyType = 1;
38 | remoteGlobalIDString = 049AFD0A2179E03500AC25DC;
39 | remoteInfo = Browsing;
40 | };
41 | /* End PBXContainerItemProxy section */
42 |
43 | /* Begin PBXCopyFilesBuildPhase section */
44 | 049AFD232179E03500AC25DC /* Embed App Extensions */ = {
45 | isa = PBXCopyFilesBuildPhase;
46 | buildActionMask = 2147483647;
47 | dstPath = "";
48 | dstSubfolderSpec = 13;
49 | files = (
50 | 049AFD1F2179E03500AC25DC /* Browsing.appex in Embed App Extensions */,
51 | );
52 | name = "Embed App Extensions";
53 | runOnlyForDeploymentPostprocessing = 0;
54 | };
55 | /* End PBXCopyFilesBuildPhase section */
56 |
57 | /* Begin PBXFileReference section */
58 | 041DE6AB217DC0C5006AF8AD /* Mask.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = Mask.pdf; sourceTree = ""; };
59 | 041DE6AF217DC0F0006AF8AD /* Compass.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = Compass.pdf; sourceTree = ""; };
60 | 041DE6B3217DD3A2006AF8AD /* IconFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconFactory.swift; sourceTree = ""; };
61 | 041DE6B5217DD7C0006AF8AD /* BrowsingIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowsingIcon.swift; sourceTree = ""; };
62 | 041DE6B9217DE480006AF8AD /* Unavailable.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = Unavailable.pdf; sourceTree = ""; };
63 | 049AFCE62179E00300AC25DC /* IsItPrivate.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IsItPrivate.app; sourceTree = BUILT_PRODUCTS_DIR; };
64 | 049AFCE92179E00300AC25DC /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
65 | 049AFCEB2179E00300AC25DC /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
66 | 049AFCED2179E00400AC25DC /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
67 | 049AFCF02179E00400AC25DC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
68 | 049AFCF22179E00400AC25DC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
69 | 049AFCF32179E00400AC25DC /* IsItPrivate.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = IsItPrivate.entitlements; sourceTree = ""; };
70 | 049AFD0B2179E03500AC25DC /* Browsing.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Browsing.appex; sourceTree = BUILT_PRODUCTS_DIR; };
71 | 049AFD0D2179E03500AC25DC /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
72 | 049AFD102179E03500AC25DC /* SafariExtensionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariExtensionHandler.swift; sourceTree = ""; };
73 | 049AFD122179E03500AC25DC /* SafariExtensionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariExtensionViewController.swift; sourceTree = ""; };
74 | 049AFD152179E03500AC25DC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/SafariExtensionViewController.xib; sourceTree = ""; };
75 | 049AFD172179E03500AC25DC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
76 | 049AFD1C2179E03500AC25DC /* Browsing.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Browsing.entitlements; sourceTree = ""; };
77 | 04A9DD5B2181F97600655766 /* PreferencesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesViewController.swift; sourceTree = ""; };
78 | 04A9DD5D2181F98700655766 /* TutorialViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TutorialViewController.swift; sourceTree = ""; };
79 | 04A9DD612182FBB900655766 /* ExtensionStateManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionStateManager.swift; sourceTree = ""; };
80 | 04A9DD63218301C700655766 /* NSViewController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSViewController+Extension.swift"; sourceTree = ""; };
81 | 04A9DD652183284D00655766 /* AboutWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutWindowController.swift; sourceTree = ""; };
82 | 04A9DD662183284D00655766 /* AboutWindowController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AboutWindowController.xib; sourceTree = ""; };
83 | 04A9DD6921832EC200655766 /* ActionLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionLabel.swift; sourceTree = ""; };
84 | /* End PBXFileReference section */
85 |
86 | /* Begin PBXFrameworksBuildPhase section */
87 | 049AFCE32179E00300AC25DC /* Frameworks */ = {
88 | isa = PBXFrameworksBuildPhase;
89 | buildActionMask = 2147483647;
90 | files = (
91 | );
92 | runOnlyForDeploymentPostprocessing = 0;
93 | };
94 | 049AFD082179E03500AC25DC /* Frameworks */ = {
95 | isa = PBXFrameworksBuildPhase;
96 | buildActionMask = 2147483647;
97 | files = (
98 | 049AFD0E2179E03500AC25DC /* Cocoa.framework in Frameworks */,
99 | );
100 | runOnlyForDeploymentPostprocessing = 0;
101 | };
102 | /* End PBXFrameworksBuildPhase section */
103 |
104 | /* Begin PBXGroup section */
105 | 049AFCDD2179E00300AC25DC = {
106 | isa = PBXGroup;
107 | children = (
108 | 049AFCE82179E00300AC25DC /* IsItPrivate */,
109 | 049AFD0F2179E03500AC25DC /* Browsing */,
110 | 049AFD0C2179E03500AC25DC /* Frameworks */,
111 | 049AFCE72179E00300AC25DC /* Products */,
112 | );
113 | sourceTree = "";
114 | };
115 | 049AFCE72179E00300AC25DC /* Products */ = {
116 | isa = PBXGroup;
117 | children = (
118 | 049AFCE62179E00300AC25DC /* IsItPrivate.app */,
119 | 049AFD0B2179E03500AC25DC /* Browsing.appex */,
120 | );
121 | name = Products;
122 | sourceTree = "";
123 | };
124 | 049AFCE82179E00300AC25DC /* IsItPrivate */ = {
125 | isa = PBXGroup;
126 | children = (
127 | 049AFCE92179E00300AC25DC /* AppDelegate.swift */,
128 | 04A9DD6D21833A2F00655766 /* DefaultWindow */,
129 | 04A9DD6C21833A1C00655766 /* AboutWindow */,
130 | 04A9DD6B21833A1100655766 /* Extensions */,
131 | 04A9DD6E21833A4900655766 /* Resources */,
132 | );
133 | path = IsItPrivate;
134 | sourceTree = "";
135 | };
136 | 049AFD0C2179E03500AC25DC /* Frameworks */ = {
137 | isa = PBXGroup;
138 | children = (
139 | 049AFD0D2179E03500AC25DC /* Cocoa.framework */,
140 | );
141 | name = Frameworks;
142 | sourceTree = "";
143 | };
144 | 049AFD0F2179E03500AC25DC /* Browsing */ = {
145 | isa = PBXGroup;
146 | children = (
147 | 049AFD102179E03500AC25DC /* SafariExtensionHandler.swift */,
148 | 049AFD122179E03500AC25DC /* SafariExtensionViewController.swift */,
149 | 049AFD142179E03500AC25DC /* SafariExtensionViewController.xib */,
150 | 041DE6B3217DD3A2006AF8AD /* IconFactory.swift */,
151 | 041DE6B5217DD7C0006AF8AD /* BrowsingIcon.swift */,
152 | 041DE6B9217DE480006AF8AD /* Unavailable.pdf */,
153 | 041DE6AF217DC0F0006AF8AD /* Compass.pdf */,
154 | 041DE6AB217DC0C5006AF8AD /* Mask.pdf */,
155 | 049AFD172179E03500AC25DC /* Info.plist */,
156 | 049AFD1C2179E03500AC25DC /* Browsing.entitlements */,
157 | );
158 | path = Browsing;
159 | sourceTree = "";
160 | };
161 | 04A9DD6B21833A1100655766 /* Extensions */ = {
162 | isa = PBXGroup;
163 | children = (
164 | 04A9DD63218301C700655766 /* NSViewController+Extension.swift */,
165 | );
166 | path = Extensions;
167 | sourceTree = "";
168 | };
169 | 04A9DD6C21833A1C00655766 /* AboutWindow */ = {
170 | isa = PBXGroup;
171 | children = (
172 | 04A9DD652183284D00655766 /* AboutWindowController.swift */,
173 | 04A9DD662183284D00655766 /* AboutWindowController.xib */,
174 | 04A9DD6921832EC200655766 /* ActionLabel.swift */,
175 | );
176 | path = AboutWindow;
177 | sourceTree = "";
178 | };
179 | 04A9DD6D21833A2F00655766 /* DefaultWindow */ = {
180 | isa = PBXGroup;
181 | children = (
182 | 049AFCEF2179E00400AC25DC /* Main.storyboard */,
183 | 049AFCEB2179E00300AC25DC /* ViewController.swift */,
184 | 04A9DD612182FBB900655766 /* ExtensionStateManager.swift */,
185 | 04A9DD5B2181F97600655766 /* PreferencesViewController.swift */,
186 | 04A9DD5D2181F98700655766 /* TutorialViewController.swift */,
187 | );
188 | path = DefaultWindow;
189 | sourceTree = "";
190 | };
191 | 04A9DD6E21833A4900655766 /* Resources */ = {
192 | isa = PBXGroup;
193 | children = (
194 | 049AFCED2179E00400AC25DC /* Assets.xcassets */,
195 | 049AFCF22179E00400AC25DC /* Info.plist */,
196 | 049AFCF32179E00400AC25DC /* IsItPrivate.entitlements */,
197 | );
198 | path = Resources;
199 | sourceTree = "";
200 | };
201 | /* End PBXGroup section */
202 |
203 | /* Begin PBXNativeTarget section */
204 | 049AFCE52179E00300AC25DC /* IsItPrivate */ = {
205 | isa = PBXNativeTarget;
206 | buildConfigurationList = 049AFD012179E00400AC25DC /* Build configuration list for PBXNativeTarget "IsItPrivate" */;
207 | buildPhases = (
208 | 049AFCE22179E00300AC25DC /* Sources */,
209 | 049AFCE32179E00300AC25DC /* Frameworks */,
210 | 049AFCE42179E00300AC25DC /* Resources */,
211 | 049AFD232179E03500AC25DC /* Embed App Extensions */,
212 | );
213 | buildRules = (
214 | );
215 | dependencies = (
216 | 049AFD1E2179E03500AC25DC /* PBXTargetDependency */,
217 | );
218 | name = IsItPrivate;
219 | productName = IsItPrivate;
220 | productReference = 049AFCE62179E00300AC25DC /* IsItPrivate.app */;
221 | productType = "com.apple.product-type.application";
222 | };
223 | 049AFD0A2179E03500AC25DC /* Browsing */ = {
224 | isa = PBXNativeTarget;
225 | buildConfigurationList = 049AFD202179E03500AC25DC /* Build configuration list for PBXNativeTarget "Browsing" */;
226 | buildPhases = (
227 | 049AFD072179E03500AC25DC /* Sources */,
228 | 049AFD082179E03500AC25DC /* Frameworks */,
229 | 049AFD092179E03500AC25DC /* Resources */,
230 | );
231 | buildRules = (
232 | );
233 | dependencies = (
234 | );
235 | name = Browsing;
236 | productName = Browsing;
237 | productReference = 049AFD0B2179E03500AC25DC /* Browsing.appex */;
238 | productType = "com.apple.product-type.app-extension";
239 | };
240 | /* End PBXNativeTarget section */
241 |
242 | /* Begin PBXProject section */
243 | 049AFCDE2179E00300AC25DC /* Project object */ = {
244 | isa = PBXProject;
245 | attributes = {
246 | LastSwiftUpdateCheck = 1000;
247 | LastUpgradeCheck = 1000;
248 | ORGANIZATIONNAME = "Florian Fittschen";
249 | TargetAttributes = {
250 | 049AFCE52179E00300AC25DC = {
251 | CreatedOnToolsVersion = 10.0;
252 | };
253 | 049AFD0A2179E03500AC25DC = {
254 | CreatedOnToolsVersion = 10.0;
255 | };
256 | };
257 | };
258 | buildConfigurationList = 049AFCE12179E00300AC25DC /* Build configuration list for PBXProject "IsItPrivate" */;
259 | compatibilityVersion = "Xcode 9.3";
260 | developmentRegion = en;
261 | hasScannedForEncodings = 0;
262 | knownRegions = (
263 | en,
264 | Base,
265 | );
266 | mainGroup = 049AFCDD2179E00300AC25DC;
267 | productRefGroup = 049AFCE72179E00300AC25DC /* Products */;
268 | projectDirPath = "";
269 | projectRoot = "";
270 | targets = (
271 | 049AFCE52179E00300AC25DC /* IsItPrivate */,
272 | 049AFD0A2179E03500AC25DC /* Browsing */,
273 | );
274 | };
275 | /* End PBXProject section */
276 |
277 | /* Begin PBXResourcesBuildPhase section */
278 | 049AFCE42179E00300AC25DC /* Resources */ = {
279 | isa = PBXResourcesBuildPhase;
280 | buildActionMask = 2147483647;
281 | files = (
282 | 04A9DD682183284D00655766 /* AboutWindowController.xib in Resources */,
283 | 049AFCEE2179E00400AC25DC /* Assets.xcassets in Resources */,
284 | 049AFCF12179E00400AC25DC /* Main.storyboard in Resources */,
285 | );
286 | runOnlyForDeploymentPostprocessing = 0;
287 | };
288 | 049AFD092179E03500AC25DC /* Resources */ = {
289 | isa = PBXResourcesBuildPhase;
290 | buildActionMask = 2147483647;
291 | files = (
292 | 041DE6B0217DC0F0006AF8AD /* Compass.pdf in Resources */,
293 | 041DE6AC217DC0C5006AF8AD /* Mask.pdf in Resources */,
294 | 049AFD162179E03500AC25DC /* SafariExtensionViewController.xib in Resources */,
295 | 041DE6BA217DE480006AF8AD /* Unavailable.pdf in Resources */,
296 | );
297 | runOnlyForDeploymentPostprocessing = 0;
298 | };
299 | /* End PBXResourcesBuildPhase section */
300 |
301 | /* Begin PBXSourcesBuildPhase section */
302 | 049AFCE22179E00300AC25DC /* Sources */ = {
303 | isa = PBXSourcesBuildPhase;
304 | buildActionMask = 2147483647;
305 | files = (
306 | 049AFCEC2179E00300AC25DC /* ViewController.swift in Sources */,
307 | 049AFCEA2179E00300AC25DC /* AppDelegate.swift in Sources */,
308 | 04A9DD6A21832EC200655766 /* ActionLabel.swift in Sources */,
309 | 04A9DD622182FBB900655766 /* ExtensionStateManager.swift in Sources */,
310 | 04A9DD5F2181F98700655766 /* TutorialViewController.swift in Sources */,
311 | 04A9DD64218301C700655766 /* NSViewController+Extension.swift in Sources */,
312 | 04A9DD5C2181F97600655766 /* PreferencesViewController.swift in Sources */,
313 | 04A9DD672183284D00655766 /* AboutWindowController.swift in Sources */,
314 | );
315 | runOnlyForDeploymentPostprocessing = 0;
316 | };
317 | 049AFD072179E03500AC25DC /* Sources */ = {
318 | isa = PBXSourcesBuildPhase;
319 | buildActionMask = 2147483647;
320 | files = (
321 | 041DE6B4217DD3A2006AF8AD /* IconFactory.swift in Sources */,
322 | 041DE6B6217DD7C0006AF8AD /* BrowsingIcon.swift in Sources */,
323 | 049AFD132179E03500AC25DC /* SafariExtensionViewController.swift in Sources */,
324 | 049AFD112179E03500AC25DC /* SafariExtensionHandler.swift in Sources */,
325 | );
326 | runOnlyForDeploymentPostprocessing = 0;
327 | };
328 | /* End PBXSourcesBuildPhase section */
329 |
330 | /* Begin PBXTargetDependency section */
331 | 049AFD1E2179E03500AC25DC /* PBXTargetDependency */ = {
332 | isa = PBXTargetDependency;
333 | target = 049AFD0A2179E03500AC25DC /* Browsing */;
334 | targetProxy = 049AFD1D2179E03500AC25DC /* PBXContainerItemProxy */;
335 | };
336 | /* End PBXTargetDependency section */
337 |
338 | /* Begin PBXVariantGroup section */
339 | 049AFCEF2179E00400AC25DC /* Main.storyboard */ = {
340 | isa = PBXVariantGroup;
341 | children = (
342 | 049AFCF02179E00400AC25DC /* Base */,
343 | );
344 | name = Main.storyboard;
345 | sourceTree = "";
346 | };
347 | 049AFD142179E03500AC25DC /* SafariExtensionViewController.xib */ = {
348 | isa = PBXVariantGroup;
349 | children = (
350 | 049AFD152179E03500AC25DC /* Base */,
351 | );
352 | name = SafariExtensionViewController.xib;
353 | sourceTree = "";
354 | };
355 | /* End PBXVariantGroup section */
356 |
357 | /* Begin XCBuildConfiguration section */
358 | 049AFCFF2179E00400AC25DC /* Debug */ = {
359 | isa = XCBuildConfiguration;
360 | buildSettings = {
361 | ALWAYS_SEARCH_USER_PATHS = NO;
362 | CLANG_ANALYZER_NONNULL = YES;
363 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
364 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
365 | CLANG_CXX_LIBRARY = "libc++";
366 | CLANG_ENABLE_MODULES = YES;
367 | CLANG_ENABLE_OBJC_ARC = YES;
368 | CLANG_ENABLE_OBJC_WEAK = YES;
369 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
370 | CLANG_WARN_BOOL_CONVERSION = YES;
371 | CLANG_WARN_COMMA = YES;
372 | CLANG_WARN_CONSTANT_CONVERSION = YES;
373 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
374 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
375 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
376 | CLANG_WARN_EMPTY_BODY = YES;
377 | CLANG_WARN_ENUM_CONVERSION = YES;
378 | CLANG_WARN_INFINITE_RECURSION = YES;
379 | CLANG_WARN_INT_CONVERSION = YES;
380 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
381 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
382 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
383 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
384 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
385 | CLANG_WARN_STRICT_PROTOTYPES = YES;
386 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
387 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
388 | CLANG_WARN_UNREACHABLE_CODE = YES;
389 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
390 | CODE_SIGN_ENTITLEMENTS = "";
391 | CODE_SIGN_IDENTITY = "Mac Developer";
392 | COPY_PHASE_STRIP = NO;
393 | DEBUG_INFORMATION_FORMAT = dwarf;
394 | ENABLE_STRICT_OBJC_MSGSEND = YES;
395 | ENABLE_TESTABILITY = YES;
396 | GCC_C_LANGUAGE_STANDARD = gnu11;
397 | GCC_DYNAMIC_NO_PIC = NO;
398 | GCC_NO_COMMON_BLOCKS = YES;
399 | GCC_OPTIMIZATION_LEVEL = 0;
400 | GCC_PREPROCESSOR_DEFINITIONS = (
401 | "DEBUG=1",
402 | "$(inherited)",
403 | );
404 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
405 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
406 | GCC_WARN_UNDECLARED_SELECTOR = YES;
407 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
408 | GCC_WARN_UNUSED_FUNCTION = YES;
409 | GCC_WARN_UNUSED_VARIABLE = YES;
410 | MACOSX_DEPLOYMENT_TARGET = 10.14;
411 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
412 | MTL_FAST_MATH = YES;
413 | ONLY_ACTIVE_ARCH = YES;
414 | SDKROOT = macosx;
415 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
416 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
417 | };
418 | name = Debug;
419 | };
420 | 049AFD002179E00400AC25DC /* Release */ = {
421 | isa = XCBuildConfiguration;
422 | buildSettings = {
423 | ALWAYS_SEARCH_USER_PATHS = NO;
424 | CLANG_ANALYZER_NONNULL = YES;
425 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
426 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
427 | CLANG_CXX_LIBRARY = "libc++";
428 | CLANG_ENABLE_MODULES = YES;
429 | CLANG_ENABLE_OBJC_ARC = YES;
430 | CLANG_ENABLE_OBJC_WEAK = YES;
431 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
432 | CLANG_WARN_BOOL_CONVERSION = YES;
433 | CLANG_WARN_COMMA = YES;
434 | CLANG_WARN_CONSTANT_CONVERSION = YES;
435 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
436 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
437 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
438 | CLANG_WARN_EMPTY_BODY = YES;
439 | CLANG_WARN_ENUM_CONVERSION = YES;
440 | CLANG_WARN_INFINITE_RECURSION = YES;
441 | CLANG_WARN_INT_CONVERSION = YES;
442 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
443 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
444 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
445 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
446 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
447 | CLANG_WARN_STRICT_PROTOTYPES = YES;
448 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
449 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
450 | CLANG_WARN_UNREACHABLE_CODE = YES;
451 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
452 | CODE_SIGN_ENTITLEMENTS = "";
453 | CODE_SIGN_IDENTITY = "Mac Developer";
454 | COPY_PHASE_STRIP = NO;
455 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
456 | ENABLE_NS_ASSERTIONS = NO;
457 | ENABLE_STRICT_OBJC_MSGSEND = YES;
458 | GCC_C_LANGUAGE_STANDARD = gnu11;
459 | GCC_NO_COMMON_BLOCKS = YES;
460 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
461 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
462 | GCC_WARN_UNDECLARED_SELECTOR = YES;
463 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
464 | GCC_WARN_UNUSED_FUNCTION = YES;
465 | GCC_WARN_UNUSED_VARIABLE = YES;
466 | MACOSX_DEPLOYMENT_TARGET = 10.14;
467 | MTL_ENABLE_DEBUG_INFO = NO;
468 | MTL_FAST_MATH = YES;
469 | SDKROOT = macosx;
470 | SWIFT_COMPILATION_MODE = wholemodule;
471 | SWIFT_OPTIMIZATION_LEVEL = "-O";
472 | };
473 | name = Release;
474 | };
475 | 049AFD022179E00400AC25DC /* Debug */ = {
476 | isa = XCBuildConfiguration;
477 | buildSettings = {
478 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
479 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
480 | CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/IsItPrivate/Resources/IsItPrivate.entitlements";
481 | CODE_SIGN_STYLE = Automatic;
482 | COMBINE_HIDPI_IMAGES = YES;
483 | DEVELOPMENT_TEAM = F9Y6K72HCR;
484 | INFOPLIST_FILE = "$(SRCROOT)/IsItPrivate/Resources/Info.plist";
485 | LD_RUNPATH_SEARCH_PATHS = (
486 | "$(inherited)",
487 | "@executable_path/../Frameworks",
488 | );
489 | PRODUCT_BUNDLE_IDENTIFIER = com.fittschen.IsItPrivate;
490 | PRODUCT_NAME = "$(TARGET_NAME)";
491 | SWIFT_VERSION = 4.2;
492 | };
493 | name = Debug;
494 | };
495 | 049AFD032179E00400AC25DC /* Release */ = {
496 | isa = XCBuildConfiguration;
497 | buildSettings = {
498 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
499 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
500 | CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/IsItPrivate/Resources/IsItPrivate.entitlements";
501 | CODE_SIGN_STYLE = Automatic;
502 | COMBINE_HIDPI_IMAGES = YES;
503 | DEVELOPMENT_TEAM = F9Y6K72HCR;
504 | INFOPLIST_FILE = "$(SRCROOT)/IsItPrivate/Resources/Info.plist";
505 | LD_RUNPATH_SEARCH_PATHS = (
506 | "$(inherited)",
507 | "@executable_path/../Frameworks",
508 | );
509 | PRODUCT_BUNDLE_IDENTIFIER = com.fittschen.IsItPrivate;
510 | PRODUCT_NAME = "$(TARGET_NAME)";
511 | SWIFT_VERSION = 4.2;
512 | };
513 | name = Release;
514 | };
515 | 049AFD212179E03500AC25DC /* Debug */ = {
516 | isa = XCBuildConfiguration;
517 | buildSettings = {
518 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
519 | CODE_SIGN_ENTITLEMENTS = Browsing/Browsing.entitlements;
520 | CODE_SIGN_STYLE = Automatic;
521 | DEVELOPMENT_TEAM = F9Y6K72HCR;
522 | INFOPLIST_FILE = Browsing/Info.plist;
523 | LD_RUNPATH_SEARCH_PATHS = (
524 | "$(inherited)",
525 | "@executable_path/../Frameworks",
526 | "@executable_path/../../../../Frameworks",
527 | );
528 | PRODUCT_BUNDLE_IDENTIFIER = com.fittschen.IsItPrivate.Browsing;
529 | PRODUCT_NAME = "$(TARGET_NAME)";
530 | SKIP_INSTALL = YES;
531 | SWIFT_VERSION = 4.2;
532 | };
533 | name = Debug;
534 | };
535 | 049AFD222179E03500AC25DC /* Release */ = {
536 | isa = XCBuildConfiguration;
537 | buildSettings = {
538 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
539 | CODE_SIGN_ENTITLEMENTS = Browsing/Browsing.entitlements;
540 | CODE_SIGN_STYLE = Automatic;
541 | DEVELOPMENT_TEAM = F9Y6K72HCR;
542 | INFOPLIST_FILE = Browsing/Info.plist;
543 | LD_RUNPATH_SEARCH_PATHS = (
544 | "$(inherited)",
545 | "@executable_path/../Frameworks",
546 | "@executable_path/../../../../Frameworks",
547 | );
548 | PRODUCT_BUNDLE_IDENTIFIER = com.fittschen.IsItPrivate.Browsing;
549 | PRODUCT_NAME = "$(TARGET_NAME)";
550 | SKIP_INSTALL = YES;
551 | SWIFT_VERSION = 4.2;
552 | };
553 | name = Release;
554 | };
555 | /* End XCBuildConfiguration section */
556 |
557 | /* Begin XCConfigurationList section */
558 | 049AFCE12179E00300AC25DC /* Build configuration list for PBXProject "IsItPrivate" */ = {
559 | isa = XCConfigurationList;
560 | buildConfigurations = (
561 | 049AFCFF2179E00400AC25DC /* Debug */,
562 | 049AFD002179E00400AC25DC /* Release */,
563 | );
564 | defaultConfigurationIsVisible = 0;
565 | defaultConfigurationName = Release;
566 | };
567 | 049AFD012179E00400AC25DC /* Build configuration list for PBXNativeTarget "IsItPrivate" */ = {
568 | isa = XCConfigurationList;
569 | buildConfigurations = (
570 | 049AFD022179E00400AC25DC /* Debug */,
571 | 049AFD032179E00400AC25DC /* Release */,
572 | );
573 | defaultConfigurationIsVisible = 0;
574 | defaultConfigurationName = Release;
575 | };
576 | 049AFD202179E03500AC25DC /* Build configuration list for PBXNativeTarget "Browsing" */ = {
577 | isa = XCConfigurationList;
578 | buildConfigurations = (
579 | 049AFD212179E03500AC25DC /* Debug */,
580 | 049AFD222179E03500AC25DC /* Release */,
581 | );
582 | defaultConfigurationIsVisible = 0;
583 | defaultConfigurationName = Release;
584 | };
585 | /* End XCConfigurationList section */
586 | };
587 | rootObject = 049AFCDE2179E00300AC25DC /* Project object */;
588 | }
589 |
--------------------------------------------------------------------------------
/IsItPrivate.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/IsItPrivate.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/IsItPrivate/AboutWindow/AboutWindowController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AboutWindowController.swift
3 | // IsItPrivate
4 | //
5 | // Created by Florian Fittschen on 26.10.18.
6 | // Copyright © 2018 Florian Fittschen. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | class AboutWindowController: NSWindowController {
12 |
13 | @IBOutlet weak var applicationNameLabel: NSTextField!
14 | @IBOutlet weak var versionLabel: NSTextField!
15 | @IBOutlet weak var buildLabel: NSTextField!
16 | @IBOutlet weak var creatorLabel: ActionLabel!
17 | @IBOutlet weak var repositoryLabel: ActionLabel!
18 | @IBOutlet weak var maskCreatorLabel: ActionLabel!
19 | @IBOutlet weak var compassCreatorLabel: ActionLabel!
20 | @IBOutlet weak var licenseLabel: NSTextField!
21 |
22 | convenience init() {
23 | self.init(windowNibName: "AboutWindowController")
24 | }
25 |
26 | override func windowDidLoad() {
27 | super.windowDidLoad()
28 |
29 | // close the window when the escape key is pressed
30 | NSEvent.addLocalMonitorForEvents(matching: .keyDown) { event in
31 | guard event.keyCode == 53 else { return event }
32 |
33 | self.closeAnimated()
34 |
35 | return nil
36 | }
37 |
38 | window?.collectionBehavior = [.transient, .ignoresCycle]
39 | window?.isMovableByWindowBackground = true
40 |
41 | guard let info = Bundle.main.infoDictionary else { return }
42 |
43 | configureUIFor(infoDictionary: info)
44 | }
45 |
46 | private func configureUIFor(infoDictionary info: [String: Any]) {
47 | applicationNameLabel.stringValue = info.stringOrEmpty(for: "CFBundleName")
48 | versionLabel.stringValue = info.stringOrEmpty(for: "CFBundleShortVersionString")
49 | buildLabel.stringValue = info.stringOrEmpty(for: "CFBundleVersionString")
50 | licenseLabel.stringValue = info.stringOrEmpty(for: "FFBundleLicenseName")
51 | creatorLabel.stringValue = info.stringOrEmpty(for: "FFBundleMainDeveloperName")
52 | repositoryLabel.stringValue = info.stringOrEmpty(for: "FFBundleRepositoryName")
53 |
54 | mainDeveloperWebsite = URL(string: info.stringOrEmpty(for: "FFBundleMainDeveloperWebsite"))
55 | repositoryWebsite = URL(string: info.stringOrEmpty(for: "FFBundleRepositoryWebsite"))
56 | maskCreatorWebsite = URL(string: info.stringOrEmpty(for: "FFBundleMaskIconCreatorWebsite"))
57 | compassCreatorWebsite = URL(string: info.stringOrEmpty(for: "FFBundleCompassIconCreatorWebsite"))
58 |
59 | configureActionLabel(creatorLabel, selector: #selector(openMainDeveloperWebsite))
60 | configureActionLabel(repositoryLabel, selector: #selector(openRepositoryWebsite))
61 | configureActionLabel(maskCreatorLabel, selector: #selector(openMaskIconCreatorWebsite))
62 | configureActionLabel(compassCreatorLabel, selector: #selector(openCompassIconCreatorWebsite))
63 |
64 | }
65 |
66 | private func configureActionLabel(_ label: ActionLabel, selector: Selector) {
67 | label.alphaValue = 0.8
68 | label.textColor = NSColor(red:0.023, green:0.752, blue:0.905, alpha:1)
69 | label.target = self
70 | label.action = selector
71 | }
72 |
73 | private var mainDeveloperWebsite: URL?
74 | private var repositoryWebsite: URL?
75 | private var maskCreatorWebsite: URL?
76 | private var compassCreatorWebsite: URL?
77 |
78 | @IBAction private func openMainDeveloperWebsite(_ sender: Any) {
79 | guard let mainDeveloperWebsite = mainDeveloperWebsite else { return }
80 |
81 | NSWorkspace.shared.open(mainDeveloperWebsite)
82 | }
83 |
84 | @IBAction private func openRepositoryWebsite(_ sender: Any) {
85 | guard let repositoryWebsite = repositoryWebsite else { return }
86 |
87 | NSWorkspace.shared.open(repositoryWebsite)
88 | }
89 |
90 | @IBAction private func openMaskIconCreatorWebsite(_ sender: Any) {
91 | guard let maskCreatorWebsite = maskCreatorWebsite else { return }
92 |
93 | NSWorkspace.shared.open(maskCreatorWebsite)
94 | }
95 |
96 | @IBAction private func openCompassIconCreatorWebsite(_ sender: Any) {
97 | guard let compassCreatorWebsite = compassCreatorWebsite else { return }
98 |
99 | NSWorkspace.shared.open(compassCreatorWebsite)
100 | }
101 |
102 | override func showWindow(_ sender: Any?) {
103 | window?.center()
104 | window?.alphaValue = 0.0
105 |
106 | super.showWindow(sender)
107 |
108 | window?.animator().alphaValue = 1.0
109 | }
110 |
111 | private func closeAnimated() {
112 | NSAnimationContext.beginGrouping()
113 | NSAnimationContext.current.duration = 0.4
114 | NSAnimationContext.current.completionHandler = {
115 | self.close()
116 | }
117 | window?.animator().alphaValue = 0.0
118 | NSAnimationContext.endGrouping()
119 | }
120 |
121 | }
122 |
123 | fileprivate extension Dictionary where Key == String, Value == Any {
124 | fileprivate func stringOrEmpty(for key: String) -> String {
125 | return (self[key] as? String) ?? ""
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/IsItPrivate/AboutWindow/AboutWindowController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
--------------------------------------------------------------------------------
/IsItPrivate/AboutWindow/ActionLabel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ActionLabel.swift
3 | // IsItPrivate
4 | //
5 | // Created by Florian Fittschen on 26.10.18.
6 | // Copyright © 2018 Florian Fittschen. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | final class ActionLabel: NSTextField {
12 |
13 | private var cursorTrackingArea: NSTrackingArea!
14 |
15 | override func updateTrackingAreas() {
16 | super.updateTrackingAreas()
17 |
18 | if cursorTrackingArea != nil {
19 | removeTrackingArea(cursorTrackingArea)
20 | }
21 |
22 | cursorTrackingArea = NSTrackingArea(rect: bounds,
23 | options: [.cursorUpdate, .inVisibleRect, .activeInActiveApp],
24 | owner: self,
25 | userInfo: nil)
26 | addTrackingArea(cursorTrackingArea)
27 | }
28 |
29 | override func cursorUpdate(with event: NSEvent) {
30 | if event.trackingArea == cursorTrackingArea {
31 | NSCursor.pointingHand.push()
32 | } else {
33 | super.cursorUpdate(with: event)
34 | }
35 | }
36 |
37 | override func mouseDown(with event: NSEvent) {
38 | if let action = action {
39 | NSApp.sendAction(action, to: target, from: self)
40 | }
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/IsItPrivate/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // IsItPrivate
4 | //
5 | // Created by Florian Fittschen on 19.10.18.
6 | // Copyright © 2018 Florian Fittschen. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | @NSApplicationMain
12 | class AppDelegate: NSObject, NSApplicationDelegate {
13 |
14 | private lazy var aboutWindowController: AboutWindowController = {
15 | return AboutWindowController()
16 | }()
17 |
18 | func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
19 | return true
20 | }
21 |
22 | func applicationWillBecomeActive(_ notification: Notification) {
23 | ExtensionStateManager.shared.fetchExtensionState()
24 |
25 | }
26 |
27 | @IBAction func showAboutWindow(_ sender: NSMenuItem) {
28 | aboutWindowController.showWindow(nil)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/IsItPrivate/DefaultWindow/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
--------------------------------------------------------------------------------
/IsItPrivate/DefaultWindow/ExtensionStateManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ExtensionStateManager.swift
3 | // IsItPrivate
4 | //
5 | // Created by Florian Fittschen on 26.10.18.
6 | // Copyright © 2018 Florian Fittschen. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import SafariServices
11 |
12 | protocol ExtensionStateManagerDelegate: class {
13 | func extensionStateChanged(from oldExtensionState: SFSafariExtensionState?, to newExtensionState: SFSafariExtensionState)
14 | }
15 |
16 | final class ExtensionStateManager {
17 |
18 | static let shared = ExtensionStateManager()
19 |
20 | weak var delegate: ExtensionStateManagerDelegate?
21 |
22 | let extensionIdentifier = "com.fittschen.IsItPrivate.Browsing"
23 |
24 | private var extensionState: SFSafariExtensionState? {
25 | didSet {
26 | guard let newValue = extensionState else { return }
27 | delegate?.extensionStateChanged(from: oldValue, to: newValue)
28 | }
29 | }
30 |
31 | private init() {
32 | fetchExtensionState()
33 | }
34 |
35 | func fetchExtensionState() {
36 | SFSafariExtensionManager.getStateOfSafariExtension(withIdentifier: extensionIdentifier) { [weak self] (state, error) in
37 | if let error = error {
38 | NSLog("Error fetching Safari Extension State: \(error.localizedDescription)")
39 | } else if let state = state {
40 | DispatchQueue.main.async {
41 | self?.extensionState = state
42 | }
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/IsItPrivate/DefaultWindow/PreferencesViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PreferencesViewController.swift
3 | // IsItPrivate
4 | //
5 | // Created by Florian Fittschen on 25.10.18.
6 | // Copyright © 2018 Florian Fittschen. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | class PreferencesViewController: NSViewController {
12 |
13 | override func viewDidLoad() {
14 | super.viewDidLoad()
15 | // Do view setup here.
16 | }
17 |
18 | override func viewWillAppear() {
19 | super.viewWillAppear()
20 | preferredContentSize = view.fittingSize
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/IsItPrivate/DefaultWindow/TutorialViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TutorialViewController.swift
3 | // IsItPrivate
4 | //
5 | // Created by Florian Fittschen on 25.10.18.
6 | // Copyright © 2018 Florian Fittschen. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | class TutorialViewController: NSViewController {
12 |
13 | @IBOutlet weak var imageView: NSImageView!
14 |
15 | override func viewDidLoad() {
16 | super.viewDidLoad()
17 | // Do view setup here.
18 | }
19 |
20 | override func viewWillAppear() {
21 | super.viewWillAppear()
22 | preferredContentSize = view.fittingSize
23 | }
24 |
25 | @IBAction func changeBrowsingMode(_ sender: NSSegmentedControl) {
26 | if sender.selectedSegment == 0 {
27 | imageView.image = #imageLiteral(resourceName: "Tutorial_Normal")
28 | } else if sender.selectedSegment == 1 {
29 | imageView.image = #imageLiteral(resourceName: "Tutorial_Private")
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/IsItPrivate/DefaultWindow/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // IsItPrivate
4 | //
5 | // Created by Florian Fittschen on 19.10.18.
6 | // Copyright © 2018 Florian Fittschen. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 | import SafariServices
11 |
12 | enum ContainerContent: String {
13 | case preferences
14 | case tutorial
15 | }
16 |
17 | extension ContainerContent {
18 | init(extensionState: SFSafariExtensionState) {
19 | if extensionState.isEnabled {
20 | self = .tutorial
21 | } else {
22 | self = .preferences
23 | }
24 | }
25 | }
26 |
27 | class ViewController: NSViewController {
28 |
29 | @IBOutlet weak var extensionStateLabel: NSTextField!
30 | @IBOutlet weak var openSafariPreferencesButton: NSButton!
31 | @IBOutlet weak var containerView: NSView!
32 | @IBOutlet weak var containerWidthConstraint: NSLayoutConstraint!
33 | @IBOutlet weak var containerHeightConstraint: NSLayoutConstraint!
34 |
35 | private var content: ContainerContent?
36 | private var shownViewController: NSViewController?
37 |
38 | override func viewDidLoad() {
39 | super.viewDidLoad()
40 |
41 | ExtensionStateManager.shared.delegate = self
42 | ExtensionStateManager.shared.fetchExtensionState()
43 | }
44 |
45 | @IBAction func openSafariPreferences(_ sender: NSButton) {
46 | SFSafariApplication.showPreferencesForExtension(withIdentifier: ExtensionStateManager.shared.extensionIdentifier) { error in
47 | if let error = error {
48 | NSLog("Error opening Safari Preferences: \(error.localizedDescription)")
49 | }
50 | }
51 | }
52 |
53 | private func transition(to content: ContainerContent) {
54 | shownViewController?.remove()
55 | let vc = createViewController(for: content)
56 | add(vc, view: containerView)
57 |
58 | shownViewController = vc
59 | self.content = content
60 |
61 | containerWidthConstraint.constant = vc.view.frame.width
62 | containerHeightConstraint.constant = vc.view.frame.height
63 | }
64 |
65 | private func createViewController(for content: ContainerContent) -> NSViewController {
66 | guard let storyboard = storyboard else {
67 | preconditionFailure("Can't transition to other ViewControllers without storyboard.")
68 | }
69 |
70 | switch content {
71 | case .preferences:
72 | return storyboard.instantiateController(withIdentifier: "PreferencesViewController") as! PreferencesViewController
73 | case .tutorial:
74 | return storyboard.instantiateController(withIdentifier: "TutorialViewController") as! TutorialViewController
75 | }
76 | }
77 |
78 | private func updateUI(for state: SFSafariExtensionState) {
79 | if state.isEnabled {
80 | extensionStateLabel.stringValue = "enabled ✅"
81 | openSafariPreferencesButton.title = "Open Safari Preferences"
82 | } else {
83 | extensionStateLabel.stringValue = "disabled ❌"
84 | openSafariPreferencesButton.title = "Enable Private Browsing Detector"
85 | }
86 | }
87 | }
88 |
89 | extension ViewController: ExtensionStateManagerDelegate {
90 | func extensionStateChanged(from oldExtensionState: SFSafariExtensionState?, to newExtensionState: SFSafariExtensionState) {
91 | let firstStateChange = oldExtensionState == nil
92 | let statesDiffer = oldExtensionState != nil && oldExtensionState!.isEnabled != newExtensionState.isEnabled
93 |
94 | guard firstStateChange || statesDiffer else {
95 | // We don't want to react to the same state
96 | return
97 | }
98 |
99 | updateUI(for: newExtensionState)
100 | transition(to: ContainerContent(extensionState: newExtensionState))
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/IsItPrivate/Extensions/NSViewController+Extension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NSViewController+Extension.swift
3 | // IsItPrivate
4 | //
5 | // Created by Florian Fittschen on 26.10.18.
6 | // Copyright © 2018 Florian Fittschen. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | @nonobjc extension NSViewController {
12 | func add(_ child: NSViewController, frame: CGRect? = nil) {
13 | addChild(child)
14 |
15 | if let frame = frame {
16 | child.view.frame = frame
17 | }
18 |
19 | view.addSubview(child.view)
20 | }
21 |
22 | func add(_ child: NSViewController, view: NSView) {
23 | addChild(child)
24 | view.addSubview(child.view)
25 | }
26 |
27 | func remove() {
28 | view.removeFromSuperview()
29 | removeFromParent()
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images": [
3 | {
4 | "idiom": "mac",
5 | "size": "16x16",
6 | "scale": "1x",
7 | "filename": "Icon-16x16-@1x.png"
8 | },
9 | {
10 | "idiom": "mac",
11 | "size": "16x16",
12 | "scale": "2x",
13 | "filename": "Icon-16x16-@2x.png"
14 | },
15 | {
16 | "idiom": "mac",
17 | "size": "32x32",
18 | "scale": "1x",
19 | "filename": "Icon-32x32-@1x.png"
20 | },
21 | {
22 | "idiom": "mac",
23 | "size": "32x32",
24 | "scale": "2x",
25 | "filename": "Icon-32x32-@2x.png"
26 | },
27 | {
28 | "idiom": "mac",
29 | "size": "128x128",
30 | "scale": "1x",
31 | "filename": "Icon-128x128-@1x.png"
32 | },
33 | {
34 | "idiom": "mac",
35 | "size": "128x128",
36 | "scale": "2x",
37 | "filename": "Icon-128x128-@2x.png"
38 | },
39 | {
40 | "idiom": "mac",
41 | "size": "256x256",
42 | "scale": "1x",
43 | "filename": "Icon-256x256-@1x.png"
44 | },
45 | {
46 | "idiom": "mac",
47 | "size": "256x256",
48 | "scale": "2x",
49 | "filename": "Icon-256x256-@2x.png"
50 | },
51 | {
52 | "idiom": "mac",
53 | "size": "512x512",
54 | "scale": "1x",
55 | "filename": "Icon-512x512-@1x.png"
56 | },
57 | {
58 | "idiom": "mac",
59 | "size": "512x512",
60 | "scale": "2x",
61 | "filename": "Icon-512x512-@2x.png"
62 | }
63 | ],
64 | "info": {
65 | "version": 1,
66 | "author": "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/AppIcon.appiconset/Icon-128x128-@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/IsItPrivate/Resources/Assets.xcassets/AppIcon.appiconset/Icon-128x128-@1x.png
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/AppIcon.appiconset/Icon-128x128-@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/IsItPrivate/Resources/Assets.xcassets/AppIcon.appiconset/Icon-128x128-@2x.png
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/AppIcon.appiconset/Icon-16x16-@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/IsItPrivate/Resources/Assets.xcassets/AppIcon.appiconset/Icon-16x16-@1x.png
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/AppIcon.appiconset/Icon-16x16-@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/IsItPrivate/Resources/Assets.xcassets/AppIcon.appiconset/Icon-16x16-@2x.png
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/AppIcon.appiconset/Icon-256x256-@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/IsItPrivate/Resources/Assets.xcassets/AppIcon.appiconset/Icon-256x256-@1x.png
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/AppIcon.appiconset/Icon-256x256-@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/IsItPrivate/Resources/Assets.xcassets/AppIcon.appiconset/Icon-256x256-@2x.png
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/AppIcon.appiconset/Icon-32x32-@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/IsItPrivate/Resources/Assets.xcassets/AppIcon.appiconset/Icon-32x32-@1x.png
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/AppIcon.appiconset/Icon-32x32-@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/IsItPrivate/Resources/Assets.xcassets/AppIcon.appiconset/Icon-32x32-@2x.png
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/AppIcon.appiconset/Icon-512x512-@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/IsItPrivate/Resources/Assets.xcassets/AppIcon.appiconset/Icon-512x512-@1x.png
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/AppIcon.appiconset/Icon-512x512-@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/IsItPrivate/Resources/Assets.xcassets/AppIcon.appiconset/Icon-512x512-@2x.png
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/Safari_Preferences.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "Safari_Preferences_Light-1.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "Safari_Preferences_Light.png",
11 | "appearances" : [
12 | {
13 | "appearance" : "luminosity",
14 | "value" : "light"
15 | }
16 | ],
17 | "scale" : "1x"
18 | },
19 | {
20 | "idiom" : "mac",
21 | "filename" : "Safari_Preferences_Dark.png",
22 | "appearances" : [
23 | {
24 | "appearance" : "luminosity",
25 | "value" : "dark"
26 | }
27 | ],
28 | "scale" : "1x"
29 | },
30 | {
31 | "idiom" : "mac",
32 | "scale" : "2x"
33 | },
34 | {
35 | "idiom" : "mac",
36 | "scale" : "2x",
37 | "appearances" : [
38 | {
39 | "appearance" : "luminosity",
40 | "value" : "light"
41 | }
42 | ]
43 | },
44 | {
45 | "idiom" : "mac",
46 | "scale" : "2x",
47 | "appearances" : [
48 | {
49 | "appearance" : "luminosity",
50 | "value" : "dark"
51 | }
52 | ]
53 | }
54 | ],
55 | "info" : {
56 | "version" : 1,
57 | "author" : "xcode"
58 | }
59 | }
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/Safari_Preferences.imageset/Safari_Preferences_Dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/IsItPrivate/Resources/Assets.xcassets/Safari_Preferences.imageset/Safari_Preferences_Dark.png
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/Safari_Preferences.imageset/Safari_Preferences_Light-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/IsItPrivate/Resources/Assets.xcassets/Safari_Preferences.imageset/Safari_Preferences_Light-1.png
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/Safari_Preferences.imageset/Safari_Preferences_Light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/IsItPrivate/Resources/Assets.xcassets/Safari_Preferences.imageset/Safari_Preferences_Light.png
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/Tutorial_Normal.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "Tutorial_Normal_Light.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "Tutorial_Normal_Light-1.png",
11 | "appearances" : [
12 | {
13 | "appearance" : "luminosity",
14 | "value" : "light"
15 | }
16 | ],
17 | "scale" : "1x"
18 | },
19 | {
20 | "idiom" : "mac",
21 | "filename" : "Tutorial_Normal_Dark.png",
22 | "appearances" : [
23 | {
24 | "appearance" : "luminosity",
25 | "value" : "dark"
26 | }
27 | ],
28 | "scale" : "1x"
29 | },
30 | {
31 | "idiom" : "mac",
32 | "scale" : "2x"
33 | },
34 | {
35 | "idiom" : "mac",
36 | "scale" : "2x",
37 | "appearances" : [
38 | {
39 | "appearance" : "luminosity",
40 | "value" : "light"
41 | }
42 | ]
43 | },
44 | {
45 | "idiom" : "mac",
46 | "scale" : "2x",
47 | "appearances" : [
48 | {
49 | "appearance" : "luminosity",
50 | "value" : "dark"
51 | }
52 | ]
53 | }
54 | ],
55 | "info" : {
56 | "version" : 1,
57 | "author" : "xcode"
58 | }
59 | }
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/Tutorial_Normal.imageset/Tutorial_Normal_Dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/IsItPrivate/Resources/Assets.xcassets/Tutorial_Normal.imageset/Tutorial_Normal_Dark.png
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/Tutorial_Normal.imageset/Tutorial_Normal_Light-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/IsItPrivate/Resources/Assets.xcassets/Tutorial_Normal.imageset/Tutorial_Normal_Light-1.png
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/Tutorial_Normal.imageset/Tutorial_Normal_Light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/IsItPrivate/Resources/Assets.xcassets/Tutorial_Normal.imageset/Tutorial_Normal_Light.png
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/Tutorial_Private.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "Tutorial_Private_Light.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "Tutorial_Private_Light-1.png",
11 | "appearances" : [
12 | {
13 | "appearance" : "luminosity",
14 | "value" : "light"
15 | }
16 | ],
17 | "scale" : "1x"
18 | },
19 | {
20 | "idiom" : "mac",
21 | "filename" : "Tutorial_Private_Dark.png",
22 | "appearances" : [
23 | {
24 | "appearance" : "luminosity",
25 | "value" : "dark"
26 | }
27 | ],
28 | "scale" : "1x"
29 | },
30 | {
31 | "idiom" : "mac",
32 | "scale" : "2x"
33 | },
34 | {
35 | "idiom" : "mac",
36 | "scale" : "2x",
37 | "appearances" : [
38 | {
39 | "appearance" : "luminosity",
40 | "value" : "light"
41 | }
42 | ]
43 | },
44 | {
45 | "idiom" : "mac",
46 | "scale" : "2x",
47 | "appearances" : [
48 | {
49 | "appearance" : "luminosity",
50 | "value" : "dark"
51 | }
52 | ]
53 | }
54 | ],
55 | "info" : {
56 | "version" : 1,
57 | "author" : "xcode"
58 | }
59 | }
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/Tutorial_Private.imageset/Tutorial_Private_Dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/IsItPrivate/Resources/Assets.xcassets/Tutorial_Private.imageset/Tutorial_Private_Dark.png
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/Tutorial_Private.imageset/Tutorial_Private_Light-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/IsItPrivate/Resources/Assets.xcassets/Tutorial_Private.imageset/Tutorial_Private_Light-1.png
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Assets.xcassets/Tutorial_Private.imageset/Tutorial_Private_Light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ffittschen/IsItPrivate/d61e9a5c765642dc5dd8b3aa8f1e73a4f0aea79f/IsItPrivate/Resources/Assets.xcassets/Tutorial_Private.imageset/Tutorial_Private_Light.png
--------------------------------------------------------------------------------
/IsItPrivate/Resources/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | Is It Private?
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 2
21 | FFBundleCompassIconCreatorWebsite
22 | https://thenounproject.com/xinhstudio
23 | FFBundleLicenseName
24 | BSD
25 | FFBundleMainDeveloperName
26 | Florian Fittschen
27 | FFBundleMainDeveloperWebsite
28 | https://twitter.com/flofi
29 | FFBundleMaskIconCreatorWebsite
30 | https://thenounproject.com/bfarias
31 | FFBundleRepositoryName
32 | ffittschen/isitprivate
33 | FFBundleRepositoryWebsite
34 | https://github.com/ffittschen/isitprivate
35 | ITSAppUsesNonExemptEncryption
36 |
37 | LSApplicationCategoryType
38 | public.app-category.productivity
39 | LSMinimumSystemVersion
40 | $(MACOSX_DEPLOYMENT_TARGET)
41 | NSHumanReadableCopyright
42 | Copyright © 2018 Florian Fittschen. All rights reserved.
43 | NSMainStoryboardFile
44 | Main
45 | NSPrincipalClass
46 | NSApplication
47 |
48 |
49 |
--------------------------------------------------------------------------------
/IsItPrivate/Resources/IsItPrivate.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.files.user-selected.read-only
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Florian Fittschen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/PRIVACY.md:
--------------------------------------------------------------------------------
1 | # Is It Private — Privacy Policy
2 |
3 | This privacy policy governs your use of the software application Is It Private ("Application"). The Application is a Safari App Extension providing a toolbar icon that changes its visual appearance if Private Browsing is enabled.
4 |
5 | The Application does not store or transmit any personal details, nor does it include advertising, tracking software or analytics software that talks to third parties.
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | # Is It Private?
8 |
9 | 
10 | [](https://github.com/ffittschen/IsItPrivate/releases/latest)
11 | [](https://github.com/ffittschen/IsItPrivate/blob/master/LICENSE)
12 |
13 | _Is It Private_ is a Safari Extension providing a toolbar icon that changes its visual appearance if Private Browsing is enabled. This is especially helpful when the Dark appearance of macOS is activated.
14 |
15 |
16 | ## Installation
17 |
18 | ### App Store
19 |
20 | _Is It Private_ is available on the [App Store](https://itunes.apple.com/de/app/is-it-private/id1440322906?l=en&mt=12) 🎉.
21 |
22 | ### GitHub Releases
23 |
24 | 1. Open the [releases](/releases) page and download the `IsItPrivate.app.zip` from the latest release.
25 | 1. Unzip the file and move `IsItPrivate.app` into your Applications folder.
26 |
27 |
28 | ### Build from Source
29 |
30 | 1. Clone this repository or download the source code of the [latest release](/releases/latest).
31 | 1. Open `IsItPrivate.xcodeproj` with Xcode and build the `IsItPrivate` scheme.
32 |
33 |
34 | ## Support
35 |
36 | If you encounter any problems, feel free to [open an issue](/issues) or contact me [on Twitter](https://twitter.com/flofi).
37 |
38 |
39 | ## Privacy Policy
40 |
41 | This privacy policy governs your use of the software application Is It Private ("Application"). The Application is a Safari App Extension providing a toolbar icon that changes its visual appearance if Private Browsing is enabled.
42 |
43 | The Application does not store or transmit any personal details, nor does it include advertising, tracking software or analytics software that talks to third parties.
44 |
45 |
46 | ## Attributions
47 |
48 | mask by b farias from the Noun Project -- [Link](https://thenounproject.com/browse/?i=795831)
49 |
50 | Compass by Xinh Studio from the Noun Project -- [Link](https://thenounproject.com/browse/?i=51854)
51 |
52 | ## License
53 |
54 | [MIT](LICENSE)
55 |
--------------------------------------------------------------------------------
/fastlane/Appfile:
--------------------------------------------------------------------------------
1 | # app_identifier("[[APP_IDENTIFIER]]") # The bundle identifier of your app
2 | # apple_id("[[APPLE_ID]]") # Your Apple email address
3 |
4 |
5 | # For more information about the Appfile, see:
6 | # https://docs.fastlane.tools/advanced/#appfile
7 |
--------------------------------------------------------------------------------
/fastlane/Fastfile:
--------------------------------------------------------------------------------
1 | # This file contains the fastlane.tools configuration
2 | # You can find the documentation at https://docs.fastlane.tools
3 | #
4 | # For a list of all available actions, check out
5 | #
6 | # https://docs.fastlane.tools/actions
7 | #
8 | # For a list of all available plugins, check out
9 | #
10 | # https://docs.fastlane.tools/plugins/available-plugins
11 | #
12 |
13 | # Uncomment the line if you want fastlane to automatically update itself
14 | # update_fastlane
15 |
16 | default_platform(:mac)
17 |
18 | platform :mac do
19 | desc "Description of what the lane does"
20 | lane :generate_icons do
21 | appicon(
22 | icon_path: "./Assets/AppIcon.png",
23 | asset_catalog_path: "./IsItPrivate/Assets.xcassets"
24 | )
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/fastlane/README.md:
--------------------------------------------------------------------------------
1 | fastlane documentation
2 | ================
3 | # Installation
4 |
5 | Make sure you have the latest version of the Xcode command line tools installed:
6 |
7 | ```
8 | xcode-select --install
9 | ```
10 |
11 | Install _fastlane_ using
12 | ```
13 | [sudo] gem install fastlane -NV
14 | ```
15 | or alternatively using `brew cask install fastlane`
16 |
17 | # Available Actions
18 | ## Mac
19 | ### mac generate_icons
20 | ```
21 | fastlane mac generate_icons
22 | ```
23 | Description of what the lane does
24 |
25 | ----
26 |
27 | This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run.
28 | More information about fastlane can be found on [fastlane.tools](https://fastlane.tools).
29 | The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools).
30 |
--------------------------------------------------------------------------------
/fastlane/actions/appicon.rb:
--------------------------------------------------------------------------------
1 | module Fastlane
2 | module Actions
3 |
4 | class AppiconAction < Action
5 | def self.run(params)
6 |
7 | icon_sets = Dir.glob(File.join(params[:asset_catalog_path], '*.appiconset'))
8 | UI.user_error!("Could not find any app icon sets in the specified asset catalog. Please create one first!") unless icon_sets.size > 0
9 |
10 | if icon_sets.size > 1
11 | UI.message "Select Icon Set: "
12 | icon_set = choose(*(icon_sets))
13 | else
14 | icon_set = icon_sets.first
15 | end
16 |
17 | contents_file = File.join(icon_set, 'Contents.json')
18 | contentsJSON = JSON.parse(File.read(contents_file))
19 |
20 | contentsJSON['images'].each do |image|
21 | image_size = image['size']
22 | image_scale = image['scale']
23 |
24 | scaled_image_width = Integer(image_size.split('x').first.to_f * image_scale.sub('x', '').to_f)
25 | scaled_image_name = "Icon-#{image_size}-@#{image_scale}#{File.extname(params[:icon_path])}"
26 | scaled_image_output = File.join(icon_set, scaled_image_name)
27 |
28 | UI.message "Generating #{image_size} @ #{image_scale} 🎨"
29 | if system("convert #{params[:icon_path].shellescape} -resize #{scaled_image_width}x#{scaled_image_width} #{scaled_image_output.shellescape}")
30 |
31 | current_icon_name = image['filename']
32 | if current_icon_name
33 | current_icon_file = File.join(icon_set, current_icon_name)
34 | if File.exist?(current_icon_file) and !scaled_image_name.eql?(current_icon_name)
35 | FileUtils.rm(current_icon_file)
36 | end
37 | end
38 |
39 | image['filename'] = scaled_image_name
40 | else
41 | UI.crash!("Failed to run: 'convert #{params[:icon_path].shellescape} -resize #{scaled_image_width}x#{scaled_image_width} #{scaled_image_output.shellescape}'")
42 | end
43 |
44 | end
45 |
46 | # Save the new Contents.json
47 | File.open(contents_file, "w") do |file|
48 | file.write(JSON.pretty_generate(contentsJSON))
49 | end
50 |
51 | UI.success "Successfully generated and installed the app icons 🎉"
52 | end
53 |
54 | #####################################################
55 | # @!group Documentation
56 | #####################################################
57 |
58 | def self.description
59 | "Generate and install icons into an Xcode Asset Catalog"
60 | end
61 |
62 | def self.available_options
63 | [
64 | FastlaneCore::ConfigItem.new(key: :icon_path,
65 | env_name: "FL_APPICON_PATH",
66 | description: "Path to the 1024x1024 iTunes icon png",
67 | is_string: true,
68 | verify_block: proc do |value|
69 | UI.user_error!("Couldn't find the specified icon at path '#{value}'") unless File.exist?(value)
70 | end
71 | ),
72 | FastlaneCore::ConfigItem.new(key: :asset_catalog_path,
73 | env_name: "FL_ASSET_CATALOG_PATH",
74 | description: "Path to the asset catalog, which holds your *.appiconset",
75 | is_string: true,
76 | verify_block: proc do |value|
77 | UI.user_error!("Couldn't find the specified asset catalog at path '#{value}'") unless File.exist?(value)
78 | UI.user_error!("It seems that you did not specify a valid asset catalog. It needs to be a .xcassets directory.") unless File.directory?(value) and File.extname(value).eql?('.xcassets')
79 | end
80 | )
81 | ]
82 | end
83 |
84 | def self.authors
85 | ["ffittschen"]
86 | end
87 |
88 | def self.is_supported?(platform)
89 | true
90 | end
91 | end
92 | end
93 | end
94 |
--------------------------------------------------------------------------------