Verified Commit 27c4fefa authored by Aral Balkan's avatar Aral Balkan

Merge branch 'v2'

parents bc9aca48 f47c9e99
//
// ApplicationWindowController.swift
// Better Mac
//
// Created by Aral Balkan on 22/08/2016.
// Copyright © 2016 Aral Balkan. All rights reserved.
//
import Cocoa
class ApplicationWindowController: NSWindowController
{
override func windowDidLoad()
{
// window?.titlebarAppearsTransparent = true
window?.titleVisibility = .hidden
// window?.styleMask = .miniaturizable
guard let storyboard = self.storyboard else { fatalError("Could not get storyboard reference.") }
guard let toolbarAccessory = storyboard.instantiateController(withIdentifier: "ToolbarAccessoryViewController") as? NSTitlebarAccessoryViewController else { fatalError("Could not instantiate toolbar accessory view controller.") }
window?.addTitlebarAccessoryViewController(toolbarAccessory)
}
}
//
// AppDelegate.swift
// Better Mac
//
// Created by Aral Balkan on 22/08/2016.
// Copyright © 2016 Aral Balkan. All rights reserved.
//
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
}
{
"images" : [
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "256x256",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "256x256",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "512x512",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "512x512",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2016 Aral Balkan. All rights reserved.</string>
<key>NSMainStoryboardFile</key>
<string>Main</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>
//
// ViewController.swift
// Better Mac
//
// Created by Aral Balkan on 22/08/2016.
// Copyright © 2016 Aral Balkan. All rights reserved.
//
import Cocoa
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildSystemType</key>
<string>Original</string>
</dict>
</plist>
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
//
// BetterNavigationBar.swift
// Better
//
// Created by Aral Balkan on 30/12/2016.
// Copyright © 2016 Aral Balkan. All rights reserved.
//
import Cocoa
class BetterTabBar: NSStackView, NSAccessibilityGroup
{
/// Accessibility: make the custom tab bar
/// present itself to the accessibility system as a tab bar.
required init?(coder: NSCoder)
{
super.init(coder: coder)
// We function as a tab group.
self.setAccessibilityRole(NSAccessibilityRole.radioGroup)
self.setAccessibilityRoleDescription("Tab bar")
}
}
//
// BetterTabButton.swift
// Better
//
// Created by Aral Balkan on 30/12/2016.
// Copyright © 2016 Aral Balkan. All rights reserved.
//
import Cocoa
class BetterTabButton: DVButton
{
/// Set the accessibility role for the tab button to tab.
required init?(coder: NSCoder)
{
super.init(coder:coder)
self.setAccessibilityRole(NSAccessibilityRole.radioButton)
self.setAccessibilityRoleDescription("Tab")
}
}
//
// BlockerStatus.swift
// Better Mac
//
// BlockerStatus.shared.check(BlockerStatusCompletionHandler)
//
// Created by Aral Balkan on 21/08/2016.
// Copyright © 2016 Aral Balkan. All rights reserved.
//
import Foundation
import SafariServices
import Handle
import Delay
class BlockerStatus: BlockerStatusBase
{
/// Singleton access: shared
static let shared = BlockerStatus()
override private init() {}
/// Checks if the content blocker extension is on in Settings.
override func check(completionHandler: @escaping BlockerStatusCompletionHandler )
{
// print("Checking if Better content blocker is active.")
// The ability to check is only available on El Capitan with Safari 10 or on macOS.
if SFSafariServicesAvailable()
{
SFContentBlockerManager.getStateOfContentBlocker(withIdentifier: BetterIdentifier.blocker)
{
/* with */ (state: SFContentBlockerState?, error: Error?) in
DispatchQueue.main.async { completionHandler(state?.isEnabled, error) }
}
}
else
{
// The API is not available; content blockers are not supported on this configuration.
self.completionHandler?(nil, BlockerStatusError.unsupported)
return
}
}
}
//
// ContentWebViewController.swift
// Better
//
// Created by Aral Balkan on 21/12/2016.
// Copyright © 2016 Aral Balkan. All rights reserved.
//
import Cocoa
import WebKit
import Handle
import Delay
class ContentWebViewController: SectionViewController, WKNavigationDelegate, WKScriptMessageHandler, TrackersListPopOverTableViewControllerDelegate
{
var webView: WKWebView?
var trackersListPopOverTableViewController: TrackersListPopOverTableViewControllerMac?
var popOver: NSPopover?
var betterDataUpdateHandler: NotificationHandler?
var viewConstraintsExist = false
//
// MARK: - View lifecycle.
//
/// Set up view.
override func viewDidLoad()
{
super.viewDidLoad()
// Create the web view
createWebView()
// Create the trackers list pop over table view controller
trackersListPopOverTableViewController = storyboard?.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "trackersListPopOverTableViewController")) as? TrackersListPopOverTableViewControllerMac
trackersListPopOverTableViewController?.delegate = self
// Handle data updates (reload the web view).
betterDataUpdateHandler = betterDataUpdateHandler ?? handle(BetterDataNotification.named(.UpdateDidSucceed))
{
/* with */ notification in
_ = self.webView?.reload()
}
}
//
// MARK: - Public
//
/// Reload the index.
override func loadContent()
{
var sectionName = section.rawValue
if sectionName == "exceptions" { sectionName = "" }
let indexURLString = "http://localhost:\(ContentWebServer.shared.port)/\(sectionName)"
// Check if the index is already showing and don’t reload it
// if it is, so that the content doesn’t flash.
let indexAlreadyShowing = (indexURLString == webView?.url?.absoluteString)
if !indexAlreadyShowing
{
_ = webView?.load(URLRequest(url: URL(string: "http://localhost:\(ContentWebServer.shared.port)/\(sectionName)")!))
}
}
//
// MARK: - Private
//
/// Creates and configures a web view and adds it to the view hierarchy.
func createWebView()
{
// Configuration for handling events (for popover)
let popOverMessageHandler = self
let personContentController = WKUserContentController()
personContentController.add(popOverMessageHandler, name: "popOverMessageHandler")
let webViewConfiguration = WKWebViewConfiguration()
webViewConfiguration.userContentController = personContentController
#if DEBUG
// Enable the inspector
webViewConfiguration.preferences.setValue(true, forKey: "developerExtrasEnabled")
#endif
let _webView = WKWebView(frame: NSRect.zero, configuration: webViewConfiguration)
view.addSubview(_webView)
_webView.allowsBackForwardNavigationGestures = true
_webView.allowsMagnification = false
_webView.translatesAutoresizingMaskIntoConstraints = false
_webView.navigationDelegate = self
_webView.wantsLayer = true
_webView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1.0, constant: 0.0).isActive = true
_webView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 1.0, constant: 0.0).isActive = true
_webView.topAnchor.constraint(equalTo: view.topAnchor, constant: 0.0).isActive = true
_webView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0.0).isActive = true
// Load the main page for the requested section.
webView = _webView
loadContent()
}
//
// MARK: - WebKit Navigation Delegate methods
//
// Signal that the content is ready.
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!)
{
// Execute on next run loop.
_ = delay(0)
{
self.delegate?.sectionViewControllerIsReady(self)
}
}
//
// MARK: - WebKit Script Message Handler Delegate methods
//
/// Handle tracker list show requests from the web content.
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)
{
guard let webView = message.webView else { fatalError("Message does not have a web view.") }
guard let trackersList = message.body as? TrackersList else { fatalError("Trackers list is an unexpected type.") }
trackersListPopOverTableViewController?.trackersList = trackersList
popOver = NSPopover()
popOver!.contentViewController = trackersListPopOverTableViewController
popOver!.behavior = .transient
popOver!.show(relativeTo: webView.bounds, of: webView, preferredEdge: .minY)
}
//
// MARK: - TrackersListPopOverTableViewControllerDelegate methods
//
/// Handle tracker selection.
func didSelectTracker(_ tracker:Tracker)
{
print("[Delegate] Did select tracker: \(tracker)")
guard let webView = self.webView else { fatalError("Could not unwrap web view") }
guard let trackerDomain = tracker["domain"] as? String else { fatalError("Could not get domain from tracker") }
// Close the pop-over
popOver?.close()
// Load the tracker information.
webView.load(URLRequest(url: URL(string: "http://localhost:\(ContentWebServer.shared.port)/trackers/\(trackerDomain)")!))
}
}
// Courtesy: https://www.raywenderlich.com/450-menus-and-popovers-in-menu-bar-apps-for-macos
import Cocoa
public class EventMonitor {
private var monitor: Any?
private let mask: NSEvent.EventTypeMask
private let handler: (NSEvent?) -> Void
public init(mask: NSEvent.EventTypeMask, handler: @escaping (NSEvent?) -> Void) {
self.mask = mask
self.handler = handler
}
deinit {
stop()
}
public func start() {
monitor = NSEvent.addGlobalMonitorForEvents(matching: mask, handler: handler)
}
public func stop() {
if monitor != nil {
NSEvent.removeMonitor(monitor!)
monitor = nil
}
}
}
......@@ -30,7 +30,7 @@ enum WeCan
/// in addition to the standard text field used for the domain name text.
class ExceptionCell: NSTableCellView, NSTextFieldDelegate
{
@IBOutlet weak var isActiveSwitch: ITSwitch!
@IBOutlet weak var isActiveSwitch: NSButton!
@IBOutlet weak var previewInSafariButton: NSButton!
@IBOutlet weak var emailDomainForReviewButton: NSButton!
......@@ -50,7 +50,15 @@ class ExceptionCell: NSTableCellView, NSTextFieldDelegate
/// State - returns the disabled/enabled state of the switch
var state:Bool
{
return isActiveSwitch.checked
get
{
return isActiveSwitch.state == NSControl.StateValue.on
}
set (value)
{
isActiveSwitch.state = value ? NSControl.StateValue.on : NSControl.StateValue.off
}
}
......@@ -69,6 +77,10 @@ class ExceptionCell: NSTableCellView, NSTextFieldDelegate
// Set email button state.
emailDomainForReviewButton.isEnabled = WeCan.sendEmail
// Make the button images template so they confirm to light/dark mode changes.
previewInSafariButton.image!.isTemplate = true
emailDomainForReviewButton.image!.isTemplate = true
}
......@@ -135,9 +147,9 @@ class ExceptionCell: NSTableCellView, NSTextFieldDelegate
/// Notifies listeners that the exception’s active state has changed.
@IBAction func switchStateDidChange(sender: ITSwitch)
@IBAction func switchStateDidChange(sender: NSButton)
{
let state = sender.checked
let state = sender.state == NSControl.StateValue.on
post(ExceptionNotification.named(.exceptionActiveStateDidChange), from: self, with: ["cell": self, "state": state])
}
......
......@@ -21,20 +21,8 @@ class ExceptionRow: NSTableRowView
if selectionHighlightStyle != .none
{
let selectionPath = NSBezierPath(rect: self.bounds)
if isEmphasized
{
// Set the color to the default Safari highlight color so that it matches
// the content in the rest of the app (which is display in WebKit views).
NSColor(red: 180/255, green: 213/255, blue: 254/255, alpha: 1.0).setFill()
}
else
{
// The app is disabled; set disabled the color to the grayscale equivalent
// via a simple averaging of the components.
NSColor(calibratedWhite: 0.845751634, alpha: 1.0).setFill()
}
NSColor.selectedTextBackgroundColor.setFill()
// NSColor(calibratedWhite: 0.845751634, alpha: 1.0).setFill()
selectionPath.fill()
}
}
......
This diff is collapsed.
//
// ExceptionsWindowController.swift
// Better Mac
//
// Created by Aral Balkan on 12/09/2018.
// Copyright © 2018 Aral Balkan. All rights reserved.
//
import Cocoa
class ExceptionsWindowController: NSWindowController {
override func windowDidLoad() {
super.windowDidLoad()
self.window!.backgroundColor = NSColor.windowBackgroundColor
}
}
......@@ -19,13 +19,15 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>2017.4</string>
<string>2018.1</string>
<key>CFBundleVersion</key>
<string>111</string><