Full Code of Mortennn/Dozer for AI

master b0540378c016 cached
42 files
96.8 KB
25.4k tokens
1 requests
Download .txt
Repository: Mortennn/Dozer
Branch: master
Commit: b0540378c016
Files: 42
Total size: 96.8 KB

Directory structure:
gitextract_h3o59koz/

├── .gitignore
├── .swiftlint.yml
├── Brewfile
├── Brewfile.lock.json
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Cartfile
├── Cartfile.resolved
├── Configs/
│   ├── Debug.xcconfig
│   └── Release.xcconfig
├── Dozer/
│   ├── AppDelegate.swift
│   ├── Constants.swift
│   ├── DozerIcons.swift
│   ├── Other/
│   │   ├── Assets.xcassets/
│   │   │   ├── AppIcon.appiconset/
│   │   │   │   └── Contents.json
│   │   │   ├── Contents.json
│   │   │   └── HelperStatusItemIcon.imageset/
│   │   │       └── Contents.json
│   │   ├── Dozer.entitlements
│   │   ├── Info.plist
│   │   ├── bridging-header.h
│   │   └── main.swift
│   ├── StatusIconClasses/
│   │   ├── HelperStatusIcon.swift
│   │   ├── NormalStatusIcon.swift
│   │   └── RemoveStatusIcon.swift
│   ├── Util.swift
│   ├── ViewControllers/
│   │   ├── DozerVC.swift
│   │   └── GeneralVC.swift
│   └── XIB/
│       ├── Dozer.xib
│       └── General.xib
├── LICENSE
├── Makefile
├── README.md
├── Scripts/
│   ├── LaunchAtLogin.sh
│   ├── SignFrameworks.sh
│   └── Swiftlint.sh
├── Stuff/
│   └── OldFiles/
│       ├── AnimationWindow.swift
│       ├── ClickedWindowInfo.swift
│       ├── CreateAnimation.swift
│       ├── GetLeftStatusIcon.swift
│       └── Screen.swift
├── appcast.xml
├── project.yml
└── swiftgen.yml

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
build/
.build/
Releases/
Dozer.xcodeproj/
Credentials/
Carthage/

# Fastlane
fastlane/
fastlaneLegacy/
Gemfile
Gemfile.lock

# Swiftgen
Dozer/Other/Generated/


================================================
FILE: .swiftlint.yml
================================================
whitelist_rules:
  - anyobject_protocol
  - array_init
  - attributes
  - block_based_kvo
  - class_delegate_protocol
  - closing_brace
  - closure_end_indentation
  - closure_parameter_position
  - closure_spacing
  - collection_alignment
  - colon
  - comma
  - compiler_protocol_init
  - conditional_returns_on_newline
  - contains_over_first_not_nil
  - control_statement
  - deployment_target
  - discarded_notification_center_observer
  - discouraged_direct_init
  - discouraged_object_literal
  - discouraged_optional_boolean
  - discouraged_optional_collection
  - duplicate_imports
  - dynamic_inline
  - empty_count
  - empty_enum_arguments
  - empty_parameters
  - empty_parentheses_with_trailing_closure
  - empty_string
  - empty_xctest_method
  - explicit_init
  - fallthrough
  - fatal_error_message
  - first_where
  - for_where
  - generic_type_name
  - identical_operands
  - identifier_name
  - implicit_getter
  - implicit_return
  - inert_defer
  - is_disjoint
  - joined_default_parameter
  - last_where
  - leading_whitespace
  - legacy_cggeometry_functions
  - legacy_constant
  - legacy_constructor
  - legacy_hashing
  - legacy_nsgeometry_functions
  - legacy_random
  - literal_expression_end_indentation
  - lower_acl_than_parent
  - mark
  - modifier_order
  - multiline_arguments
  - multiline_function_chains
  - multiline_literal_brackets
  - multiline_parameters
  - multiline_parameters_brackets
  - multiple_closures_with_trailing_closure
  - nimble_operator
  - no_extension_access_modifier
  - no_fallthrough_only
  - notification_center_detachment
  - number_separator
  - object_literal
  - opening_brace
  - operator_usage_whitespace
  - operator_whitespace
  - overridden_super_call
  - pattern_matching_keywords
  - private_action
  - private_outlet
  - private_unit_test
  - prohibited_super_call
  - protocol_property_accessors_order
  - redundant_discardable_let
  - redundant_nil_coalescing
  - redundant_objc_attribute
  - redundant_optional_initialization
  - redundant_set_access_control
  - redundant_string_enum_value
  - redundant_type_annotation
  - redundant_void_return
  - required_enum_case
  - return_arrow_whitespace
  - shorthand_operator
  - sorted_first_last
  - statement_position
  - static_operator
  - strong_iboutlet
  - superfluous_disable_command
  - switch_case_alignment
  - switch_case_on_newline
  - syntactic_sugar
  - todo
  - toggle_bool
  - trailing_closure
  - trailing_comma
  - trailing_newline
  - trailing_semicolon
  - trailing_whitespace
  - type_name
  - unavailable_function
  - unneeded_break_in_switch
  - unneeded_parentheses_in_closure_argument
  - untyped_error_in_catch
  - unused_closure_parameter
  - unused_control_flow_label
  - unused_enumerated
  - unused_optional_binding
  - unused_setter_value
  - valid_ibinspectable
  - vertical_parameter_alignment
  - vertical_parameter_alignment_on_call
  - vertical_whitespace_closing_braces
  - vertical_whitespace_opening_braces
  - void_return
  - weak_computed_property
  - weak_delegate
  - xct_specific_matcher
  - xctfail_message
  - yoda_condition
analyzer_rules:
  - unused_import
  - unused_private_declaration
force_cast: warning
force_unwrapping: warning
number_separator:
  minimum_length: 5
object_literal:
  image_literal: false
discouraged_object_literal:
  color_literal: false
identifier_name:
  max_length:
    warning: 100
    error: 100
  min_length:
    warning: 2
    error: 2
  validates_start_with_lowercase: false
  allowed_symbols:
    - '_'
  excluded:
    - 'x'
    - 'y'
    - 'a'
    - 'b'
    - 'x1'
    - 'x2'
    - 'y1'
    - 'y2'
included:
    - Dozer


================================================
FILE: Brewfile
================================================
brew "swiftformat"
brew "swiftgen"
brew "swiftlint"
brew "xcodegen"
brew "carthage"


================================================
FILE: Brewfile.lock.json
================================================
{
  "entries": {
    "brew": {
      "swiftformat": {
        "version": "0.44.16",
        "bottle": {
          "cellar": ":any_skip_relocation",
          "prefix": "/usr/local",
          "files": {
            "catalina": {
              "url": "https://homebrew.bintray.com/bottles/swiftformat-0.44.16.catalina.bottle.tar.gz",
              "sha256": "e03e40dbe228ee7136cc2dd57079b589a6c531f4f2a52fce8a0ad7aaa2e2a935"
            },
            "mojave": {
              "url": "https://homebrew.bintray.com/bottles/swiftformat-0.44.16.mojave.bottle.tar.gz",
              "sha256": "9b866de2516e8f68b1ad764f996f38cba31b2d2fc345ba683bdd1867e6a44091"
            },
            "high_sierra": {
              "url": "https://homebrew.bintray.com/bottles/swiftformat-0.44.16.high_sierra.bottle.tar.gz",
              "sha256": "eb111096afada9821c4cf1489706b5daf599670d8651719955998f763c6b9cdb"
            }
          }
        }
      },
      "swiftgen": {
        "version": "6.2.1",
        "bottle": {
          "cellar": ":any",
          "prefix": "/usr/local",
          "files": {
            "catalina": {
              "url": "https://homebrew.bintray.com/bottles/swiftgen-6.2.1.catalina.bottle.tar.gz",
              "sha256": "0fde7ff65be044c1685ab5aa84514e45c594cbc8bad028b5ac8f2f6218cfd626"
            }
          }
        }
      },
      "swiftlint": {
        "version": "0.39.2",
        "bottle": {
          "cellar": ":any_skip_relocation",
          "prefix": "/usr/local",
          "files": {
            "catalina": {
              "url": "https://homebrew.bintray.com/bottles/swiftlint-0.39.2.catalina.bottle.tar.gz",
              "sha256": "32f9e5e37190e81856eff49c2118c04d1995110b509f0a4997e211c9f939919e"
            },
            "mojave": {
              "url": "https://homebrew.bintray.com/bottles/swiftlint-0.39.2.mojave.bottle.tar.gz",
              "sha256": "c4fc10277d46c406277491003e5d5bbdfe526890c39b30eb924749696ed56d40"
            }
          }
        }
      },
      "xcodegen": {
        "version": "2.16.0",
        "bottle": {
          "cellar": ":any_skip_relocation",
          "prefix": "/usr/local",
          "files": {
            "catalina": {
              "url": "https://homebrew.bintray.com/bottles/xcodegen-2.16.0.catalina.bottle.tar.gz",
              "sha256": "fc8f03f0f3968c6f913725629bdfa34a24a539a6868afdb1112b8f76cdbf5a55"
            },
            "mojave": {
              "url": "https://homebrew.bintray.com/bottles/xcodegen-2.16.0.mojave.bottle.tar.gz",
              "sha256": "a8eea29cb064ef817a1aae173b102eb689a263fc4039987a4592e9f15c4b1d85"
            }
          }
        }
      },
      "carthage": {
        "version": "0.35.0",
        "bottle": {
          "cellar": ":any_skip_relocation",
          "prefix": "/usr/local",
          "files": {
            "catalina": {
              "url": "https://homebrew.bintray.com/bottles/carthage-0.35.0.catalina.bottle.tar.gz",
              "sha256": "fdaacafff1566fa7b1e42e68e108da69aa7578dc82f4736272dca10283c9cba2"
            },
            "mojave": {
              "url": "https://homebrew.bintray.com/bottles/carthage-0.35.0.mojave.bottle.tar.gz",
              "sha256": "1da29ca0b1d8e79bec5e548f5ab2433890ebc3fc9007f5fdb70d9e3be281dbb7"
            },
            "high_sierra": {
              "url": "https://homebrew.bintray.com/bottles/carthage-0.35.0.high_sierra.bottle.tar.gz",
              "sha256": "130fcb9bc06ef8e7f1c5ac9af0d155bd347db039b2cf80fa0fef764b3627ffbf"
            }
          }
        }
      }
    }
  },
  "system": {
    "macos": {
      "catalina": {
        "HOMEBREW_VERSION": "2.4.4-57-g6d2c395",
        "HOMEBREW_PREFIX": "/usr/local",
        "Homebrew/homebrew-core": "a4ba652e5d0b5380df4f2edecc2f4d15cd15fc48",
        "CLT": "1103.0.32.29",
        "Xcode": "11.5",
        "macOS": "10.15.5"
      }
    }
  }
}


================================================
FILE: CHANGELOG.md
================================================
# Changelog

## Version 4.2.0
New features:
* Configure amount of seconds to hide the icons after #104. @blakedgordon
* Resize icons and padding capability added #101. @blakedgordon

Fixed:
* Fix both dozer icons from being hidden #105. @blakedgordon

Thank you @blakedgordon for the contributions🙌

## Version 4.1.0
New features:
* Hide status bar icons at launch #78. @aonez

Fixed:
* Reduce CPU usage when "Hide status bar icons after 10 seconds" is checked #78. @aonez

Thank you @aonez for the contributions🙌

## Version 4
New features:
* ”Remove”-icon. Additional icon to hide/show icons with `option+click`
* Auto-hide status bar icons #22
* ”No Icon”-mode. Hide/show only using keyboard shortcut

Other:
* Improved UI in preferences


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to Dozer

There are various ways to contribute to Dozer, and all are welcome and appreciated!

- [Bug reports](#bug-reports)
- [Feature requests](#feature-requests)
- [Design](#design)
- [Code](#code)
    - [Getting started](#getting-started)
    - [Submitting your pull request](#submitting-your-pull-request)

## Bug reports
Open issues about problems you may be encountering. When doing so please mention the version you're using.

## Feature requests
If you have a good idea for a feature or enhancement open an issue.

## Design
Refresh the Dozer icons or logo. [Design resources for logo and status bar icon](https://www.figma.com/file/g5MhiwxR1YFg5vti0tPANa/Dozer).

## Code
You can submit your own code. This can be bug fixes or new features. Please ask me (@Mortennn) before implementing a new feature. Check out [Issues](https://github.com/Mortennn/Dozer/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).

### Getting started
Make sure you have at least Xcode 10 installed.

Run the following command:
```shell
git clone https://github.com/mortennn/dozer &&
cd dozer &&
make build
```
Done! The project should open automatically in Xcode.

### Submitting your pull request
Please give a small summary of what has changed. Also add any github issues links (`Fixes #100`).
Once your pull request is created, please add a changelog entry to the CHANGELOG.md along with the PR number.

================================================
FILE: Cartfile
================================================
github "sindresorhus/LaunchAtLogin"
github "sindresorhus/Defaults"
github "sindresorhus/Preferences"
github "shpakovski/MASShortcut"
github "sparkle-project/Sparkle"

================================================
FILE: Cartfile.resolved
================================================
github "shpakovski/MASShortcut" "2.4.0"
github "sindresorhus/Defaults" "v4.2.2"
github "sindresorhus/LaunchAtLogin" "v4.1.0"
github "sindresorhus/Preferences" "v2.2.1"
github "sparkle-project/Sparkle" "1.26.0"


================================================
FILE: Configs/Debug.xcconfig
================================================
SWIFT_COMPILATION_MODE=Incremental
SWIFT_OPTIMIZATION_LEVEL=-Onone
DEBUG_INFORMATION_FORMAT=dwarf
ENABLE_TESTABILITY=YES


================================================
FILE: Configs/Release.xcconfig
================================================
SWIFT_COMPILATION_MODE=wholemodule
SWIFT_OPTIMIZATION_LEVEL=-O


================================================
FILE: Dozer/AppDelegate.swift
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

import Cocoa
import MASShortcut
import Sparkle
import Defaults
import Preferences


final class AppDelegate: NSObject, NSApplicationDelegate {
    func applicationDidFinishLaunching(_: Notification) {
        MASShortcutBinder.shared()?.bindShortcut(withDefaultsKey: UserDefaultKeys.Shortcuts.ToggleMenuItems) { () in
            DozerIcons.shared.toggle()
        }

        // Initalize Dozer Icons
        _ = DozerIcons.shared
        
        // If enabled hide menu bar icons at launch
        DozerIcons.shared.hideAtLaunch()

        _ = DozerIcons.toggleDockIcon(showIcon: false)
    }

    // Show all Dozer icons when opening Dozer from Finder etc.
    func applicationOpenUntitledFile(_ sender: NSApplication) -> Bool {
        DozerIcons.shared.showAll()
        return true
    }

    lazy var preferences: [PreferencePane] = [
        Dozer(),
        General()
    ]

    lazy var preferencesWindowController = PreferencesWindowController(
        preferencePanes: preferences,
        style: .toolbarItems,
        animated: true,
        hidesToolbarForSingleItem: true
    )
}


================================================
FILE: Dozer/Constants.swift
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

import Cocoa
import Preferences
import Defaults

extension Defaults.Keys {
    static let hideOnLogin: Defaults.Key<Bool> = Key<Bool>("hideOnLogin", default: false)
    static let hideAtLaunchEnabled: Defaults.Key<Bool> = Key<Bool>("hideAtLaunchEnabled", default: false)
    static let hideAfterDelayEnabled: Defaults.Key<Bool> = Key<Bool>("hideAfterDelayEnabled", default: false)
    static let hideAfterDelay: Defaults.Key<TimeInterval> = Key<TimeInterval>("hideAfterDelay", default: 10)
    static let noIconMode: Defaults.Key<Bool> = Key<Bool>("noIconMode", default: false)
    static let removeDozerIconEnabled: Defaults.Key<Bool> = Key<Bool>("removeStatusIconEnabled", default: false)
    static let showIconAndMenuEnabled: Defaults.Key<Bool> = Key<Bool>("showIconAndMenuEnabled", default: false)
    static let iconSize: Defaults.Key<Int> = Key<Int>("fontSize", default: 10)
    static let buttonPadding: Defaults.Key<CGFloat> = Key<CGFloat>("buttonPadding", default: 25)
    static let animationEnabled: Defaults.Key<Bool> = Key<Bool>("animationEnabeld", default: false)
    static let isShortcutSet: Defaults.Key<Bool> = Key<Bool>("isShortcutSet", default: false)
}

struct UserDefaultKeys {
    struct Shortcuts {
        static let ToggleMenuItems: String = "toggleMenuItems"
    }
}

extension NSStoryboard.Name {
    static let preferences: NSStoryboard.Name = NSStoryboard.Name("Preferences")
}

extension Preferences.PaneIdentifier {
    static let dozer = Self("dozer")
    static let general = Self("general")
}

struct AppInfo {
    static let bundleIdentifier: String = Bundle.main.bundleIdentifier!
    static var releaseVersionNumber: String? {
        Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
    }
    static var buildVersionNumber: String? {
        Bundle.main.infoDictionary?["CFBundleVersion"] as? String
    }
}

enum StatusIconAction {
    case show
    case hide
    case toggle
}

enum StatusIconType {
    case normal
    case remove
}

enum DozerIcon {
    case remove
    case normalLeft
    case normalRight
}


================================================
FILE: Dozer/DozerIcons.swift
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

import Cocoa
import Defaults

public final class DozerIcons {
    static var shared = DozerIcons()
    private var dozerIcons: [HelperstatusIcon] = []
    private var timerToCheckUserInteraction = Timer()
    private var timerToHideDozerIcons = Timer()
    private var previousApp = NSRunningApplication()

    private init() {
        dozerIcons.append(NormalStatusIcon())

        if !hideBothDozerIcons  || !Defaults[.isShortcutSet] {
            dozerIcons.append(NormalStatusIcon())
        }

        if enableRemoveDozerIcon {
            dozerIcons.append(RemoveStatusIcon())
        }

        if hideStatusBarIconsAfterDelay {
            startTimer()
        }

        Defaults.observe(.isShortcutSet) { change in
            self.triggerHideBothDozerIcons()
        }
        .tieToLifetime(of: self)
    }

    private func startUserInteractionTimer() {
        guard Defaults[.hideAfterDelayEnabled] else {
            stopUserInteractionTimer()
            return
        }
        timerToCheckUserInteraction = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { _ in
            if self.isUserInteractingWithStatusBar() {
                self.resetTimer()
            }
        }
    }

    private func stopUserInteractionTimer() {
        timerToCheckUserInteraction.invalidate()
    }

    // MARK: Observe changes to settings
    public var hideStatusBarIconsAtLaunch: Bool = Defaults[.hideAtLaunchEnabled] {
        didSet {
            Defaults[.hideAtLaunchEnabled] = self.hideStatusBarIconsAtLaunch
        }
    }

    public var hideStatusBarIconsAfterDelay: Bool = Defaults[.hideAfterDelayEnabled] {
        didSet {
            Defaults[.hideAfterDelayEnabled] = self.hideStatusBarIconsAfterDelay
            if hideStatusBarIconsAfterDelay {
                startTimer()
            } else {
                stopTimer()
            }
        }
    }

    public var hideBothDozerIcons: Bool = Defaults[.noIconMode] {
        didSet {
            Defaults[.noIconMode] = self.hideBothDozerIcons
            triggerHideBothDozerIcons()
        }
    }

    public func triggerHideBothDozerIcons() {
        let normalStatusIconsCount = dozerIcons.filter { $0.type == .normal}.count
        if hideBothDozerIcons && Defaults[.isShortcutSet] {
            if normalStatusIconsCount == 2 {
                let rightDozerIconXPos = get(dozerIcon: .normalRight).xPositionOnScreen
                dozerIcons.removeAll { $0.xPositionOnScreen == rightDozerIconXPos }
            }
        } else if !hideBothDozerIcons && Defaults[.isShortcutSet] || !Defaults[.isShortcutSet] {
            if normalStatusIconsCount == 1 {
                show()
                dozerIcons.append(NormalStatusIcon())
            }
        }
        show()
    }

    public var enableRemoveDozerIcon: Bool = Defaults[.removeDozerIconEnabled] {
        didSet {
            Defaults[.removeDozerIconEnabled] = self.enableRemoveDozerIcon
            if enableRemoveDozerIcon {
                dozerIcons.append(RemoveStatusIcon())
            } else {
                dozerIcons.removeAll { $0.type == .remove }
            }
            showAll()
        }
    }

    public var enableIconAndMenu: Bool = Defaults[.showIconAndMenuEnabled] {
        didSet {
            Defaults[.showIconAndMenuEnabled] = self.enableIconAndMenu
            if self.enableIconAndMenu == false {
                _ = DozerIcons.toggleDockIcon(showIcon: false)
                appDelegate.preferencesWindowController.show(preferencePane: .general)
            }
        }
    }

    public var iconFontSize: Int = Defaults[.iconSize] {
        didSet {
            Defaults[.iconSize] = self.iconFontSize
            for icon in dozerIcons {
                icon.setSize()
            }
        }
    }

    public var buttonPadding: CGFloat = Defaults[.buttonPadding] {
        didSet {
            Defaults[.buttonPadding] = self.buttonPadding
            for icon in dozerIcons {
                icon.setSize()
            }
        }
    }

    // MARK: Public methods
    public func hide() {
        perform(action: .hide, statusIcon: .remove)
        perform(action: .hide, statusIcon: .normalLeft)
        if Defaults[.noIconMode] && Defaults[.isShortcutSet] {
            perform(action: .hide, statusIcon: .normalRight)
        }
        didHideStatusBarIcons()
        hideIconAndMenu()
    }

    public func hideAtLaunch() {
        if hideStatusBarIconsAtLaunch {
            if #available(macOS 11.0, *) {
                Timer.scheduledTimer(withTimeInterval: 0.15, repeats: false) { _ in
                   self.hide()
                }
            } else {
                self.hide()
            }
        }
    }

    public func show() {
        resetTimer()
        perform(action: .hide, statusIcon: .remove)
        perform(action: .show, statusIcon: .normalLeft)
        if Defaults[.noIconMode] {
            perform(action: .show, statusIcon: .normalRight)
        }
        didShowStatusBarIcons()
        showIconAndMenu()
    }

    public func toggle() {
        if get(dozerIcon: .normalLeft).isShown {
            hide()
        } else {
            show()
        }
    }

    public func toggleRemove() {
        if get(dozerIcon: .remove).isShown {
            perform(action: .hide, statusIcon: .remove)
        } else {
            perform(action: .show, statusIcon: .remove)
        }
    }

    public func showIconAndMenu() {
        if NSWorkspace.shared.frontmostApplication?.bundleIdentifier != AppInfo.bundleIdentifier {
            previousApp = NSWorkspace.shared.frontmostApplication!
        }
        if Defaults[.showIconAndMenuEnabled] {
            _ = DozerIcons.toggleDockIcon(showIcon: true)
            NSApp.activate(ignoringOtherApps: true)
        }
    }

    public func hideIconAndMenu() {
        if Defaults[.showIconAndMenuEnabled] {
            _ = DozerIcons.toggleDockIcon(showIcon: false)
            if NSWorkspace.shared.frontmostApplication?.bundleIdentifier == AppInfo.bundleIdentifier {
                previousApp.activate()
            }
        }
    }

    /// Force show all Dozer icons
    public func showAll() {
        perform(action: .show, statusIcon: .remove)
        perform(action: .show, statusIcon: .normalLeft)
        perform(action: .show, statusIcon: .normalRight)
        didShowStatusBarIcons()
    }

    public func handleOptionClick() {
        showIconAndMenu()
        if get(dozerIcon: .normalLeft).isShown {
            DozerIcons.shared.perform(
                action: .toggle,
                statusIcon: .remove
            )
        } else {
            DozerIcons.shared.perform(
                action: .show,
                statusIcon: .normalLeft
            )
            DozerIcons.shared.perform(
                action: .show,
                statusIcon: .remove
            )
        }
        stopUserInteractionTimer()
        startUserInteractionTimer()
        resetTimer()
    }

    // MARK: Show/hide lifecycle
    private func didShowStatusBarIcons() {
        //startTimer()
        startUserInteractionTimer()
    }

    private func didHideStatusBarIcons() {
        stopTimer()
        stopUserInteractionTimer()
    }

    private func willHideStatusBarIcons() {
        guard Defaults[.hideAfterDelayEnabled] else {
            return
        }

        // don't hide on user interaction with menu bar
        guard !isUserInteractingWithStatusBar() else {
            resetTimer()
            return
        }

        DozerIcons.shared.hide()
    }

    // MARK: timerToHideDozerIcons methods
    private func startTimer() {
        guard Defaults[.hideAfterDelayEnabled] else {
            stopTimer()
            return
        }
        timerToHideDozerIcons = Timer.scheduledTimer(withTimeInterval: Defaults[.hideAfterDelay], repeats: false) { (_: Timer) -> Void in
            self.willHideStatusBarIcons()
        }
    }

    private func stopTimer() {
        timerToHideDozerIcons.invalidate()
    }

    func resetTimer() {
        self.stopTimer()
        self.startTimer()
    }

    // MARK: Private methods
    /// Will fail silently if statusIcon does not exist
    private func perform(action: StatusIconAction, statusIcon: DozerIcon) {
        if statusIcon == .remove {
            guard Defaults[.removeDozerIconEnabled] else {
                return
            }
        }
        let theStatusIcon: HelperstatusIcon = get(dozerIcon: statusIcon)
        switch action {
        case .show:
            theStatusIcon.show()
        case .hide:
            theStatusIcon.hide()
        case .toggle:
            theStatusIcon.toggle()
        }
    }

    /// Will crash if trying to get ´DozerIcon´ which does not exist in the menu bar
    private func get(dozerIcon: DozerIcon) -> HelperstatusIcon {
        var normalStatusIconsXPosition: [CGFloat] = []
        for statusIcon in dozerIcons where statusIcon.type == .normal {
            normalStatusIconsXPosition.append(statusIcon.xPositionOnScreen)
        }
        switch dozerIcon {
        case .remove:
            guard let removeStatusIcon = dozerIcons.first(where: { $0.type == .remove }) else {
                fatalError("Failed getting remove status icon")
            }
            return removeStatusIcon
        case .normalLeft:
            guard let leftStatusIcon = dozerIcons.first(where: { $0.xPositionOnScreen == normalStatusIconsXPosition.min() }) else {
                fatalError("Failed getting status icon on the left")
            }
            return leftStatusIcon
        case .normalRight:
            guard let rightStatusIcon = dozerIcons.first(where: { $0.xPositionOnScreen == normalStatusIconsXPosition.max() }) else {
                fatalError("Failed getting status icon on the right")
            }
            return rightStatusIcon
        }
    }

    /// hide and show dock icon and thus its menu bar: to free up space to show more menu bar icons
    public class func toggleDockIcon(showIcon state: Bool) -> Bool {
        if state {
            return NSApp.setActivationPolicy(NSApplication.ActivationPolicy.regular)
        } else {
            return NSApp.setActivationPolicy(NSApplication.ActivationPolicy.accessory)
        }
    }

    /// Determines if the user is interacting with the menu bar based on level, owner and y-coordinate
    ///
    /// - Returns: Returns whether the user is interacting with the menu bar or not
    private func isUserInteractingWithStatusBar() -> Bool {
        let windowListType = CGWindowListOption.optionOnScreenOnly
        guard let windowInfoList = CGWindowListCopyWindowInfo(windowListType, kCGNullWindowID) as NSArray? as? [[String: AnyObject]] else {
            return false
        }
        var statusBarAppsWindowInfo: [Window] = []

        for windowInfo in windowInfoList {
            guard let window = Window(windowInfo),
                // If the preferences window are close to the menu bar it won't auto hide
                window.owner != "Dozer" else {
                    continue
            }

            if window.isStatusIcon {
                statusBarAppsWindowInfo.append(window)
            }
        }

        for windowInfo in windowInfoList {
            guard let window = Window(windowInfo) else { continue }
            guard window.isStatusIcon == false else { continue }

            for statusBarApp in statusBarAppsWindowInfo {
                guard statusBarApp.owner == window.owner else { continue }
                guard (statusBarApp.y + 22...statusBarApp.y + 30).contains(window.y) else { continue }

                return true
            }
        }

        return false
    }

    /// Wrapper class for CGWindowList
    private class Window {
        var x: Int = 0
        var y: Int = 0
        var width: Int = 0
        var height: Int = 0

        var level: Int
        var owner: String

        init?(_ windowInfo: [String: AnyObject]) {
            guard let level = windowInfo[kCGWindowLayer as String] as? Int else {
                return nil
            }
            guard let owner = windowInfo[kCGWindowOwnerName as String] as? String else {
                return nil
            }

            self.level = level
            self.owner = owner

            let bounds: [String: Int] = windowInfo[kCGWindowBounds as String] as! [String: Int]
            for item in bounds {
                switch item.key {
                case "X":
                    x = item.value
                case "Y":
                    y = item.value
                case "Width":
                    width = item.value
                case "Height":
                    height = item.value
                default:
                    continue
                }
            }
        }

        var isStatusIcon: Bool {
            guard level == 25 && height == 22 else {
                return false
            }
            return true
        }
    }
}


================================================
FILE: Dozer/Other/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
  "images" : [
    {
      "size" : "16x16",
      "idiom" : "mac",
      "filename" : "Icon_16x16.png",
      "scale" : "1x"
    },
    {
      "size" : "16x16",
      "idiom" : "mac",
      "filename" : "Icon_16x16@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "32x32",
      "idiom" : "mac",
      "filename" : "Icon_32x32.png",
      "scale" : "1x"
    },
    {
      "size" : "32x32",
      "idiom" : "mac",
      "filename" : "Icon_32x32@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "128x128",
      "idiom" : "mac",
      "filename" : "Icon_128x128.png",
      "scale" : "1x"
    },
    {
      "size" : "128x128",
      "idiom" : "mac",
      "filename" : "Icon_128x128@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "256x256",
      "idiom" : "mac",
      "filename" : "Icon_256x256.png",
      "scale" : "1x"
    },
    {
      "size" : "256x256",
      "idiom" : "mac",
      "filename" : "Icon_256x256@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "512x512",
      "idiom" : "mac",
      "filename" : "Icon_512x512.png",
      "scale" : "1x"
    },
    {
      "size" : "512x512",
      "idiom" : "mac",
      "filename" : "Icon_512x512@2x.png",
      "scale" : "2x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: Dozer/Other/Assets.xcassets/Contents.json
================================================
{
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: Dozer/Other/Assets.xcassets/HelperStatusItemIcon.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "mac",
      "filename" : "icons8-filled-circle-24.png",
      "scale" : "1x"
    },
    {
      "idiom" : "mac",
      "scale" : "2x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  },
  "properties" : {
    "template-rendering-intent" : "original"
  }
}

================================================
FILE: Dozer/Other/Dozer.entitlements
================================================
<?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/>
</plist>


================================================
FILE: Dozer/Other/Info.plist
================================================
<?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>AppIcon.icns</string>
	<key>CFBundleIdentifier</key>
	<string>com.mortennn.Dozer</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>Dozer</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>4.2.0</string>
	<key>CFBundleVersion</key>
	<string>30</string>
	<key>LSApplicationCategoryType</key>
	<string>public.app-category.utilities</string>
	<key>LSMinimumSystemVersion</key>
	<string>10.13</string>
	<key>LSUIElement</key>
	<true/>
	<key>NSHumanReadableCopyright</key>
	<string>Copyright © 2020 Mortennn@GitHub. All rights reserved.</string>
	<key>NSPrincipalClass</key>
	<string>NSApplication</string>
	<key>SUFeedURL</key>
	<string>https://raw.githubusercontent.com/Mortennn/Dozer/master/appcast.xml</string>
	<key>SUPublicEDKey</key>
	<string>97gvwr+B10rf6Exnj8yPuAXrYSu9yKikViJkYkvPMHY=</string>
</dict>
</plist>


================================================
FILE: Dozer/Other/bridging-header.h
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

#ifndef bridging_header_h
#define bridging_header_h

#import <Cocoa/Cocoa.h>
#import <MASShortcut/Shortcut.h>

#endif


================================================
FILE: Dozer/Other/main.swift
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

import AppKit
let app = NSApplication.shared
let appDelegate = AppDelegate()
app.delegate = appDelegate
_ = NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv)


================================================
FILE: Dozer/StatusIconClasses/HelperStatusIcon.swift
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

import Cocoa
import Defaults

private struct StatusIconLength {
    static var show: CGFloat {
        Defaults[.buttonPadding]
    }
    static let hide: CGFloat = 10_000
}

class HelperstatusIcon {
    var type: StatusIconType

    let statusIcon: NSStatusItem = NSStatusBar.system.statusItem(withLength: StatusIconLength.show)

    init() {
        type = .normal
        statusIcon.length = StatusIconLength.show
        statusIcon.highlightMode = false

        guard let statusIconButton = statusIcon.button else {
            fatalError("helper status item button failed")
        }

        statusIconButton.target = self
        statusIconButton.action = #selector(statusIconClicked(_:))
        setIcon()
        statusIconButton.sendAction(on: [.leftMouseDown, .rightMouseDown])
    }

    deinit {
        print("status item has been deallocated")
    }

    func show() {
        statusIcon.length = StatusIconLength.show
    }

    func hide() {
        statusIcon.length = StatusIconLength.hide
    }

    func toggle() {
        if isShown {
            hide()
        } else {
            show()
        }
    }

    func setIcon() {
        guard let statusIconButton = statusIcon.button else {
            fatalError("helper status item button failed")
        }
        statusIconButton.image = Icons().helperstatusIcon
        statusIconButton.image!.isTemplate = true
    }

    func setSize() {
        if statusIcon.length != StatusIconLength.hide {
            statusIcon.length = StatusIconLength.show
        }
        guard let statusIconButton = statusIcon.button else {
            fatalError("helper status item button failed")
        }
        let image = statusIconButton.image
        var size = DozerIcons.shared.iconFontSize
        if self.type == .remove {
            size /= 2
        }
        image?.size = NSSize(width: size, height: size)
        statusIconButton.image = image
    }

    func showRemoveIcons() {}

    @objc
    func statusIconClicked(_ sender: AnyObject?) {}

    var isShown: Bool {
        statusIcon.length == StatusIconLength.show
    }

    var isHidden: Bool {
        statusIcon.length == StatusIconLength.hide
    }

    var xPositionOnScreen: CGFloat {
        guard let dozerIconFrame = statusIcon.button?.window?.frame else {
            return 0
        }
        let dozerIconXPosition = dozerIconFrame.origin.x
        return dozerIconXPosition
    }
}


================================================
FILE: Dozer/StatusIconClasses/NormalStatusIcon.swift
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

import Cocoa
import Defaults

class NormalStatusIcon: HelperstatusIcon {
    override init() {
        super.init()
        type = .normal
    }

    override func statusIconClicked(_: AnyObject?) {
        guard let currentEvent = NSApp.currentEvent else {
            return
        }

        if currentEvent.modifierFlags.contains(.option) &&
            !currentEvent.modifierFlags.contains(.control) &&
            !currentEvent.modifierFlags.contains(.command) {
            DozerIcons.shared.handleOptionClick()

            return
        }

        switch currentEvent.type {
        case .leftMouseDown:
            DozerIcons.shared.toggle()
        case .rightMouseDown:
            appDelegate.preferencesWindowController.show(preferencePane: .general)
        default:
            break
        }
    }
}


================================================
FILE: Dozer/StatusIconClasses/RemoveStatusIcon.swift
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

import Cocoa
import Defaults

class RemoveStatusIcon: HelperstatusIcon {
    override init() {
        super.init()
        type = .remove
    }

    override func statusIconClicked(_: AnyObject?) {
        guard let currentEvent = NSApp.currentEvent else {
            return
        }

        switch currentEvent.type {
        case .leftMouseDown:
            DozerIcons.shared.toggleRemove()
        case .rightMouseDown:
            appDelegate.preferencesWindowController.show(preferencePane: .general)
        default:
            break
        }
    }

    override func setIcon() {
        guard let statusIconButton = statusIcon.button else {
            fatalError("helper status item button failed")
        }
        statusIconButton.image = Icons().removeStatusIcon
        statusIconButton.image!.isTemplate = true
    }
}


================================================
FILE: Dozer/Util.swift
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

import Cocoa
import Defaults

extension NSButton {
    var isChecked: Bool {
        get {
            state == .on
        }
        set {
            state = newValue ? .on : .off
        }
    }
}

struct Icons {
    var helperstatusIcon: NSImage {
        let size = Defaults[.iconSize]
        return create(image: Assets.helperStatusItemIcon.name, size, size)
    }

    var removeStatusIcon: NSImage {
        let size = Defaults[.iconSize] / 2
        return create(image: Assets.helperStatusItemIcon.name, size, size)
    }

    private func create(image name: String, _ width: Int, _ height: Int) -> NSImage {
        guard let image = Bundle.main.image(forResource: NSImage.Name(name)) else {
            fatalError("get image failed")
        }
        image.size = NSSize(width: width, height: height)
        return image
    }
}


================================================
FILE: Dozer/ViewControllers/DozerVC.swift
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

import Cocoa
import Sparkle
import Preferences

final class Dozer: NSViewController, PreferencePane {
    let preferencePaneIdentifier = Preferences.PaneIdentifier.dozer
    let preferencePaneTitle: String = "Dozer"
    let toolbarItemIcon = NSImage(named: "AppIcon")!

    override var nibName: NSNib.Name? { "Dozer" }

    @IBOutlet private var versionLabel: NSTextField!
    @IBOutlet private var checkForUpdates: NSButton!
    @IBOutlet private var quit: NSButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        if let releaseVersionNumber = AppInfo.releaseVersionNumber,
            let buildVersionNumber = AppInfo.buildVersionNumber {
            versionLabel.stringValue = "\(releaseVersionNumber) (\(buildVersionNumber))"
        }

        checkForUpdates.target = SUUpdater.shared()!
        checkForUpdates.action = #selector(SUUpdater.shared()!.checkForUpdates(_:))

        quit.action = #selector(NSApp.terminate(_:))
    }
}


================================================
FILE: Dozer/ViewControllers/GeneralVC.swift
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

import Cocoa
import Preferences
import MASShortcut
import LaunchAtLogin
import Sparkle
import Defaults

final class General: NSViewController, PreferencePane {
    let preferencePaneIdentifier = Preferences.PaneIdentifier.general
    let preferencePaneTitle: String = "General"
    let toolbarItemIcon = NSImage(named: NSImage.preferencesGeneralName)!

    override var nibName: NSNib.Name? { "General" }

    fileprivate var userShortCut: MASShortcut!

    @IBOutlet private var LaunchAtLoginCheckbox: NSButton!
    @IBOutlet private var CheckForUpdatesCheckbox: NSButton!
    @IBOutlet private var HideStatusBarIconsAtLaunchCheckbox: NSButton!
    @IBOutlet private var HideStatusBarIconsAfterDelayCheckbox: NSButton!
    @IBOutlet private var HideStatusBarIconsSecondsPopUpButton: NSPopUpButton!
    @IBOutlet private var HideBothDozerIconsCheckbox: NSButton!
    @IBOutlet private var EnableRemoveDozerIconCheckbox: NSButton!
    @IBOutlet private var ShowIconAndMenuCheckbox: NSButton!
    @IBOutlet private var FontSizePopUpButton: NSPopUpButton!
    @IBOutlet private var ButtonPaddingPopUpButton: NSPopUpButton!
    @IBOutlet private var ToggleMenuItemsView: MASShortcutView!

    override func viewDidLoad() {
        super.viewDidLoad()

        LaunchAtLoginCheckbox.focusRingType = .none

        LaunchAtLoginCheckbox.isChecked = LaunchAtLogin.isEnabled
        if SUUpdater.shared() != nil {
            CheckForUpdatesCheckbox.isChecked = SUUpdater.shared()!.automaticallyChecksForUpdates
        } else {
            CheckForUpdatesCheckbox.isChecked = false
        }

        HideStatusBarIconsAtLaunchCheckbox.isChecked = Defaults[.hideAtLaunchEnabled]
        HideStatusBarIconsAfterDelayCheckbox.isChecked = Defaults[.hideAfterDelayEnabled]
        HideBothDozerIconsCheckbox.isChecked = Defaults[.noIconMode]
        EnableRemoveDozerIconCheckbox.isChecked = Defaults[.removeDozerIconEnabled]
        ShowIconAndMenuCheckbox.isChecked = Defaults[.showIconAndMenuEnabled]
        HideStatusBarIconsSecondsPopUpButton.selectItem(withTitle: "\(Int(Defaults[.hideAfterDelay])) seconds")
        FontSizePopUpButton.selectItem(withTitle: "\(Int(Defaults[.iconSize])) px")
        ButtonPaddingPopUpButton.selectItem(withTitle: "\(Int(Defaults[.buttonPadding])) px")

        ToggleMenuItemsView.associatedUserDefaultsKey = UserDefaultKeys.Shortcuts.ToggleMenuItems
        view.addSubview(ToggleMenuItemsView)
        configureEnabledNoIconCheckbox()

        ToggleMenuItemsView.shortcutValueChange = { _ -> Void in
            self.userShortCut = self.ToggleMenuItemsView.shortcutValue
            self.configureEnabledNoIconCheckbox()
        }
    }

    @IBAction private func launchAtLoginClicked(_ sender: NSButton) {
        LaunchAtLogin.isEnabled = (sender.state == .on)
    }

    @IBAction private func automaticallyCheckForUpdatesClicked(_ sender: NSButton) {
        guard SUUpdater.shared() != nil else {
            CheckForUpdatesCheckbox.isChecked = false
            return
        }
        SUUpdater.shared()!.automaticallyChecksForUpdates = CheckForUpdatesCheckbox.isChecked
    }

    @IBAction private func hideStatusBarIconsAtLaunchClicked(_ sender: NSButton) {
        DozerIcons.shared.hideStatusBarIconsAtLaunch = HideStatusBarIconsAtLaunchCheckbox.isChecked
    }

    @IBAction private func hideStatusBarIconsAfterDelayClicked(_ sender: NSButton) {
        DozerIcons.shared.hideStatusBarIconsAfterDelay = HideStatusBarIconsAfterDelayCheckbox.isChecked
    }

    @IBAction private func hideStatusBarIconsSecondsUpdated(_ sender: NSPopUpButton) {
        Defaults[.hideAfterDelay] = TimeInterval(HideStatusBarIconsSecondsPopUpButton.selectedTag())
        DozerIcons.shared.resetTimer()
    }

    @IBAction private func hideBothDozerIconsClicked(_ sender: NSButton) {
        DozerIcons.shared.hideBothDozerIcons = HideBothDozerIconsCheckbox.isChecked
    }

    @IBAction private func showIconAndMenuClicked(_ sender: NSButton) {
        DozerIcons.shared.enableIconAndMenu = ShowIconAndMenuCheckbox.isChecked
    }

    @IBAction private func fontSizeChanged(_ sender: NSPopUpButton) {
        DozerIcons.shared.iconFontSize = FontSizePopUpButton.selectedTag()
    }

    @IBAction private func buttonPaddingChanged(_ sender: NSPopUpButton) {
        DozerIcons.shared.buttonPadding = CGFloat(ButtonPaddingPopUpButton.selectedTag())
    }

    @IBAction private func enableRemoveDozerIconClicked(_ sender: NSButton) {
        DozerIcons.shared.enableRemoveDozerIcon = EnableRemoveDozerIconCheckbox.isChecked
    }

    /// disables the noIcon-checkbox if no shortcut is set and keeps track whether shortcut is set
    private func configureEnabledNoIconCheckbox() {
        if ToggleMenuItemsView.shortcutValue == nil {
            HideBothDozerIconsCheckbox.isEnabled = false
            Defaults[.isShortcutSet] = false
        } else {
            HideBothDozerIconsCheckbox.isEnabled = true
            Defaults[.isShortcutSet] = true
        }
    }
}


================================================
FILE: Dozer/XIB/Dozer.xib
================================================
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="17701" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
    <dependencies>
        <deployment identifier="macosx"/>
        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17701"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <objects>
        <customObject id="-2" userLabel="File's Owner" customClass="Dozer" customModule="Dozer" customModuleProvider="target">
            <connections>
                <outlet property="checkForUpdates" destination="9vD-g9-QSn" id="vq3-pD-sN9"/>
                <outlet property="quit" destination="pje-Gc-VuB" id="bVZ-fZ-wIo"/>
                <outlet property="versionLabel" destination="55H-bw-r5z" id="aJg-O9-Hf5"/>
                <outlet property="view" destination="c22-O7-iKe" id="6nC-uH-0pZ"/>
            </connections>
        </customObject>
        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
        <customView id="c22-O7-iKe">
            <rect key="frame" x="0.0" y="0.0" width="182" height="127"/>
            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
            <subviews>
                <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="9vD-g9-QSn">
                    <rect key="frame" x="13" y="46" width="156" height="32"/>
                    <buttonCell key="cell" type="push" title="Check for updates" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="rlC-nV-9gL">
                        <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
                        <font key="font" metaFont="system"/>
                        <string key="keyEquivalent">u</string>
                        <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                    </buttonCell>
                </button>
                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="SpT-W4-9Jy">
                    <rect key="frame" x="18" y="83" width="60" height="24"/>
                    <textFieldCell key="cell" lineBreakMode="clipping" title="Dozer" id="aTf-T7-WMw">
                        <font key="font" metaFont="systemBold" size="20"/>
                        <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                    </textFieldCell>
                </textField>
                <textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="55H-bw-r5z">
                    <rect key="frame" x="82" y="85" width="82" height="16"/>
                    <textFieldCell key="cell" lineBreakMode="clipping" title="x.x.x (xxx)" id="D7X-My-KCz">
                        <font key="font" metaFont="systemLight" size="13"/>
                        <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                    </textFieldCell>
                </textField>
                <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="pje-Gc-VuB">
                    <rect key="frame" x="13" y="13" width="156" height="32"/>
                    <buttonCell key="cell" type="push" title="Quit" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="WWq-a5-SXU">
                        <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
                        <font key="font" metaFont="system"/>
                        <string key="keyEquivalent">q</string>
                        <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                    </buttonCell>
                </button>
            </subviews>
            <constraints>
                <constraint firstItem="55H-bw-r5z" firstAttribute="leading" secondItem="SpT-W4-9Jy" secondAttribute="trailing" constant="8" symbolic="YES" id="4sc-ch-AOc"/>
                <constraint firstAttribute="trailing" secondItem="9vD-g9-QSn" secondAttribute="trailing" constant="20" symbolic="YES" id="QAs-vQ-uHy"/>
                <constraint firstItem="SpT-W4-9Jy" firstAttribute="leading" secondItem="c22-O7-iKe" secondAttribute="leading" constant="20" symbolic="YES" id="RUa-mD-Fqp"/>
                <constraint firstItem="9vD-g9-QSn" firstAttribute="leading" secondItem="c22-O7-iKe" secondAttribute="leading" constant="20" symbolic="YES" id="Rjb-Gs-uK3"/>
                <constraint firstItem="SpT-W4-9Jy" firstAttribute="top" secondItem="c22-O7-iKe" secondAttribute="top" constant="20" symbolic="YES" id="Xmc-Nu-0b4"/>
                <constraint firstItem="55H-bw-r5z" firstAttribute="firstBaseline" secondItem="SpT-W4-9Jy" secondAttribute="firstBaseline" id="ZL7-wv-Jn7"/>
                <constraint firstAttribute="bottom" secondItem="pje-Gc-VuB" secondAttribute="bottom" constant="20" symbolic="YES" id="alI-LE-btA"/>
                <constraint firstAttribute="trailing" secondItem="55H-bw-r5z" secondAttribute="trailing" constant="20" symbolic="YES" id="baX-kt-VJH"/>
                <constraint firstItem="pje-Gc-VuB" firstAttribute="top" secondItem="9vD-g9-QSn" secondAttribute="bottom" constant="13" id="d5E-ht-mL4"/>
                <constraint firstAttribute="trailing" secondItem="pje-Gc-VuB" secondAttribute="trailing" constant="20" symbolic="YES" id="kob-LH-1Cr"/>
                <constraint firstItem="9vD-g9-QSn" firstAttribute="top" secondItem="SpT-W4-9Jy" secondAttribute="bottom" constant="10" id="rQi-Et-gGH"/>
                <constraint firstAttribute="width" relation="greaterThanOrEqual" constant="182" id="x8b-be-Sai"/>
                <constraint firstItem="pje-Gc-VuB" firstAttribute="leading" secondItem="c22-O7-iKe" secondAttribute="leading" constant="20" symbolic="YES" id="xug-sv-EmU"/>
            </constraints>
            <point key="canvasLocation" x="-10" y="81.5"/>
        </customView>
    </objects>
</document>


================================================
FILE: Dozer/XIB/General.xib
================================================
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
    <dependencies>
        <deployment identifier="macosx"/>
        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <objects>
        <customObject id="-2" userLabel="File's Owner" customClass="General" customModule="Dozer" customModuleProvider="target">
            <connections>
                <outlet property="ButtonPaddingPopUpButton" destination="D1W-S4-kqi" id="FHs-Gq-kJv"/>
                <outlet property="CheckForUpdatesCheckbox" destination="htn-2c-54s" id="sO5-Ft-amU"/>
                <outlet property="EnableRemoveDozerIconCheckbox" destination="pDX-1f-4hl" id="uHk-1U-HG9"/>
                <outlet property="FontSizePopUpButton" destination="Lku-wR-aPA" id="GZe-ld-Ip5"/>
                <outlet property="HideBothDozerIconsCheckbox" destination="w7z-Qa-kqw" id="L5J-6S-jtb"/>
                <outlet property="HideStatusBarIconsAfterDelayCheckbox" destination="hOy-nu-Sy0" id="aNv-vt-dQL"/>
                <outlet property="HideStatusBarIconsAtLaunchCheckbox" destination="phN-BY-WEC" id="zff-cm-aik"/>
                <outlet property="HideStatusBarIconsSecondsPopUpButton" destination="Ziw-so-qpj" id="iWr-jc-Wbb"/>
                <outlet property="LaunchAtLoginCheckbox" destination="29f-2D-VsY" id="X2Z-FE-7IA"/>
                <outlet property="ShowIconAndMenuCheckbox" destination="oAW-Yf-7fi" id="7ZW-82-aRZ"/>
                <outlet property="ToggleMenuItemsView" destination="4Dt-wS-aZ8" id="PAm-fa-zGy"/>
                <outlet property="view" destination="c22-O7-iKe" id="buC-Sz-vlD"/>
            </connections>
        </customObject>
        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
        <customView translatesAutoresizingMaskIntoConstraints="NO" id="c22-O7-iKe">
            <rect key="frame" x="0.0" y="0.0" width="405" height="415"/>
            <subviews>
                <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="29f-2D-VsY">
                    <rect key="frame" x="18" y="379" width="361" height="18"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <buttonCell key="cell" type="check" title="Launch at login" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="qB0-b5-ye2">
                        <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
                        <font key="font" metaFont="system"/>
                    </buttonCell>
                    <connections>
                        <action selector="launchAtLoginClicked:" target="-2" id="Ci8-n6-lms"/>
                    </connections>
                </button>
                <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="htn-2c-54s">
                    <rect key="frame" x="18" y="351" width="361" height="18"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <buttonCell key="cell" type="check" title="Automatically check for updates" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="3Mj-bx-k9f">
                        <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
                        <font key="font" metaFont="system"/>
                    </buttonCell>
                    <connections>
                        <action selector="automaticallyCheckForUpdatesClicked:" target="-2" id="TJa-HP-dNZ"/>
                    </connections>
                </button>
                <box verticalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="ayr-kp-VXW">
                    <rect key="frame" x="20" y="339" width="365" height="5"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                </box>
                <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="phN-BY-WEC">
                    <rect key="frame" x="18" y="313" width="357" height="18"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <buttonCell key="cell" type="check" title="Hide menu bar icons at launch" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="24v-K4-mhc">
                        <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
                        <font key="font" metaFont="system"/>
                    </buttonCell>
                    <connections>
                        <action selector="hideStatusBarIconsAtLaunchClicked:" target="-2" id="9pu-qd-GaG"/>
                    </connections>
                </button>
                <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hOy-nu-Sy0">
                    <rect key="frame" x="18" y="283" width="179" height="18"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <buttonCell key="cell" type="check" title="Hide menu bar icons after" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="hS1-gl-Pc1">
                        <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
                        <font key="font" metaFont="system"/>
                    </buttonCell>
                    <connections>
                        <action selector="hideStatusBarIconsAfterDelayClicked:" target="-2" id="XYy-w6-La0"/>
                    </connections>
                </button>
                <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ziw-so-qpj" userLabel="10 seconds">
                    <rect key="frame" x="197" y="279" width="114" height="25"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <popUpButtonCell key="cell" type="push" title="10 seconds" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="10" imageScaling="proportionallyDown" inset="2" selectedItem="OdJ-mZ-u0T" id="JbX-Xw-iVE" userLabel="10 seconds">
                        <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
                        <font key="font" metaFont="menu"/>
                        <menu key="menu" id="fJp-Cl-42M">
                            <items>
                                <menuItem title="30 seconds" tag="30" id="dAj-2T-ECp"/>
                                <menuItem title="20 seconds" tag="20" id="tfP-VF-MG8"/>
                                <menuItem title="15 seconds" tag="15" id="EK8-vh-0H9"/>
                                <menuItem title="10 seconds" state="on" tag="10" id="OdJ-mZ-u0T"/>
                                <menuItem title="5 seconds" tag="5" id="Uqk-BC-hfK"/>
                                <menuItem title="3 seconds" tag="3" id="ven-uH-a0W"/>
                            </items>
                        </menu>
                    </popUpButtonCell>
                    <connections>
                        <action selector="hideStatusBarIconsSecondsUpdated:" target="-2" id="07d-zi-l5c"/>
                    </connections>
                </popUpButton>
                <textField horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="CNz-dE-9vs">
                    <rect key="frame" x="36" y="267" width="349" height="13"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <textFieldCell key="cell" sendsActionOnEndEditing="YES" title="The delay resets when you interact with the menu bar." id="QoH-wj-4Bo">
                        <font key="font" metaFont="system" size="10"/>
                        <color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                    </textFieldCell>
                </textField>
                <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="w7z-Qa-kqw">
	            <rect key="frame" x="18" y="240" width="357" height="18"/>
	            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
	            <buttonCell key="cell" type="check" title="Hide both Dozer icons when menu bar icons are hidden" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="PrK-hp-6i2">
		            <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
	            </buttonCell>
	            <connections>
		            <action selector="hideBothDozerIconsClicked:" target="-2" id="PdP-dQ-ir6"/>
	            </connections>
                </button>
                <textField horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Yjj-cw-XAs">
                    <rect key="frame" x="36" y="224" width="349" height="13"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Use the shortcut to show the menu bar icons." id="vbw-Q7-ecG">
                        <font key="font" metaFont="system" size="10"/>
                        <color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                    </textFieldCell>
                </textField>
                <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="pDX-1f-4hl">
                    <rect key="frame" x="18" y="197" width="361" height="18"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <buttonCell key="cell" type="check" title="Enable 'remove' Dozer icon" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="Toa-to-mCu">
                        <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
                        <font key="font" metaFont="system"/>
                    </buttonCell>
                    <connections>
                        <action selector="enableRemoveDozerIconClicked:" target="-2" id="vr8-Rh-V8P"/>
                    </connections>
                </button>
                <textField horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="IDw-Ag-Gcv">
                    <rect key="frame" x="36" y="168" width="349" height="26"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Enable additional Dozer icon. Show/hide less frequently used menu bar icons using option+click." id="UjO-Yp-XO4">
                        <font key="font" metaFont="system" size="10"/>
                        <color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                    </textFieldCell>
                </textField>
                <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="oAW-Yf-7fi">
                    <rect key="frame" x="18" y="140" width="352" height="18"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <buttonCell key="cell" type="check" title="Use full width of screen when showing menu bar icons" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="BFd-a4-rMo">
                        <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
                        <font key="font" metaFont="system"/>
                    </buttonCell>
                    <connections>
                        <action selector="showIconAndMenuClicked:" target="-2" id="iKs-IV-lOa"/>
                    </connections>
                </button>
                <textField horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="kyk-ok-xNW">
                    <rect key="frame" x="36" y="124" width="330" height="13"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Temporarily replaces Application menu and shows Dozer dock icon." id="ETO-zu-yhS">
                        <font key="font" metaFont="system" size="10"/>
                        <color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                    </textFieldCell>
                </textField>
                <box verticalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="6I6-gw-UlF">
                    <rect key="frame" x="20" y="113" width="365" height="5"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                </box>
                <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Lku-wR-aPA">
                    <rect key="frame" x="18" y="82" width="76" height="25"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <popUpButtonCell key="cell" type="push" title="10 px" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="10" imageScaling="proportionallyDown" inset="2" selectedItem="K1H-GX-dgi" id="dMj-ju-7Q7">
                        <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
                        <font key="font" metaFont="menu"/>
                        <menu key="menu" id="Ve7-Ni-pIE">
                            <items>
                                <menuItem title="10 px" state="on" tag="10" id="K1H-GX-dgi"/>
                                <menuItem title="9 px" tag="9" id="MjK-xE-xDS"/>
                                <menuItem title="8 px" tag="8" id="Tbm-iD-LcT"/>
                                <menuItem title="7 px" tag="7" id="As9-yv-ClQ"/>
                                <menuItem title="6 px" tag="6" id="QkM-lb-TEG"/>
                                <menuItem title="5 px" tag="5" id="eXo-xP-6N7"/>
                                <menuItem title="4 px" tag="4" id="LhP-q9-3yU"/>
                            </items>
                        </menu>
                    </popUpButtonCell>
                    <connections>
                        <action selector="fontSizeChanged:" target="-2" id="u5V-8g-GVu"/>
                    </connections>
                </popUpButton>
                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="TmQ-WL-Cmf">
                    <rect key="frame" x="95" y="88" width="150" height="16"/>
                    <autoresizingMask key="autoresizingMask"/>
                    <textFieldCell key="cell" lineBreakMode="clipping" title="Font size of Dozer icons" id="lI8-BD-YX6">
                        <font key="font" metaFont="system"/>
                        <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                    </textFieldCell>
                </textField>
                <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="D1W-S4-kqi">
                    <rect key="frame" x="18" y="52" width="76" height="25"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <popUpButtonCell key="cell" type="push" title="40 px" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="40" imageScaling="proportionallyDown" inset="2" selectedItem="nEF-ne-Uur" id="4qm-Fp-7BG">
                        <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
                        <font key="font" metaFont="menu"/>
                        <menu key="menu" id="PKu-6K-JrX">
                            <items>
                                <menuItem title="40 px" state="on" tag="40" id="nEF-ne-Uur"/>
                                <menuItem title="35 px" tag="35" id="MuZ-9R-GNV"/>
                                <menuItem title="30 px" tag="30" id="RRq-eq-zCw"/>
                                <menuItem title="25 px" tag="25" id="j6J-tT-q5c"/>
                                <menuItem title="20 px" tag="20" id="CSv-Pn-4v4"/>
                                <menuItem title="15 px" tag="15" id="SEt-aL-AMP"/>
                                <menuItem title="10 px" tag="10" id="xkS-gq-5Cm"/>
                            </items>
                        </menu>
                    </popUpButtonCell>
                    <connections>
                        <action selector="buttonPaddingChanged:" target="-2" id="Wk8-Qm-W0g"/>
                    </connections>
                </popUpButton>
                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tB7-K2-Gts">
                    <rect key="frame" x="95" y="58" width="131" height="16"/>
                    <autoresizingMask key="autoresizingMask"/>
                    <textFieldCell key="cell" lineBreakMode="clipping" title="Width of Dozer icons" id="y67-Ov-Fvx">
                        <font key="font" metaFont="system"/>
                        <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                    </textFieldCell>
                </textField>
                <box verticalHuggingPriority="750" fixedFrame="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="6Mb-v7-wV4">
                    <rect key="frame" x="20" y="43" width="365" height="5"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                </box>
                <customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4Dt-wS-aZ8" customClass="MASShortcutView">
                    <rect key="frame" x="20" y="15" width="106" height="20"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                </customView>
                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="nmU-jA-Ht8">
                    <rect key="frame" x="130" y="17" width="249" height="17"/>
                    <autoresizingMask key="autoresizingMask"/>
                    <textFieldCell key="cell" lineBreakMode="clipping" alignment="left" title="Show/hide menu bar icons" id="HZP-sl-H5I">
                        <font key="font" metaFont="system"/>
                        <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                    </textFieldCell>
                </textField>
            </subviews>
            <constraints>
                <constraint firstAttribute="width" constant="405" id="WEJ-WZ-mea"/>
                <constraint firstAttribute="height" constant="415" id="ieY-Q5-nHf"/>
            </constraints>
            <point key="canvasLocation" x="137.5" y="172.5"/>
        </customView>
    </objects>
</document>


================================================
FILE: LICENSE
================================================
Mozilla Public License Version 2.0
==================================

1. Definitions
--------------

1.1. "Contributor"
    means each individual or legal entity that creates, contributes to
    the creation of, or owns Covered Software.

1.2. "Contributor Version"
    means the combination of the Contributions of others (if any) used
    by a Contributor and that particular Contributor's Contribution.

1.3. "Contribution"
    means Covered Software of a particular Contributor.

1.4. "Covered Software"
    means Source Code Form to which the initial Contributor has attached
    the notice in Exhibit A, the Executable Form of such Source Code
    Form, and Modifications of such Source Code Form, in each case
    including portions thereof.

1.5. "Incompatible With Secondary Licenses"
    means

    (a) that the initial Contributor has attached the notice described
        in Exhibit B to the Covered Software; or

    (b) that the Covered Software was made available under the terms of
        version 1.1 or earlier of the License, but not also under the
        terms of a Secondary License.

1.6. "Executable Form"
    means any form of the work other than Source Code Form.

1.7. "Larger Work"
    means a work that combines Covered Software with other material, in
    a separate file or files, that is not Covered Software.

1.8. "License"
    means this document.

1.9. "Licensable"
    means having the right to grant, to the maximum extent possible,
    whether at the time of the initial grant or subsequently, any and
    all of the rights conveyed by this License.

1.10. "Modifications"
    means any of the following:

    (a) any file in Source Code Form that results from an addition to,
        deletion from, or modification of the contents of Covered
        Software; or

    (b) any new file in Source Code Form that contains any Covered
        Software.

1.11. "Patent Claims" of a Contributor
    means any patent claim(s), including without limitation, method,
    process, and apparatus claims, in any patent Licensable by such
    Contributor that would be infringed, but for the grant of the
    License, by the making, using, selling, offering for sale, having
    made, import, or transfer of either its Contributions or its
    Contributor Version.

1.12. "Secondary License"
    means either the GNU General Public License, Version 2.0, the GNU
    Lesser General Public License, Version 2.1, the GNU Affero General
    Public License, Version 3.0, or any later versions of those
    licenses.

1.13. "Source Code Form"
    means the form of the work preferred for making modifications.

1.14. "You" (or "Your")
    means an individual or a legal entity exercising rights under this
    License. For legal entities, "You" includes any entity that
    controls, is controlled by, or is under common control with You. For
    purposes of this definition, "control" means (a) the power, direct
    or indirect, to cause the direction or management of such entity,
    whether by contract or otherwise, or (b) ownership of more than
    fifty percent (50%) of the outstanding shares or beneficial
    ownership of such entity.

2. License Grants and Conditions
--------------------------------

2.1. Grants

Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:

(a) under intellectual property rights (other than patent or trademark)
    Licensable by such Contributor to use, reproduce, make available,
    modify, display, perform, distribute, and otherwise exploit its
    Contributions, either on an unmodified basis, with Modifications, or
    as part of a Larger Work; and

(b) under Patent Claims of such Contributor to make, use, sell, offer
    for sale, have made, import, and otherwise transfer either its
    Contributions or its Contributor Version.

2.2. Effective Date

The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.

2.3. Limitations on Grant Scope

The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:

(a) for any code that a Contributor has removed from Covered Software;
    or

(b) for infringements caused by: (i) Your and any other third party's
    modifications of Covered Software, or (ii) the combination of its
    Contributions with other software (except as part of its Contributor
    Version); or

(c) under Patent Claims infringed by Covered Software in the absence of
    its Contributions.

This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).

2.4. Subsequent Licenses

No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).

2.5. Representation

Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.

2.6. Fair Use

This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.

2.7. Conditions

Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.

3. Responsibilities
-------------------

3.1. Distribution of Source Form

All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.

3.2. Distribution of Executable Form

If You distribute Covered Software in Executable Form then:

(a) such Covered Software must also be made available in Source Code
    Form, as described in Section 3.1, and You must inform recipients of
    the Executable Form how they can obtain a copy of such Source Code
    Form by reasonable means in a timely manner, at a charge no more
    than the cost of distribution to the recipient; and

(b) You may distribute such Executable Form under the terms of this
    License, or sublicense it under different terms, provided that the
    license for the Executable Form does not attempt to limit or alter
    the recipients' rights in the Source Code Form under this License.

3.3. Distribution of a Larger Work

You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).

3.4. Notices

You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.

3.5. Application of Additional Terms

You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.

4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------

If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.

5. Termination
--------------

5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.

5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.

5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.

************************************************************************
*                                                                      *
*  6. Disclaimer of Warranty                                           *
*  -------------------------                                           *
*                                                                      *
*  Covered Software is provided under this License on an "as is"       *
*  basis, without warranty of any kind, either expressed, implied, or  *
*  statutory, including, without limitation, warranties that the       *
*  Covered Software is free of defects, merchantable, fit for a        *
*  particular purpose or non-infringing. The entire risk as to the     *
*  quality and performance of the Covered Software is with You.        *
*  Should any Covered Software prove defective in any respect, You     *
*  (not any Contributor) assume the cost of any necessary servicing,   *
*  repair, or correction. This disclaimer of warranty constitutes an   *
*  essential part of this License. No use of any Covered Software is   *
*  authorized under this License except under this disclaimer.         *
*                                                                      *
************************************************************************

************************************************************************
*                                                                      *
*  7. Limitation of Liability                                          *
*  --------------------------                                          *
*                                                                      *
*  Under no circumstances and under no legal theory, whether tort      *
*  (including negligence), contract, or otherwise, shall any           *
*  Contributor, or anyone who distributes Covered Software as          *
*  permitted above, be liable to You for any direct, indirect,         *
*  special, incidental, or consequential damages of any character      *
*  including, without limitation, damages for lost profits, loss of    *
*  goodwill, work stoppage, computer failure or malfunction, or any    *
*  and all other commercial damages or losses, even if such party      *
*  shall have been informed of the possibility of such damages. This   *
*  limitation of liability shall not apply to liability for death or   *
*  personal injury resulting from such party's negligence to the       *
*  extent applicable law prohibits such limitation. Some               *
*  jurisdictions do not allow the exclusion or limitation of           *
*  incidental or consequential damages, so this exclusion and          *
*  limitation may not apply to You.                                    *
*                                                                      *
************************************************************************

8. Litigation
-------------

Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.

9. Miscellaneous
----------------

This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.

10. Versions of the License
---------------------------

10.1. New Versions

Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.

10.2. Effect of New Versions

You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.

10.3. Modified Versions

If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).

10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses

If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.

Exhibit A - Source Code Form License Notice
-------------------------------------------

  This Source Code Form is subject to the terms of the Mozilla Public
  License, v. 2.0. If a copy of the MPL was not distributed with this
  file, You can obtain one at http://mozilla.org/MPL/2.0/.

If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.

You may add additional accurate notices of copyright ownership.

Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------

  This Source Code Form is "Incompatible With Secondary Licenses", as
  defined by the Mozilla Public License, v. 2.0.


================================================
FILE: Makefile
================================================
build:
	@brew bundle --no-upgrade
	@carthage bootstrap --cache-builds --platform osx
	@mkdir -p Dozer/Other/Generated
	@swiftgen
	@xcodegen 
	@xed "."

release:
	@echo "Running Fastlane deploy"
	@bundle exec fastlane release

.PHONY: build release 


================================================
FILE: README.md
================================================
<p align="center">
	<img width="200" height="200" margin-right="100%" src="https://raw.githubusercontent.com/Mortennn/Dozer/master/Stuff/AppIcon.png">
</p>
<p align="center">Hide menu bar icons to give your Mac a cleaner look.</p>
<p align="center">
	<a href="https://github.com/Mortennn/Dozer/releases/latest">
 		<img src="https://img.shields.io/badge/download-latest-brightgreen.svg" alt="download">
	<a href="https://img.shields.io/badge/platform-macOS-lightgrey.svg">
 		<img src="https://img.shields.io/badge/platform-macOS-lightgrey.svg" alt="platform">
	</a>
	<a href="https://img.shields.io/badge/requirements-macOS High Sierra+-ff69b4.svg">
 		<img src="https://img.shields.io/badge/requirements-macOS High Sierra+-lightgrey.svg" alt="systemrequirements">
	</a>
	<a href="https://github.com/sindresorhus/swiftlint-sindre">
 		<img src="https://img.shields.io/badge/SwiftLint-Sindre-hotpink.svg" alt="swiftlint">
	</a>
	<a href="https://opensource.org/licenses/MPL-2.0">
 		<img src="https://img.shields.io/badge/License-MPL%202.0-orange.svg" alt="license">
	</a>
</p>
<p align="center">
	<img height="100" min-width="100" src="https://github.com/Mortennn/Dozer/raw/master/Stuff/demo.gif" alt="demo">
</p>

<p align="center"></p>
<a href="https://www.buymeacoffee.com/mortennn" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>

## ⚙️ Install
Using [Homebrew Cask](https://formulae.brew.sh/cask/dozer):
```shell
brew install --cask dozer
```

Manual:

[Download](https://github.com/Mortennn/Dozer/releases/latest), open and drag the app to the Applications folder.

## ⚫️ Dozer Icons

There are 2 or 3, numbered from right to left:

1. this can be positioned anywhere you prefer, it is only a point of interaction
2. this and everything to its left will be hidden/shown by clicking any Dozer icon
3. (Optional) the "remove" icon and everything to its left will be hidden/shown by option-clicking any Dozer icon

## 👨‍💻 Usage

* Move the icons you want to hide until clicked to the left of the second Dozer icon
* Move the icons you want to hide until option-clicked to the left of the third Dozer icon

**N.B. hold command (`⌘`) then drag to move the menu bar icons.**

## 👇 Interactions
* Left-click one of the Dozer icons to hide/show the first group of menu bar icons
* Option-Left-click one of the Dozer icons to show the second group of menu bar icons (optional)
* Right-click one of the Dozer icons to open the settings

<!-- GIF is commented out until it is redone -->
<!-- **Checkout [this GIF](https://raw.githubusercontent.com/Mortennn/Dozer/master/Stuff/demo.gif) to watch Dozer in action.** -->

## 📄 Requirements
macOS 10.13+


================================================
FILE: Scripts/LaunchAtLogin.sh
================================================
./Carthage/Build/Mac/LaunchAtLogin.framework/Resources/copy-helper.sh


================================================
FILE: Scripts/SignFrameworks.sh
================================================
LOCATION="${BUILT_PRODUCTS_DIR}"/"${FRAMEWORKS_FOLDER_PATH}"

# By default, use the configured code signing identity for the project/target
IDENTITY="${CODE_SIGN_IDENTITY}"
if [ "$IDENTITY" == "" ]
then
    # If a code signing identity is not specified, use ad hoc signing
    IDENTITY="-"
fi
codesign --verbose --force --deep -o runtime --sign "$IDENTITY" "$LOCATION/Sparkle.framework/Versions/A/Resources/AutoUpdate.app"
codesign --verbose --force -o runtime --sign "$IDENTITY" "$LOCATION/Sparkle.framework/Versions/A"


================================================
FILE: Scripts/Swiftlint.sh
================================================
if which swiftlint >/dev/null; then
  swiftlint
else
  echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi


================================================
FILE: Stuff/OldFiles/AnimationWindow.swift
================================================
import Cocoa

final class AnimationWindow: NSPanel {
    convenience init(frame: NSRect) {
        self.init(contentRect: frame, styleMask: .nonactivatingPanel, backing: .buffered, defer: false)
        self.isOpaque = false
        self.hasShadow = true
        self.titlebarAppearsTransparent = true
        self.titleVisibility = .hidden
        self.level = .init(26)
        self.collectionBehavior = [.canJoinAllSpaces, .fullScreenNone]
        self.backgroundColor = NSColor(calibratedRed: 0.13, green: 0.13, blue: 0.12, alpha: 1)
        self.ignoresMouseEvents = false
    }

    func animate() {
        self.alphaValue = 1
        self.makeKeyAndOrderFront(nil)
        NSAnimationContext.runAnimationGroup({ context in
            context.duration = TimeInterval(0.25)
            self.animator().alphaValue = 0
        }, completionHandler: nil)
    }
}


================================================
FILE: Stuff/OldFiles/ClickedWindowInfo.swift
================================================
// This can be used when detecting clicks on status bar
extension NSEvent {
    var clickedWindowInfo: [String: AnyObject]? {
        let type = CGWindowListOption.optionOnScreenOnly
        let windowList = CGWindowListCopyWindowInfo(type, kCGNullWindowID) as NSArray? as? [[String: AnyObject]]

        for entry in windowList! {
            guard let windowNumber = entry[kCGWindowNumber as String] as? Int else { continue }
            if windowNumber == self.windowNumber {
                return entry
            }
        }
        return nil
    }
}


================================================
FILE: Stuff/OldFiles/CreateAnimation.swift
================================================
private func createAnimation() {
    let normalStatusIconRightX = Int(DozerStatusIconController.shared.get(dozerIcon: .normalRight).xPositionOnScreen)
    let leftStatusIconPosition = getLeftStatusIcon()
    let frame = NSRect(
        x: leftStatusIconPosition,
        y: Int(NSScreen.main!.frame.height - 22),
        width: normalStatusIconRightX - leftStatusIconPosition,
        height: 22)
    let animationWindow = AnimationWindow(frame: frame)
    animationWindow.orderFront(nil)
    animationWindow.animate()
}


================================================
FILE: Stuff/OldFiles/GetLeftStatusIcon.swift
================================================
import Cocoa

#warning("possible bug: this should only return the visible icons positions")
func getLeftStatusIcon() -> Int {
    guard let windowInfoList = CGWindowListCopyWindowInfo(CGWindowListOption.optionOnScreenOnly, kCGNullWindowID) as NSArray? as? [[String: AnyObject]] else {
        print("Failed getting the left status icon")
        return 0
    }

    var statusBarIconX: [Int] = []

    // collect all status bar icons x positions
    for windowInfo in windowInfoList {
        guard let window = Window(windowInfo) else { continue }
        guard window.isStatusIcon else { continue }
        statusBarIconX.append(window.x)
    }

    // find the smallest x position
    guard let minX = statusBarIconX.min() else {
        print("Failed getting the smallest x position")
        return 0
    }
    return minX
}


================================================
FILE: Stuff/OldFiles/Screen.swift
================================================
import Cocoa

extension NSScreen {
    /// Takes a window point an outputs the screen the window is located on
    ///
    /// - Parameter point: Window point
    /// - Returns: The screen the window is located on
    class func currentScreenForPointLocation(point: NSPoint) -> NSScreen? {
        for screen in NSScreen.screens {
            if NSMouseInRect(point, screen.frame, false) {
                return screen
            }
        }
        return nil
    }

    /// Converts global point to point relative to screen
    ///
    /// - Parameter aPoint: window point
    /// - Returns: window point relative to screen
    func convertPoint(toScreenCoordinates aPoint: NSPoint) -> NSPoint {
        let normalizedX: CGFloat = abs(abs(frame.origin.x) - abs(aPoint.x))
        let normalizedY: CGFloat = aPoint.y - frame.origin.y

        return NSPoint(x: normalizedX, y: normalizedY)
    }

    func flip(_ aPoint: NSPoint) -> NSPoint {
        return NSPoint(x: aPoint.x, y: frame.size.height - aPoint.y)
    }
}

// ORIGINAL
// extension NSScreen {
//    class func currentScreenForMouseLocation() -> NSScreen? {
//        let mouseLocation: NSPoint = NSEvent.mouseLocation
//
//        let screenEnumerator: NSEnumerator = (NSScreen.screens as NSArray).objectEnumerator()
//        var screen: NSScreen?
//        while (screen = screenEnumerator.nextObject() as? NSScreen) != nil, !NSMouseInRect(mouseLocation, screen!.frame, false) {}
//
//        return screen
//    }
//
//    func convertPoint(toScreenCoordinates aPoint: NSPoint) -> NSPoint {
//        let normalizedX: CGFloat = abs(abs(frame.origin.x) - abs(aPoint.x))
//        let normalizedY: CGFloat = aPoint.y - frame.origin.y
//
//        return NSPoint(x: normalizedX, y: normalizedY)
//    }
//
//    func flip(_ aPoint: NSPoint) -> NSPoint {
//        return NSPoint(x: aPoint.x, y: frame.size.height - aPoint.y)
//    }
// }


================================================
FILE: appcast.xml
================================================
<?xml version="1.0" standalone="yes"?><rss xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" version="2.0">
<channel>
<title>Dozer</title>
<item>
<title>4.0.0</title>
<description><![CDATA[<h2>New features in version 4:</h2><ul><li>”Remove”-icon. Additional icon to hide/show icons with `option+click`</li><li>Auto-hide status bar icons #22</li><li>”No Icon”-mode. Hide/show only using keyboard shortcut</li></ul><h2>Other:</h2><ul><li>Improved UI in preferences</li></ul><ul>]]></description>
<pubDate>Tue, 20 Aug 2019 13:01:53 +0200</pubDate>
<sparkle:minimumSystemVersion>10.13</sparkle:minimumSystemVersion>
<enclosure url="https://github.com/Mortennn/Dozer/releases/download/v4.0.0/Dozer.4.0.0.dmg" sparkle:version="27" sparkle:shortVersionString="4.0.0" length="8081734" type="application/octet-stream" sparkle:edSignature="CFXdt4FjQxevj6FfjDlpXQyHV7rYm8RGBRV8uw+nE6EulKvt04rLb8VBwjywG5GgqooXW78y073hO079KGkhAQ=="/>
</item>
</channel></rss>

================================================
FILE: project.yml
================================================
name: Dozer
options:
  usesTabs: false
  tabWidth: 4
  createIntermediateGroups: true
  xcodeVersion: 10.2.1
  deploymentTarget: 10.13
targets:
  Dozer:
    type: application
    platform: macOS
    deploymentTarget: 
      macOS: 10.13
    configFiles:
      Debug: Configs/Debug.xcconfig
      Release: Configs/Release.xcconfig
    sources:
      - Dozer
    postBuildScripts:
      - path: Scripts/LaunchAtLogin.sh
        name: Launch At Login
        runOnlyWhenInstalling: true
      - path: Scripts/SignFrameworks.sh
        name: Sign Frameworks
        runOnlyWhenInstalling: true
        runOnlyWhenInstalling: true
      - script: /usr/local/bin/swiftgen
        name: Generate files using SwiftGen
      - path: Scripts/Swiftlint.sh
        name: Swiftlint
    settings:
      base:
        CODE_SIGN_ENTITLEMENTS: Dozer/Other/Dozer.entitlements
        PRODUCT_BUNDLE_IDENTIFIER: "com.mortennn.Dozer"
        SWIFT_VERSION: 5
        DEBUG_INFORMATION_FORMAT: "dwarf-with-dsym"
        ENABLE_HARDENED_RUNTIME: true
        MACOSX_DEPLOYMENT_TARGET: 10.13
        VERSIONING_SYSTEM: apple-generic
        CURRENT_PROJECT_VERSION: 30
    dependencies:
      - carthage: LaunchAtLogin
      - carthage: Defaults
      - carthage: Preferences
      - carthage: MASShortcut
      - carthage: Sparkle
schemes:
  Dozer:
    build:
      targets:
        Dozer: all

================================================
FILE: swiftgen.yml
================================================
input_dir: Dozer/Other/
output_dir: Dozer/Other/Generated/
xcassets:
  inputs:
    Assets.xcassets
  outputs:
    - templateName: swift4
      output: Assets.swift
      params:
        enumName: Assets
Download .txt
gitextract_h3o59koz/

├── .gitignore
├── .swiftlint.yml
├── Brewfile
├── Brewfile.lock.json
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Cartfile
├── Cartfile.resolved
├── Configs/
│   ├── Debug.xcconfig
│   └── Release.xcconfig
├── Dozer/
│   ├── AppDelegate.swift
│   ├── Constants.swift
│   ├── DozerIcons.swift
│   ├── Other/
│   │   ├── Assets.xcassets/
│   │   │   ├── AppIcon.appiconset/
│   │   │   │   └── Contents.json
│   │   │   ├── Contents.json
│   │   │   └── HelperStatusItemIcon.imageset/
│   │   │       └── Contents.json
│   │   ├── Dozer.entitlements
│   │   ├── Info.plist
│   │   ├── bridging-header.h
│   │   └── main.swift
│   ├── StatusIconClasses/
│   │   ├── HelperStatusIcon.swift
│   │   ├── NormalStatusIcon.swift
│   │   └── RemoveStatusIcon.swift
│   ├── Util.swift
│   ├── ViewControllers/
│   │   ├── DozerVC.swift
│   │   └── GeneralVC.swift
│   └── XIB/
│       ├── Dozer.xib
│       └── General.xib
├── LICENSE
├── Makefile
├── README.md
├── Scripts/
│   ├── LaunchAtLogin.sh
│   ├── SignFrameworks.sh
│   └── Swiftlint.sh
├── Stuff/
│   └── OldFiles/
│       ├── AnimationWindow.swift
│       ├── ClickedWindowInfo.swift
│       ├── CreateAnimation.swift
│       ├── GetLeftStatusIcon.swift
│       └── Screen.swift
├── appcast.xml
├── project.yml
└── swiftgen.yml
Condensed preview — 42 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (106K chars).
[
  {
    "path": ".gitignore",
    "chars": 159,
    "preview": "build/\n.build/\nReleases/\nDozer.xcodeproj/\nCredentials/\nCarthage/\n\n# Fastlane\nfastlane/\nfastlaneLegacy/\nGemfile\nGemfile.l"
  },
  {
    "path": ".swiftlint.yml",
    "chars": 3627,
    "preview": "whitelist_rules:\n  - anyobject_protocol\n  - array_init\n  - attributes\n  - block_based_kvo\n  - class_delegate_protocol\n  "
  },
  {
    "path": "Brewfile",
    "chars": 84,
    "preview": "brew \"swiftformat\"\nbrew \"swiftgen\"\nbrew \"swiftlint\"\nbrew \"xcodegen\"\nbrew \"carthage\"\n"
  },
  {
    "path": "Brewfile.lock.json",
    "chars": 3900,
    "preview": "{\n  \"entries\": {\n    \"brew\": {\n      \"swiftformat\": {\n        \"version\": \"0.44.16\",\n        \"bottle\": {\n          \"cella"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 741,
    "preview": "# Changelog\n\n## Version 4.2.0\nNew features:\n* Configure amount of seconds to hide the icons after #104. @blakedgordon\n* "
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 1407,
    "preview": "# Contributing to Dozer\n\nThere are various ways to contribute to Dozer, and all are welcome and appreciated!\n\n- [Bug rep"
  },
  {
    "path": "Cartfile",
    "chars": 165,
    "preview": "github \"sindresorhus/LaunchAtLogin\"\ngithub \"sindresorhus/Defaults\"\ngithub \"sindresorhus/Preferences\"\ngithub \"shpakovski/"
  },
  {
    "path": "Cartfile.resolved",
    "chars": 210,
    "preview": "github \"shpakovski/MASShortcut\" \"2.4.0\"\ngithub \"sindresorhus/Defaults\" \"v4.2.2\"\ngithub \"sindresorhus/LaunchAtLogin\" \"v4."
  },
  {
    "path": "Configs/Debug.xcconfig",
    "chars": 121,
    "preview": "SWIFT_COMPILATION_MODE=Incremental\nSWIFT_OPTIMIZATION_LEVEL=-Onone\nDEBUG_INFORMATION_FORMAT=dwarf\nENABLE_TESTABILITY=YES"
  },
  {
    "path": "Configs/Release.xcconfig",
    "chars": 63,
    "preview": "SWIFT_COMPILATION_MODE=wholemodule\nSWIFT_OPTIMIZATION_LEVEL=-O\n"
  },
  {
    "path": "Dozer/AppDelegate.swift",
    "chars": 1303,
    "preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
  },
  {
    "path": "Dozer/Constants.swift",
    "chars": 2280,
    "preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
  },
  {
    "path": "Dozer/DozerIcons.swift",
    "chars": 13207,
    "preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
  },
  {
    "path": "Dozer/Other/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 1300,
    "preview": "{\n  \"images\" : [\n    {\n      \"size\" : \"16x16\",\n      \"idiom\" : \"mac\",\n      \"filename\" : \"Icon_16x16.png\",\n      \"scale\""
  },
  {
    "path": "Dozer/Other/Assets.xcassets/Contents.json",
    "chars": 62,
    "preview": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Dozer/Other/Assets.xcassets/HelperStatusItemIcon.imageset/Contents.json",
    "chars": 314,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"mac\",\n      \"filename\" : \"icons8-filled-circle-24.png\",\n      \"scale\" : \"1x\"\n   "
  },
  {
    "path": "Dozer/Other/Dozer.entitlements",
    "chars": 181,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Dozer/Other/Info.plist",
    "chars": 1269,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Dozer/Other/bridging-header.h",
    "chars": 325,
    "preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
  },
  {
    "path": "Dozer/Other/main.swift",
    "chars": 375,
    "preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
  },
  {
    "path": "Dozer/StatusIconClasses/HelperStatusIcon.swift",
    "chars": 2638,
    "preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
  },
  {
    "path": "Dozer/StatusIconClasses/NormalStatusIcon.swift",
    "chars": 1027,
    "preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
  },
  {
    "path": "Dozer/StatusIconClasses/RemoveStatusIcon.swift",
    "chars": 1046,
    "preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
  },
  {
    "path": "Dozer/Util.swift",
    "chars": 1051,
    "preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
  },
  {
    "path": "Dozer/ViewControllers/DozerVC.swift",
    "chars": 1173,
    "preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
  },
  {
    "path": "Dozer/ViewControllers/GeneralVC.swift",
    "chars": 5214,
    "preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
  },
  {
    "path": "Dozer/XIB/Dozer.xib",
    "chars": 6599,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion"
  },
  {
    "path": "Dozer/XIB/General.xib",
    "chars": 21436,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion"
  },
  {
    "path": "LICENSE",
    "chars": 16725,
    "preview": "Mozilla Public License Version 2.0\n==================================\n\n1. Definitions\n--------------\n\n1.1. \"Contributor\""
  },
  {
    "path": "Makefile",
    "chars": 249,
    "preview": "build:\n\t@brew bundle --no-upgrade\n\t@carthage bootstrap --cache-builds --platform osx\n\t@mkdir -p Dozer/Other/Generated\n\t@"
  },
  {
    "path": "README.md",
    "chars": 2915,
    "preview": "<p align=\"center\">\n\t<img width=\"200\" height=\"200\" margin-right=\"100%\" src=\"https://raw.githubusercontent.com/Mortennn/Do"
  },
  {
    "path": "Scripts/LaunchAtLogin.sh",
    "chars": 70,
    "preview": "./Carthage/Build/Mac/LaunchAtLogin.framework/Resources/copy-helper.sh\n"
  },
  {
    "path": "Scripts/SignFrameworks.sh",
    "chars": 521,
    "preview": "LOCATION=\"${BUILT_PRODUCTS_DIR}\"/\"${FRAMEWORKS_FOLDER_PATH}\"\n\n# By default, use the configured code signing identity for"
  },
  {
    "path": "Scripts/Swiftlint.sh",
    "chars": 148,
    "preview": "if which swiftlint >/dev/null; then\n  swiftlint\nelse\n  echo \"warning: SwiftLint not installed, download from https://git"
  },
  {
    "path": "Stuff/OldFiles/AnimationWindow.swift",
    "chars": 867,
    "preview": "import Cocoa\n\nfinal class AnimationWindow: NSPanel {\n    convenience init(frame: NSRect) {\n        self.init(contentRect"
  },
  {
    "path": "Stuff/OldFiles/ClickedWindowInfo.swift",
    "chars": 559,
    "preview": "// This can be used when detecting clicks on status bar\nextension NSEvent {\n    var clickedWindowInfo: [String: AnyObjec"
  },
  {
    "path": "Stuff/OldFiles/CreateAnimation.swift",
    "chars": 521,
    "preview": "private func createAnimation() {\n    let normalStatusIconRightX = Int(DozerStatusIconController.shared.get(dozerIcon: .n"
  },
  {
    "path": "Stuff/OldFiles/GetLeftStatusIcon.swift",
    "chars": 830,
    "preview": "import Cocoa\n\n#warning(\"possible bug: this should only return the visible icons positions\")\nfunc getLeftStatusIcon() -> "
  },
  {
    "path": "Stuff/OldFiles/Screen.swift",
    "chars": 1905,
    "preview": "import Cocoa\n\nextension NSScreen {\n    /// Takes a window point an outputs the screen the window is located on\n    ///\n "
  },
  {
    "path": "appcast.xml",
    "chars": 964,
    "preview": "<?xml version=\"1.0\" standalone=\"yes\"?><rss xmlns:sparkle=\"http://www.andymatuschak.org/xml-namespaces/sparkle\" version=\""
  },
  {
    "path": "project.yml",
    "chars": 1371,
    "preview": "name: Dozer\noptions:\n  usesTabs: false\n  tabWidth: 4\n  createIntermediateGroups: true\n  xcodeVersion: 10.2.1\n  deploymen"
  },
  {
    "path": "swiftgen.yml",
    "chars": 203,
    "preview": "input_dir: Dozer/Other/\noutput_dir: Dozer/Other/Generated/\nxcassets:\n  inputs:\n    Assets.xcassets\n  outputs:\n    - temp"
  }
]

About this extraction

This page contains the full source code of the Mortennn/Dozer GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 42 files (96.8 KB), approximately 25.4k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!