├── Pods ├── LetsMove │ ├── en.lproj │ │ ├── InfoPlist.strings │ │ └── MoveApplication.strings │ ├── ca.lproj │ │ └── MoveApplication.strings │ ├── cs.lproj │ │ └── MoveApplication.strings │ ├── da.lproj │ │ └── MoveApplication.strings │ ├── de.lproj │ │ └── MoveApplication.strings │ ├── es.lproj │ │ └── MoveApplication.strings │ ├── fr.lproj │ │ └── MoveApplication.strings │ ├── hu.lproj │ │ └── MoveApplication.strings │ ├── it.lproj │ │ └── MoveApplication.strings │ ├── ja.lproj │ │ └── MoveApplication.strings │ ├── ko.lproj │ │ └── MoveApplication.strings │ ├── mk.lproj │ │ └── MoveApplication.strings │ ├── nb.lproj │ │ └── MoveApplication.strings │ ├── nl.lproj │ │ └── MoveApplication.strings │ ├── pl.lproj │ │ └── MoveApplication.strings │ ├── pt.lproj │ │ └── MoveApplication.strings │ ├── ru.lproj │ │ └── MoveApplication.strings │ ├── sk.lproj │ │ └── MoveApplication.strings │ ├── sr.lproj │ │ └── MoveApplication.strings │ ├── sv.lproj │ │ └── MoveApplication.strings │ ├── tr.lproj │ │ └── MoveApplication.strings │ ├── pt_BR.lproj │ │ └── MoveApplication.strings │ ├── zh_CN.lproj │ │ └── MoveApplication.strings │ ├── zh_TW.lproj │ │ └── MoveApplication.strings │ ├── LetsMove.h │ ├── PFMoveApplication.h │ ├── README.md │ └── PFMoveApplication.m ├── Target Support Files │ ├── ITSwitch │ │ ├── ITSwitch.modulemap │ │ ├── ITSwitch-dummy.m │ │ ├── ITSwitch-prefix.pch │ │ ├── ITSwitch-umbrella.h │ │ ├── ITSwitch.xcconfig │ │ └── Info.plist │ ├── LetsMove │ │ ├── LetsMove.modulemap │ │ ├── LetsMove-dummy.m │ │ ├── LetsMove-prefix.pch │ │ ├── LetsMove-umbrella.h │ │ ├── LetsMove.xcconfig │ │ └── Info.plist │ └── Pods-Sub It │ │ ├── Pods-Sub It.modulemap │ │ ├── Pods-Sub It-dummy.m │ │ ├── Pods-Sub It-umbrella.h │ │ ├── Pods-Sub It.debug.xcconfig │ │ ├── Pods-Sub It.release.xcconfig │ │ ├── Info.plist │ │ ├── Pods-Sub It-resources.sh │ │ ├── Pods-Sub It-frameworks.sh │ │ ├── Pods-Sub It-acknowledgements.markdown │ │ └── Pods-Sub It-acknowledgements.plist ├── Manifest.lock └── ITSwitch │ ├── ITSwitch │ ├── ITSwitch.h │ └── ITSwitch.m │ ├── README.md │ └── LICENSE ├── Podfile ├── ReadMe Resources ├── Settings.png └── MainWindow.png ├── Sub It ├── Assets.xcassets │ ├── Contents.json │ ├── K.imageset │ │ ├── K.png │ │ └── Contents.json │ ├── refresh.imageset │ │ ├── r4.png │ │ └── Contents.json │ ├── github.imageset │ │ ├── 25231.png │ │ └── Contents.json │ ├── package.imageset │ │ ├── package.png │ │ └── Contents.json │ ├── Settings.imageset │ │ ├── Settings.png │ │ └── Contents.json │ ├── safari.imageset │ │ ├── safari-icon.png │ │ └── Contents.json │ ├── subtitle.imageset │ │ ├── subtitle.png │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ ├── Icon_16x16.png │ │ ├── Icon_32x32.png │ │ ├── Icon_128x128.png │ │ ├── Icon_16x16@2x.png │ │ ├── Icon_256x256.png │ │ ├── Icon_32x32@2x.png │ │ ├── Icon_512x512.png │ │ ├── Icon_128x128@2x.png │ │ ├── Icon_256x256@2x.png │ │ ├── Icon_512x512@2x.png │ │ └── Contents.json │ ├── left arrow.imageset │ │ ├── left arrow.png │ │ └── Contents.json │ ├── Folder-icon.imageset │ │ ├── Folder-icon.png │ │ └── Contents.json │ ├── right arrow.imageset │ │ ├── right arrow.png │ │ └── Contents.json │ ├── paypal.imageset │ │ ├── paypal-icon-614x460.png │ │ └── Contents.json │ └── arrowDown.imageset │ │ ├── 1f0bfba0e3fe29faa448ae8f9576c718_picture-of-arrow-down-arrow-down-clipart_2400-2400.png │ │ └── Contents.json ├── WindowController.swift ├── GrayButton.swift ├── ProgressView.swift ├── AppDelegate.swift ├── DownloadButton.swift ├── openTerminalButton.swift ├── optionsTextfield.swift ├── Info.plist ├── installationGuideTextField.swift ├── Constants.swift ├── AboutViewController.swift ├── InstallationGuideTexts.swift ├── SubIt.swift ├── dropView.swift ├── InstallationGuideViewController.swift ├── ViewController.swift └── OptionsViewController.swift ├── Sub It.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── project.pbxproj ├── Sub It.xcworkspace ├── xcshareddata │ └── IDEWorkspaceChecks.plist └── contents.xcworkspacedata ├── Podfile.lock ├── LICENSE ├── .gitignore └── README.md /Pods/LetsMove/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | target ‘Sub It’ do 2 | use_frameworks! 3 | pod 'ITSwitch' 4 | pod 'LetsMove' 5 | end 6 | -------------------------------------------------------------------------------- /ReadMe Resources/Settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/ReadMe Resources/Settings.png -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ReadMe Resources/MainWindow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/ReadMe Resources/MainWindow.png -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/K.imageset/K.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Sub It/Assets.xcassets/K.imageset/K.png -------------------------------------------------------------------------------- /Pods/LetsMove/ca.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/ca.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Pods/LetsMove/cs.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/cs.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Pods/LetsMove/da.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/da.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Pods/LetsMove/de.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/de.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Pods/LetsMove/en.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/en.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Pods/LetsMove/es.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/es.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Pods/LetsMove/fr.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/fr.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Pods/LetsMove/hu.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/hu.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Pods/LetsMove/it.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/it.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Pods/LetsMove/ja.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/ja.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Pods/LetsMove/ko.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/ko.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Pods/LetsMove/mk.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/mk.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Pods/LetsMove/nb.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/nb.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Pods/LetsMove/nl.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/nl.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Pods/LetsMove/pl.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/pl.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Pods/LetsMove/pt.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/pt.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Pods/LetsMove/ru.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/ru.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Pods/LetsMove/sk.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/sk.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Pods/LetsMove/sr.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/sr.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Pods/LetsMove/sv.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/sv.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Pods/LetsMove/tr.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/tr.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/refresh.imageset/r4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Sub It/Assets.xcassets/refresh.imageset/r4.png -------------------------------------------------------------------------------- /Pods/LetsMove/pt_BR.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/pt_BR.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Pods/LetsMove/zh_CN.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/zh_CN.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Pods/LetsMove/zh_TW.lproj/MoveApplication.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Pods/LetsMove/zh_TW.lproj/MoveApplication.strings -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/github.imageset/25231.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Sub It/Assets.xcassets/github.imageset/25231.png -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/package.imageset/package.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Sub It/Assets.xcassets/package.imageset/package.png -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/Settings.imageset/Settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Sub It/Assets.xcassets/Settings.imageset/Settings.png -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/safari.imageset/safari-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Sub It/Assets.xcassets/safari.imageset/safari-icon.png -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/subtitle.imageset/subtitle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Sub It/Assets.xcassets/subtitle.imageset/subtitle.png -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/AppIcon.appiconset/Icon_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Sub It/Assets.xcassets/AppIcon.appiconset/Icon_16x16.png -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/AppIcon.appiconset/Icon_32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Sub It/Assets.xcassets/AppIcon.appiconset/Icon_32x32.png -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/left arrow.imageset/left arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Sub It/Assets.xcassets/left arrow.imageset/left arrow.png -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/AppIcon.appiconset/Icon_128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Sub It/Assets.xcassets/AppIcon.appiconset/Icon_128x128.png -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/AppIcon.appiconset/Icon_16x16@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Sub It/Assets.xcassets/AppIcon.appiconset/Icon_16x16@2x.png -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/AppIcon.appiconset/Icon_256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Sub It/Assets.xcassets/AppIcon.appiconset/Icon_256x256.png -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/AppIcon.appiconset/Icon_32x32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Sub It/Assets.xcassets/AppIcon.appiconset/Icon_32x32@2x.png -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/AppIcon.appiconset/Icon_512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Sub It/Assets.xcassets/AppIcon.appiconset/Icon_512x512.png -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/Folder-icon.imageset/Folder-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Sub It/Assets.xcassets/Folder-icon.imageset/Folder-icon.png -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/right arrow.imageset/right arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Sub It/Assets.xcassets/right arrow.imageset/right arrow.png -------------------------------------------------------------------------------- /Pods/Target Support Files/ITSwitch/ITSwitch.modulemap: -------------------------------------------------------------------------------- 1 | framework module ITSwitch { 2 | umbrella header "ITSwitch-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/LetsMove/LetsMove.modulemap: -------------------------------------------------------------------------------- 1 | framework module LetsMove { 2 | umbrella header "LetsMove-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/AppIcon.appiconset/Icon_128x128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Sub It/Assets.xcassets/AppIcon.appiconset/Icon_128x128@2x.png -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/AppIcon.appiconset/Icon_256x256@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Sub It/Assets.xcassets/AppIcon.appiconset/Icon_256x256@2x.png -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/AppIcon.appiconset/Icon_512x512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Sub It/Assets.xcassets/AppIcon.appiconset/Icon_512x512@2x.png -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/paypal.imageset/paypal-icon-614x460.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Sub It/Assets.xcassets/paypal.imageset/paypal-icon-614x460.png -------------------------------------------------------------------------------- /Pods/Target Support Files/ITSwitch/ITSwitch-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_ITSwitch : NSObject 3 | @end 4 | @implementation PodsDummy_ITSwitch 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/LetsMove/LetsMove-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_LetsMove : NSObject 3 | @end 4 | @implementation PodsDummy_LetsMove 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Sub It/Pods-Sub It.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_Sub_It { 2 | umbrella header "Pods-Sub It-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Sub It/Pods-Sub It-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_Sub_It : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_Sub_It 5 | @end 6 | -------------------------------------------------------------------------------- /Sub It.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Pods/LetsMove/LetsMove.h: -------------------------------------------------------------------------------- 1 | // 2 | // LetsMove.h 3 | // LetsMove 4 | // 5 | // Created by Matt Prowse on 14/05/2016. 6 | // 7 | // The contents of this file are dedicated to the public domain. 8 | 9 | #import 10 | #import 11 | -------------------------------------------------------------------------------- /Pods/Target Support Files/ITSwitch/ITSwitch-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/LetsMove/LetsMove-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/arrowDown.imageset/1f0bfba0e3fe29faa448ae8f9576c718_picture-of-arrow-down-arrow-down-clipart_2400-2400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kevin-De-Koninck/Sub-It/HEAD/Sub It/Assets.xcassets/arrowDown.imageset/1f0bfba0e3fe29faa448ae8f9576c718_picture-of-arrow-down-arrow-down-clipart_2400-2400.png -------------------------------------------------------------------------------- /Sub It.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Pods/LetsMove/PFMoveApplication.h: -------------------------------------------------------------------------------- 1 | // 2 | // PFMoveApplication.h, version 1.22 3 | // LetsMove 4 | // 5 | // Created by Andy Kim at Potion Factory LLC on 9/17/09 6 | // 7 | // The contents of this file are dedicated to the public domain. 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | void PFMoveToApplicationsFolderIfNecessary(void); 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/K.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "K.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Sub It.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/refresh.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "r4.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Sub It/Pods-Sub It-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_Sub_ItVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_Sub_ItVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/github.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "25231.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/package.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "package.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/Settings.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Settings.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/safari.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "safari-icon.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/subtitle.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "subtitle.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Sub It/WindowController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WindowController.swift 3 | // Sub It 4 | // 5 | // Created by Kevin De Koninck on 28/01/2017. 6 | // Copyright © 2017 Kevin De Koninck. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class WindowController: NSWindowController { 12 | 13 | override func windowDidLoad() { 14 | super.windowDidLoad() 15 | self.window!.backgroundColor = NSColor.white 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/Folder-icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Folder-icon.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/left arrow.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "left arrow.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/right arrow.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "right arrow.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Pods/Target Support Files/ITSwitch/ITSwitch-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | #import "ITSwitch.h" 14 | 15 | FOUNDATION_EXPORT double ITSwitchVersionNumber; 16 | FOUNDATION_EXPORT const unsigned char ITSwitchVersionString[]; 17 | 18 | -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/paypal.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "paypal-icon-614x460.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Pods/Target Support Files/LetsMove/LetsMove-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | #import "PFMoveApplication.h" 14 | 15 | FOUNDATION_EXPORT double LetsMoveVersionNumber; 16 | FOUNDATION_EXPORT const unsigned char LetsMoveVersionString[]; 17 | 18 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - ITSwitch (1.0) 3 | - LetsMove (1.22) 4 | 5 | DEPENDENCIES: 6 | - ITSwitch 7 | - LetsMove 8 | 9 | SPEC REPOS: 10 | https://github.com/CocoaPods/Specs.git: 11 | - ITSwitch 12 | - LetsMove 13 | 14 | SPEC CHECKSUMS: 15 | ITSwitch: 7ff745d6f2a6910e9194b23e4eab9a843258a478 16 | LetsMove: 407d4d14815e6dc1549b6a9fe8e4b0f6aed3e305 17 | 18 | PODFILE CHECKSUM: 0bea7d6e33d310773e4b8497fdeb97e7d6cec2fb 19 | 20 | COCOAPODS: 1.5.0 21 | -------------------------------------------------------------------------------- /Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - ITSwitch (1.0) 3 | - LetsMove (1.22) 4 | 5 | DEPENDENCIES: 6 | - ITSwitch 7 | - LetsMove 8 | 9 | SPEC REPOS: 10 | https://github.com/CocoaPods/Specs.git: 11 | - ITSwitch 12 | - LetsMove 13 | 14 | SPEC CHECKSUMS: 15 | ITSwitch: 7ff745d6f2a6910e9194b23e4eab9a843258a478 16 | LetsMove: 407d4d14815e6dc1549b6a9fe8e4b0f6aed3e305 17 | 18 | PODFILE CHECKSUM: 0bea7d6e33d310773e4b8497fdeb97e7d6cec2fb 19 | 20 | COCOAPODS: 1.5.0 21 | -------------------------------------------------------------------------------- /Pods/Target Support Files/LetsMove/LetsMove.xcconfig: -------------------------------------------------------------------------------- 1 | CODE_SIGN_IDENTITY = 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/LetsMove 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | PODS_BUILD_DIR = ${BUILD_DIR} 5 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 6 | PODS_ROOT = ${SRCROOT} 7 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/LetsMove 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/arrowDown.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "1f0bfba0e3fe29faa448ae8f9576c718_picture-of-arrow-down-arrow-down-clipart_2400-2400.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Pods/Target Support Files/ITSwitch/ITSwitch.xcconfig: -------------------------------------------------------------------------------- 1 | CODE_SIGN_IDENTITY = 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/ITSwitch 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | OTHER_LDFLAGS = -framework "QuartzCore" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/ITSwitch 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 10 | SKIP_INSTALL = YES 11 | -------------------------------------------------------------------------------- /Sub It/GrayButton.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GrayButton.swift 3 | // Sub It 4 | // 5 | // Created by Kevin De Koninck on 29/01/2017. 6 | // Copyright © 2017 Kevin De Koninck. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class GrayButton: NSButton { 12 | 13 | override func draw(_ dirtyRect: NSRect) { 14 | super.draw(dirtyRect) 15 | 16 | self.layer?.backgroundColor = CGColor.init(red: 0.3, green: 0.3, blue: 0.3, alpha: 0.3) 17 | self.layer?.cornerRadius = 15.0 18 | self.layer?.masksToBounds = true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Sub It/ProgressView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ProgressView.swift 3 | // Sub It 4 | // 5 | // Created by Kevin De Koninck on 13/05/2018. 6 | // Copyright © 2018 Kevin De Koninck. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class ProgressView: NSView { 12 | 13 | override func draw(_ dirtyRect: NSRect) { 14 | super.draw(dirtyRect) 15 | 16 | self.alphaValue = 0.7 17 | self.layer?.backgroundColor = NSColor.black.cgColor 18 | self.layer?.cornerRadius = 15.0 19 | self.layer?.masksToBounds = true 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Pods/ITSwitch/ITSwitch/ITSwitch.h: -------------------------------------------------------------------------------- 1 | // 2 | // ITSwitch.h 3 | // ITSwitch-Demo 4 | // 5 | // Created by Ilija Tovilo on 01/02/14. 6 | // Copyright (c) 2014 Ilija Tovilo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | * ITSwitch is a replica of UISwitch for Mac OS X 13 | */ 14 | IB_DESIGNABLE 15 | @interface ITSwitch : NSControl 16 | 17 | /** 18 | * @property checked - Gets or sets the switches state 19 | */ 20 | @property (nonatomic, assign) IBInspectable BOOL checked; 21 | 22 | /** 23 | * @property tintColor - Gets or sets the switches tint 24 | */ 25 | @property (nonatomic, strong) IBInspectable NSColor *tintColor; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Sub It/Pods-Sub It.debug.xcconfig: -------------------------------------------------------------------------------- 1 | CODE_SIGN_IDENTITY = 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ITSwitch" "${PODS_CONFIGURATION_BUILD_DIR}/LetsMove" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/../Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/ITSwitch/ITSwitch.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/LetsMove/LetsMove.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "ITSwitch" -framework "LetsMove" 7 | PODS_BUILD_DIR = ${BUILD_DIR} 8 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 9 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 10 | PODS_ROOT = ${SRCROOT}/Pods 11 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Sub It/Pods-Sub It.release.xcconfig: -------------------------------------------------------------------------------- 1 | CODE_SIGN_IDENTITY = 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ITSwitch" "${PODS_CONFIGURATION_BUILD_DIR}/LetsMove" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/../Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/ITSwitch/ITSwitch.framework/Headers" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/LetsMove/LetsMove.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "ITSwitch" -framework "LetsMove" 7 | PODS_BUILD_DIR = ${BUILD_DIR} 8 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 9 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 10 | PODS_ROOT = ${SRCROOT}/Pods 11 | -------------------------------------------------------------------------------- /Pods/Target Support Files/ITSwitch/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/LetsMove/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.22.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Sub It/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Sub It/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Sub It 4 | // 5 | // Created by Kevin De Koninck on 23/05/16. 6 | // Copyright © 2016 Kevin De Koninck. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | import LetsMove 11 | 12 | @NSApplicationMain 13 | class AppDelegate: NSObject, NSApplicationDelegate { 14 | 15 | func applicationDidFinishLaunching(_ aNotification: Notification) { 16 | // Insert code here to initialize your application 17 | } 18 | 19 | func applicationWillTerminate(_ aNotification: Notification) { 20 | // Insert code here to tear down your application 21 | } 22 | 23 | //Close app when closing window 24 | func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 25 | return true; 26 | } 27 | 28 | func applicationWillFinishLaunching(_ notification: Notification) { 29 | PFMoveToApplicationsFolderIfNecessary() 30 | } 31 | 32 | } 33 | 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Kevin De Koninck 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Sub It/DownloadButton.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BlueButton.swift 3 | // Sub It 4 | // 5 | // Created by Kevin De Koninck on 29/01/2017. 6 | // Copyright © 2017 Kevin De Koninck. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class DownloadButton: NSButton { 12 | 13 | override func draw(_ dirtyRect: NSRect) { 14 | super.draw(dirtyRect) 15 | } 16 | 17 | override func awakeFromNib() { 18 | super.awakeFromNib() 19 | 20 | self.layer?.backgroundColor = blueColor.cgColor 21 | self.layer?.cornerRadius = 15.0 22 | self.layer?.masksToBounds = true 23 | 24 | //text 25 | let style = NSMutableParagraphStyle() 26 | style.alignment = .center 27 | self.attributedTitle = NSAttributedString(string: "Download", attributes: [ NSForegroundColorAttributeName : NSColor.white, 28 | NSParagraphStyleAttributeName : style, 29 | NSFontAttributeName: NSFont(name: "Arial", size: 18)!]) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Sub It/openTerminalButton.swift: -------------------------------------------------------------------------------- 1 | // 2 | // openTerminalButton.swift 3 | // Sub It 4 | // 5 | // Created by Kevin De Koninck on 05/02/2017. 6 | // Copyright © 2017 Kevin De Koninck. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class installButton: NSButton { 12 | 13 | override func draw(_ dirtyRect: NSRect) { 14 | super.draw(dirtyRect) 15 | } 16 | 17 | override func awakeFromNib() { 18 | super.awakeFromNib() 19 | 20 | self.layer?.backgroundColor = blueColor.cgColor 21 | self.layer?.cornerRadius = 15.0 22 | self.layer?.masksToBounds = true 23 | 24 | //text 25 | let style = NSMutableParagraphStyle() 26 | style.alignment = .center 27 | self.attributedTitle = NSAttributedString(string: "Install", attributes: [ NSForegroundColorAttributeName : NSColor.white, 28 | NSParagraphStyleAttributeName : style, 29 | NSFontAttributeName: NSFont(name: "Arial", size: 18)!]) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Sub It/optionsTextfield.swift: -------------------------------------------------------------------------------- 1 | // 2 | // optionsTextfield.swift 3 | // Sub It 4 | // 5 | // Created by Kevin De Koninck on 04/02/2017. 6 | // Copyright © 2017 Kevin De Koninck. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class optionsTextfield: NSTextField { 12 | 13 | override func draw(_ dirtyRect: NSRect) { 14 | super.draw(dirtyRect) 15 | 16 | var bgColor = NSColor(red: 251/255.0, green: 251/255.0, blue: 251/255.0, alpha: 1.0) 17 | bgColor = NSColor(red: 245/255.0, green: 245/255.0, blue: 245/255.0, alpha: 1.0) 18 | 19 | self.focusRingType = .none 20 | self.isBordered = false 21 | self.drawsBackground = false 22 | self.backgroundColor = bgColor 23 | self.layer?.backgroundColor = bgColor.cgColor 24 | 25 | //underline 26 | let border = CALayer() 27 | let width = CGFloat(1.0) 28 | border.borderColor = blueColor.cgColor 29 | border.frame = CGRect(x: 0, y: self.frame.size.height - width, width: self.frame.size.width, height: self.frame.size.height) 30 | border.borderWidth = width 31 | self.layer?.addSublayer(border) 32 | self.layer?.masksToBounds = true 33 | 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Sub It/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 0.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSApplicationCategoryType 24 | public.app-category.utilities 25 | LSMinimumSystemVersion 26 | $(MACOSX_DEPLOYMENT_TARGET) 27 | NSHumanReadableCopyright 28 | Copyright © 2017 Kevin De Koninck. All rights reserved. 29 | NSMainStoryboardFile 30 | Main 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /Pods/ITSwitch/README.md: -------------------------------------------------------------------------------- 1 | ITSwitch 2 | ======== 3 | 4 | `ITSwitch` is a simple and lightweight replica of iOS 7 `UISwitch` for Mac OS X. 5 | 6 | ![](./demo.png) 7 | 8 | Usage 9 | ----- 10 | 11 | Not much to it, simply set the custom class of a `NSView` to `ITSwitch` in Interface Builder. 12 | 13 | You can create an IBAction and simply connect the two in Interface Builder. 14 | 15 | Additionally, you can use these two properties: 16 | 17 | ```objc 18 | /** 19 | * @property checked - Gets or sets the switches state 20 | */ 21 | @property (nonatomic, assign) IBInspectable BOOL checked; 22 | 23 | /** 24 | * @property tintColor - Gets or sets the switches tint 25 | */ 26 | @property (nonatomic, strong) IBInspectable NSColor *tintColor; 27 | ``` 28 | 29 | Since `ITSwitch` uses its `CALayer` to draw a drop-shadow, you should also layer-back it's superview. 30 | If you don't use Core Animation, you can also simply embed the view in a layer-backed view. 31 | 32 | Requirements 33 | ------------ 34 | 35 | ITSwitch requires 10.9+ and linking against the QuartzCore.framework. 36 | 37 | Tips 38 | ---- 39 | 40 | You may want to consider setting the width of the view to the golden ratio * height. 41 | 42 | So for example: 43 | 44 | ```objc 45 | height = 20; 46 | width = height * 1.618; 47 | ``` 48 | -------------------------------------------------------------------------------- /Sub It/installationGuideTextField.swift: -------------------------------------------------------------------------------- 1 | // 2 | // installationGuideTextField.swift 3 | // Sub It 4 | // 5 | // Created by Kevin De Koninck on 05/02/2017. 6 | // Copyright © 2017 Kevin De Koninck. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class installationGuideTextField: NSTextField { 12 | 13 | override func draw(_ dirtyRect: NSRect) { 14 | super.draw(dirtyRect) 15 | 16 | var bgColor = NSColor(red: 251/255.0, green: 251/255.0, blue: 251/255.0, alpha: 1.0) 17 | bgColor = NSColor(red: 255/255.0, green: 255/255.0, blue: 255/255.0, alpha: 1.0) 18 | 19 | self.focusRingType = .none 20 | self.isBordered = false 21 | self.drawsBackground = false 22 | self.backgroundColor = bgColor 23 | self.layer?.backgroundColor = bgColor.cgColor 24 | 25 | //underline 26 | let border = CALayer() 27 | let width = CGFloat(1.0) 28 | border.borderColor = blueColor.cgColor 29 | border.frame = CGRect(x: 0, y: self.frame.size.height - width, width: self.frame.size.width, height: self.frame.size.height) 30 | border.borderWidth = width 31 | self.layer?.addSublayer(border) 32 | self.layer?.masksToBounds = true 33 | 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Sub It/Constants.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Constants.swift 3 | // Sub It 4 | // 5 | // Created by Kevin De Koninck on 28/01/2017. 6 | // Copyright © 2017 Kevin De Koninck. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Cocoa 11 | 12 | // Command 13 | let DEFAULT_COMMAND = "export PATH=$PATH:/usr/local/bin && subliminal download -s -l en" 14 | let DEFAULT_OUTPUTPATH = "~/Downloads/" 15 | let REGEX_PATTERN = ".+?(?=\\[)" //matches anything before the [ 16 | 17 | //Color 18 | var blueColor = NSColor.init(red: 45.0/255, green: 135.0/255, blue: 250.0/255, alpha: 1) 19 | 20 | 21 | // Settings 22 | let DEFAULT_SETTINGS = [ "selectedPath" : "~/Downloads/", 23 | "singleFile" : "1", //bool 24 | "forceDownload" : "1", //bool 25 | "preferHearingImpaired" : "0", //bool 26 | "useFilter" : "0", //bool 27 | "seperateDownloadsFolder": "0", //bool 28 | "languageSubs1" : "0", //index 29 | "languageSubs2" : "0" //index 30 | ] 31 | 32 | // User Defaults - keys 33 | let SAVED_COMMAND = "savedCommand" 34 | let SETTINGS_KEY = "settings" 35 | let SUBLIMINAL = "isYTDLInstalled" 36 | let BREW = "isBrewInstalled" 37 | let PYTHON = "isPythonInstalled" 38 | let XCODE = "isXcodeInstalled" 39 | let OUTPUT_PATH = "outputPath" 40 | -------------------------------------------------------------------------------- /Sub It/AboutViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AboutViewController.swift 3 | // Sub It 4 | // 5 | // Created by Kevin De Koninck on 29/01/2017. 6 | // Copyright © 2017 Kevin De Koninck. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class AboutViewController: NSViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | self.view.wantsLayer = true 16 | } 17 | 18 | override func awakeFromNib() { 19 | if self.view.layer != nil { 20 | let color : CGColor = CGColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0) 21 | self.view.layer?.backgroundColor = color 22 | } 23 | } 24 | 25 | @IBAction func githubBtnClicked(_ sender: Any) { 26 | open(website: "https://github.com/Kevin-De-Koninck/Get-It") 27 | } 28 | 29 | @IBAction func kBtnClicked(_ sender: Any) { 30 | open(website: "https://kevindekoninck.com") 31 | } 32 | 33 | @IBAction func supportedSitesBtnClicked(_ sender: Any) { 34 | open(website: "https://rg3.github.io/youtube-dl/supportedsites.html") 35 | } 36 | 37 | @IBAction func githubYTBtnClicked(_ sender: Any) { 38 | open(website: "https://github.com/rg3/youtube-dl") 39 | } 40 | 41 | @IBAction func donateBtnClicked(_ sender: Any) { 42 | open(website: "https://rg3.github.io/youtube-dl/donations.html") 43 | } 44 | 45 | func open(website: String){ 46 | if let url = URL(string: website), NSWorkspace.shared().open(url) { 47 | print("default browser was successfully opened") 48 | } 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /Sub It/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "Icon_16x16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "Icon_16x16@2x.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "Icon_32x32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "Icon_32x32@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "Icon_128x128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "Icon_128x128@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "Icon_256x256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "Icon_256x256@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "Icon_512x512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "Icon_512x512@2x.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | ## Playgrounds 31 | timeline.xctimeline 32 | playground.xcworkspace 33 | 34 | # Swift Package Manager 35 | # 36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 37 | # Packages/ 38 | .build/ 39 | 40 | # CocoaPods 41 | # 42 | # We recommend against adding the Pods directory to your .gitignore. However 43 | # you should judge for yourself, the pros and cons are mentioned at: 44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 45 | # 46 | # Pods/ 47 | 48 | # Carthage 49 | # 50 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 51 | # Carthage/Checkouts 52 | 53 | Carthage/Build 54 | 55 | # fastlane 56 | # 57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 58 | # screenshots whenever they are needed. 59 | # For more information about the recommended setup visit: 60 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 61 | 62 | fastlane/report.xml 63 | fastlane/Preview.html 64 | fastlane/screenshots 65 | fastlane/test_output 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sub-It 2 | Small macOS application to download subtitles. 3 | 4 | 5 | 6 | 7 | # Installation 8 | 9 | Download it [here](https://github.com/Kevin-De-Koninck/Sub-It/releases/download/v0.2/Sub.It.app.zip), unzip it and open it. 10 | If a yellow package button is visible on the main screen, click on it and follow the guide (to install the dependencies). 11 | 12 | # ToDo 13 | These features will come: 14 | - Ad blocker: Based on a friend of mine's script -> Filter all ads out of the downloaded subtitles. 15 | - file association: right-click on your movie and select 'open with Sub It' will start the program and start downloading your subs. 16 | - Menu bar status app: Drag your files the the icon in the menu bar and start downloading your subtitles. 17 | - Cron job installation: see file association. Option to install a cron job to check your movie folder and download missing subtitles every time interval. 18 | - Cute sounds. 19 | 20 | # About 21 | 22 | Sub It will download subtitles for all your movie files. It's a GUI round the popular Subliminal command-line program but with an easy to use interface and additional features. 23 | It will save your settings dynamically or you can restore the default settings. The default settings will download the a single subtitle file in english. This was, in my opinion, the mostly used setting. 24 | 25 | 26 | # Installation Guide 27 | 28 | Sub It will check if the dependencies that it needs are installed. If not all dependencies are installed, there will be a package icon in the main window that you can click. This button will load a simple installation guide that will guide you through the installation of the missing dependencies. If a dependency is already installed on your Mac, than the guide will not show this to avoid over complicating it. 29 | 30 | 31 | # THANKS 32 | 33 | Thanks to [Subliminal](http://subliminal.readthedocs.io/en/latest/) developers for creating such an amazing tool. 34 | -------------------------------------------------------------------------------- /Sub It/InstallationGuideTexts.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InstallationGuideTexts.swift 3 | // Sub It 4 | // 5 | // Created by Kevin De Koninck on 05/02/2017. 6 | // Copyright © 2017 Kevin De Koninck. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | let PAGES = ["intro","xcode","brew","python","sub","finish"] 12 | 13 | let TITLE:[String:String] = ["intro":"Introduction", 14 | "xcode":"Xcode Command Line Tools", 15 | "brew":"Homebrew", 16 | "python":"Python interpreter", 17 | "sub":"Subliminal", 18 | "finish":"It's over now. It's done."] 19 | 20 | let BODY:[String:String] = ["intro":"Before you can use Sub It, we must install some dependencies. This guide will assist you with installing these dependencies.\n\nThe dependencies that we will install (if not already installed) are:\n - Homebrew\n - Python 3\n - Subliminal.", 21 | "xcode":"Xcode development tools are some handy tools that are always nice to have on your system. Xcode is a large suite of software development tools and libraries from Apple.\nInstallation of many common Unix-based tools requires the GCC compiler. The Xcode Command Line Tools include a GCC compiler.\n\nTo install the Xcode command line tools, just press the 'Install' button below and follow the guide that will pop up.", 22 | "brew":"Homebrew is the missing package manager for macOS which we'll be using Homebrew to install all the software that is needed for Get It.\n\nTo install brew, copy the following command (green text), press the button 'Open the Terminal app' and paste the command in the terminal app. Then press enter, wait a bit and press enter again. Enter your password when the installer asks for it.\nWhen the installation has finished, you may close the Terminal app.", 23 | "python":"Our core program requires the python 3 interpreter to operate.\n\nTo install Python 3, just press the 'Install' button below.", 24 | "sub":"Subliminal is the core program of Sub It. It's an open-source command line tool that handles the downloading of our subtitles.\n\nTo install Subliminal, just press the 'Install' button below.", 25 | "finish":"If you executed eveything correctly, then your installation is completed. \n\nYou may close this window (and the Terminal app) now and click on the little blue refresh icon (like the one below) to reload all software.\n\nThen you're good to go!"] 26 | 27 | let INSTALLATION_COMMANDS:[String:String] = ["intro":"", 28 | "xcode":"xcode-select --install", 29 | "brew":"/usr/bin/ruby -e \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)\"", 30 | "python":"brew install python3", 31 | "sub":"brew install subliminal", //TODO install Sven zijn repo 32 | "finish":""] 33 | -------------------------------------------------------------------------------- /Sub It/SubIt.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SubIt.swift 3 | // Sub It 4 | // 5 | // Created by Kevin De Koninck on 28/01/2017. 6 | // Copyright © 2017 Kevin De Koninck. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class SubIt { 12 | var isSubliminalInstalled: Bool = false 13 | var isBrewInstalled: Bool = false 14 | var isPythonInstalled: Bool = false 15 | var isXcodeInstalled: Bool = false 16 | 17 | init() { 18 | //Get installed software 19 | //This is needed for the installation guide 20 | if let installed = UserDefaults.standard.value(forKey: SUBLIMINAL) as? String { 21 | self.isSubliminalInstalled = installed == "true" ? true : false 22 | } else { 23 | self.isSubliminalInstalled = false 24 | } 25 | 26 | if let installed = UserDefaults.standard.value(forKey: BREW) as? String { 27 | self.isBrewInstalled = installed == "true" ? true : false 28 | } else { 29 | self.isBrewInstalled = false 30 | } 31 | 32 | if let installed = UserDefaults.standard.value(forKey: PYTHON) as? String { 33 | self.isPythonInstalled = installed == "true" ? true : false 34 | } else { 35 | self.isPythonInstalled = false 36 | } 37 | 38 | if let installed = UserDefaults.standard.value(forKey: XCODE) as? String { 39 | self.isXcodeInstalled = installed == "true" ? true : false 40 | } else { 41 | self.isXcodeInstalled = false 42 | } 43 | } 44 | 45 | 46 | func getCommand() -> String { 47 | if let cmd = UserDefaults.standard.value(forKey: SAVED_COMMAND) as? String { 48 | return cmd + " " 49 | } else { 50 | return DEFAULT_COMMAND + " " 51 | } 52 | } 53 | 54 | func getOutputPath() -> String { 55 | if let path = UserDefaults.standard.value(forKey: OUTPUT_PATH) as? String { 56 | return path + "/" 57 | } else { 58 | return DEFAULT_SETTINGS["path"]! + "/" 59 | } 60 | } 61 | 62 | 63 | func open(folder: String){ 64 | _ = self.execute(commandSynchronous: "open \(folder)") 65 | } 66 | 67 | 68 | func execute(commandSynchronous: String) -> String { 69 | var arguments:[String] = [] 70 | arguments.append("-c") 71 | arguments.append( commandSynchronous ) 72 | 73 | let task = Process() 74 | task.launchPath = "/bin/sh" 75 | task.arguments = arguments 76 | 77 | let pipe = Pipe() 78 | task.standardOutput = pipe 79 | task.standardError = pipe 80 | task.launch() 81 | task.waitUntilExit() 82 | let data = pipe.fileHandleForReading.readDataToEndOfFile() 83 | 84 | return(NSString(data: data, encoding: String.Encoding.utf8.rawValue) as! String) 85 | } 86 | 87 | 88 | func checkIfSoftwareIsInstalled(){ 89 | var result = self.execute(commandSynchronous: "export PATH=$PATH:/usr/local/bin && if brew ls --versions subliminal > /dev/null; then echo INSTALLED; else echo NOT INSTALLED; fi") 90 | var temp = result.components(separatedBy: "\n") 91 | isSubliminalInstalled = temp[0] == "INSTALLED" ? true : false 92 | 93 | result = self.execute(commandSynchronous: "export PATH=$PATH:/usr/local/bin && [ ! -f \"`which brew`\" ] && echo NOT INSTALLED") 94 | temp = result.components(separatedBy: "\n") 95 | isBrewInstalled = temp[0] == "NOT INSTALLED" ? false : true 96 | 97 | result = self.execute(commandSynchronous: "export PATH=$PATH:/usr/local/bin && if brew ls --versions python3 > /dev/null; then echo INSTALLED; else echo NOT INSTALLED; fi") 98 | temp = result.components(separatedBy: "\n") 99 | isPythonInstalled = temp[0] == "INSTALLED" ? true : false 100 | 101 | result = self.execute(commandSynchronous: "export PATH=$PATH:/usr/local/bin && [ ! -f \"`which xcode-select`\" ] && echo NOT INSTALLED") 102 | temp = result.components(separatedBy: "\n") 103 | isXcodeInstalled = temp[0] == "NOT INSTALLED" ? false : true 104 | 105 | //save it so we can use it everywhere (installation guide) 106 | UserDefaults.standard.setValue("\(isBrewInstalled)", forKey: BREW) 107 | UserDefaults.standard.setValue("\(isPythonInstalled)", forKey: PYTHON) 108 | UserDefaults.standard.setValue("\(isXcodeInstalled)", forKey: XCODE) 109 | UserDefaults.standard.synchronize() 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /Sub It/dropView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // dropView.swift 3 | // Sub It 4 | // 5 | // Created by Kevin De Koninck on 12/02/2017. 6 | // Copyright © 2017 Kevin De Koninck. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class DropView: NSView { 12 | 13 | 14 | var filePaths = [String]() 15 | let expectedExt = ["AVI","FLV","WMV","MP4","MOV","MKV","QT","HEVC","DIVX","XVID"] // file extensions allowed fornDropping 16 | let backgroundColor = NSColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.05).cgColor 17 | 18 | private var allowedArray = [Bool]() 19 | 20 | required init?(coder: NSCoder) { 21 | super.init(coder: coder) 22 | 23 | register(forDraggedTypes: [NSFilenamesPboardType, NSURLPboardType]) 24 | } 25 | 26 | override func draw(_ dirtyRect: NSRect) { 27 | super.draw(dirtyRect) 28 | self.wantsLayer = true 29 | self.layer?.backgroundColor = backgroundColor 30 | 31 | // dash customization parameters 32 | let dashHeight: CGFloat = 5 33 | let dashLength: CGFloat = 10 34 | let dashColor = NSColor.gray 35 | 36 | // setup the context 37 | let currentContext = NSGraphicsContext.current()!.cgContext 38 | currentContext.setLineWidth(dashHeight) 39 | currentContext.setLineDash(phase: 0, lengths: [dashLength]) 40 | currentContext.setStrokeColor(dashColor.cgColor) 41 | 42 | // draw the dashed path 43 | currentContext.addRect(bounds.insetBy(dx: dashHeight-dashHeight/2, dy: dashHeight-dashHeight/2)) 44 | currentContext.strokePath() 45 | } 46 | 47 | override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation { 48 | 49 | //Reset on new drag 50 | self.allowedArray = [Bool]() 51 | self.filePaths = [String]() 52 | 53 | if checkExtension(sender) == true { 54 | self.layer?.backgroundColor = NSColor(red: 50.0/255, green: 140.0/255, blue: 255.0/255, alpha: 0.2).cgColor 55 | return .copy 56 | } else { 57 | self.layer?.backgroundColor = NSColor(red: 255.0/255, green: 0.0/255, blue: 0.0/255, alpha: 0.2).cgColor 58 | return NSDragOperation() 59 | } 60 | } 61 | 62 | fileprivate func checkExtension(_ drag: NSDraggingInfo) -> Bool { 63 | guard let board = drag.draggingPasteboard().propertyList(forType: "NSFilenamesPboardType") as? NSArray, 64 | let paths = board as? [String] 65 | else { return false } 66 | 67 | for path in paths { 68 | var isAllowed = false 69 | var isDir: ObjCBool = false 70 | let fm = FileManager() 71 | if fm.fileExists(atPath: path, isDirectory: &isDir) { 72 | if(isDir.boolValue){ 73 | isAllowed = true 74 | } else { 75 | let suffix = URL(fileURLWithPath: path).pathExtension 76 | for ext in self.expectedExt { 77 | if ext.lowercased() == suffix { 78 | isAllowed = true 79 | } 80 | } 81 | } 82 | } 83 | allowedArray.append(isAllowed) 84 | } 85 | 86 | //If one element is allowed, pass everything (we'll handle this un-allowed file later) 87 | for check in allowedArray { if check { return true } } 88 | return false 89 | 90 | } 91 | 92 | override func draggingExited(_ sender: NSDraggingInfo?) { 93 | self.layer?.backgroundColor = backgroundColor 94 | } 95 | 96 | override func draggingEnded(_ sender: NSDraggingInfo?) { 97 | self.layer?.backgroundColor = backgroundColor 98 | } 99 | 100 | override func performDragOperation(_ sender: NSDraggingInfo) -> Bool { 101 | guard let pasteboard = sender.draggingPasteboard().propertyList(forType: "NSFilenamesPboardType") as? NSArray, 102 | let paths = pasteboard as? [String] 103 | else { return false } 104 | 105 | var index = 0 106 | for path in paths { 107 | 108 | //Append path to array if the file type was allowed 109 | if allowedArray[index] { 110 | self.filePaths.append(path) 111 | } 112 | index = index + 1 113 | } 114 | 115 | //post notification 116 | NotificationCenter.default.post(NSNotification(name: NSNotification.Name(rawValue: "somethingWasDropped"), object: nil) as Notification) 117 | 118 | return true 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Pods/LetsMove/README.md: -------------------------------------------------------------------------------- 1 | LetsMove 2 | ======== 3 | 4 | A sample project that demonstrates how to move a running Mac OS X application to the Applications folder. 5 | 6 | ![Screenshot](http://i.imgur.com/euTRZiI.png) 7 | 8 | 9 | Requirements 10 | ------------ 11 | Builds and runs on Mac OS X 10.6 or higher. Does NOT support sandboxed applications. 12 | 13 | 14 | Usage 15 | ----- 16 | 17 | Option 1: 18 | 19 | Build then embed LetsMove.framework into your app. 20 | 21 | Option 2: 22 | 23 | Copy the following files into your project: 24 | 25 | - PFMoveApplication.h 26 | - PFMoveApplication.m 27 | 28 | If your project has ARC enabled, you'll want to disable ARC on the above files. You can do so by adding -fno-objc-arc compiler flag to your PFMoveApplication.m source file. See http://stackoverflow.com/questions/6646052/how-can-i-disable-arc-for-a-single-file-in-a-project/6658549#6658549 29 | 30 | If your application is localized, also copy the 'MoveApplication.string' files into your project. 31 | 32 | Link your application against Security.framework. 33 | 34 | In your app delegate's "-[applicationWillFinishLaunching:]" method, call the PFMoveToApplicationsFolderIfNecessary function at the very top. 35 | 36 | 37 | License 38 | ------- 39 | Public domain 40 | 41 | 42 | 43 | Version History 44 | --------------- 45 | 46 | * 1.22 47 | - Fix not deleting or trashing itself after copying to /Applications in macOS Sierra 48 | 49 | * 1.21 50 | - Support for [Carthage](https://github.com/Carthage/Carthage) added 51 | - Project now support OS X 10.6 and higher 52 | 53 | * 1.20 54 | - Support for applications bundled inside another application 55 | - Brazilian Portuguese localization slightly updated 56 | - Build warnings fixed 57 | 58 | * 1.19 59 | - Slovak localization added 60 | 61 | * 1.18 62 | - Catalan localization added 63 | 64 | * 1.17 65 | - Tranditional Chinese localization added. 66 | 67 | * 1.16 68 | - Deprecation warning that appears when minimum deployment target is set to OS X 10.10 taken care of 69 | 70 | * 1.15 71 | - Swedish localization added 72 | 73 | * 1.14 74 | - Hugarian, Serbian, and Turkish localizations added 75 | - Macedonian localization added 76 | 77 | * 1.13 78 | - Polish localization added 79 | 80 | * 1.12 81 | - Use country code based .lproj directories 82 | - Make it compile for projects that don't use precompiled headers to import AppKit.framework 83 | - Minor adjustment to Dutch localization 84 | - Warning fixes in example project 85 | 86 | * 1.11 87 | - Objective-C++ compatibility 88 | 89 | * 1.10 90 | - Fixed deprecation warnings that show up when building against the OS X 10.9 SDK. 91 | 92 | * 1.9 93 | - Removed OS X 10.4 support 94 | - Properly detect if the running app is in a disk image 95 | - Fixed a bug where if the app's name contained a quote, the app could not be moved 96 | - After a successful move, delete the application instead of moving it to the Trash. 97 | - Other fixes and improvements 98 | 99 | * 1.8 100 | - If the app is already there in the Applications folder but not writable, request authentication from user 101 | - Added Korean localization 102 | 103 | * 1.7.2 104 | - Fixed an exception that could happen. 105 | 106 | * 1.7.1 107 | - Refactoring 108 | 109 | * 1.7 110 | - Only move to ~/Appilcations directory if an app is already in there. 111 | 112 | * 1.6.3 113 | - Function calls deprecated in 10.7 no longer cause compile time warnings. 114 | - Added Simplified Chinese and European Portuguese localizations 115 | 116 | * 1.6.2 117 | - Garbage collection compatibility added 118 | - Use a new method to check if an application is already running on Mac OS X 10.6 systems or higher 119 | 120 | * 1.6.1 121 | - Use exit(0) to terminate the app before relaunching instead of [NSApp terminate:]. We don't want applicationShouldTerminate or applicationWillTerminate NSApplication delegate methods to be called, possibly introducing side effects. 122 | 123 | * 1.6 124 | - Resolve any aliases when finding the Applications directory 125 | 126 | * 1.5.2 127 | - Cleaned up the code a bit. Almost functionally equivalent to 1.5.1. 128 | 129 | * 1.5.1 130 | - Fixed a bug with clearing the quarantine file attribute on Mac OS X 10.5 131 | 132 | * 1.5 133 | - Don't prompt to move the application if it has "Applications" in its path somewhere 134 | 135 | * 1.4 136 | - Mac OS X 10.5 compatibility fixes 137 | 138 | * 1.3 139 | - Fixed a rare bug in the shell script that checks to see if the app is already running 140 | - Clear quarantine flag after copying 141 | - Compile time option to show normal sized alert supress checkbox button 142 | - German, Danish, and Norwegian localizations added 143 | 144 | * 1.2 145 | - Copy application from disk image then unmount disk image 146 | - Spanish, French, Dutch, and Russian localizations 147 | 148 | * 1.1 149 | - Prefers ~/Applications over /Applications if it exists 150 | - Escape key pushes the "Do Not Move" button 151 | 152 | * 1.0 153 | - First release 154 | 155 | 156 | Code Contributors: 157 | ------------- 158 | * Andy Kim 159 | * John Brayton 160 | * Chad Sellers 161 | * Kevin LaCoste 162 | * Rasmus Andersson 163 | * Timothy J. Wood 164 | * Matt Gallagher 165 | * Whitney Young 166 | * Nick Moore 167 | * Nicholas Riley 168 | * Matt Prowse 169 | 170 | 171 | Translators: 172 | ------------ 173 | * Eita Hayashi (Japanese) 174 | * Gleb M. Borisov (Russian) 175 | * Wouter Broekhof (Dutch) 176 | * Rasmus Andersson / Spotify (French and Spanish) 177 | * Markus Kirschner (German) 178 | * Fredrik Nannestad (Danish) 179 | * Georg Alexander Bøe (Norwegian) 180 | * Marco Improda (Italian) 181 | * Venj Chu (Simplified Chinese) 182 | * Sérgio Miranda (European Portuguese) 183 | * Victor Figueiredo and BR Lingo (Brazilian Portuguese) 184 | * AppLingua (Korean) 185 | * Czech X Team (Czech) 186 | * Marek Telecki (Polish) 187 | * Petar Vlahu (Macedonian) 188 | * Václav Slavík (Hungarian, Serbian, and Turkish) 189 | * Erik Vikström (Swedish) 190 | * Inndy Lin (Traditional Chinese) 191 | * aONe (Catalan) 192 | * Marek Hrusovsky (Slovak) 193 | 194 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 195 | -------------------------------------------------------------------------------- /Sub It/InstallationGuideViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InstallationGuideViewController.swift 3 | // Sub It 4 | // 5 | // Created by Kevin De Koninck on 05/02/2017. 6 | // Copyright © 2017 Kevin De Koninck. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class InstallationGuideViewController: NSViewController { 12 | 13 | var subIt = SubIt() 14 | 15 | /* 16 | * Dictoinary title ("intro" : "introduction", "brew" : "Homebrew", ...) 17 | bodyText ("intro : "welcome to ..." , "brew" : "we will ...", ...) 18 | ... 19 | 20 | * variabele page: Int = 0 21 | variable pages = ["intro", "brew", ...] 22 | 23 | * bodytext = bodyTextDict(pages[page]) 24 | 25 | * if clicked previeous: page = page - 1 (if page > 0) 26 | 27 | etc 28 | */ 29 | 30 | @IBOutlet weak var nextPageBtn: NSButton! 31 | @IBOutlet weak var previousPageBtn: NSButton! 32 | @IBOutlet weak var bodyText: NSTextField! 33 | @IBOutlet weak var commandTextField: optionsTextfield! 34 | @IBOutlet weak var titleText: NSTextField! 35 | @IBOutlet weak var refreshImage: NSButton! 36 | @IBOutlet weak var openTerminalButton: NSButton! 37 | @IBOutlet weak var installButton: installButton! 38 | 39 | var currentPage: Int = 0 //intro 40 | 41 | override func viewDidLoad() { 42 | super.viewDidLoad() 43 | self.view.wantsLayer = true 44 | 45 | previousPageBtn.isHidden = true 46 | refreshImage.isHidden = true 47 | currentPage = 0 48 | displayPage() 49 | 50 | //TODO remove 51 | // 52 | // print(getIt.isXcodeInstalled) 53 | // print(getIt.isBrewInstalled) 54 | // print(getIt.isPythonInstalled) 55 | // print(getIt.isYTDLInstalled) 56 | // 57 | // getIt.isXcodeInstalled = false 58 | // getIt.isPythonInstalled = false 59 | // getIt.isBrewInstalled = false 60 | } 61 | 62 | override func awakeFromNib() { 63 | if self.view.layer != nil { 64 | let color : CGColor = CGColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0) 65 | self.view.layer?.backgroundColor = color 66 | } 67 | } 68 | 69 | 70 | func displayPage() { 71 | installButton.isEnabled = true 72 | switch currentPage { 73 | case 0: 74 | previousPageBtn.isHidden = true 75 | nextPageBtn.isHidden = false 76 | commandTextField.isHidden = true 77 | refreshImage.isHidden = true 78 | openTerminalButton.isHidden = true 79 | installButton.isHidden = true 80 | case 2: 81 | previousPageBtn.isHidden = false 82 | nextPageBtn.isHidden = false 83 | commandTextField.isHidden = false 84 | refreshImage.isHidden = true 85 | openTerminalButton.isHidden = false 86 | installButton.isHidden = true 87 | case 5: 88 | previousPageBtn.isHidden = false 89 | nextPageBtn.isHidden = true 90 | commandTextField.isHidden = true 91 | refreshImage.isHidden = false 92 | openTerminalButton.isHidden = true 93 | installButton.isHidden = true 94 | default: 95 | previousPageBtn.isHidden = false 96 | nextPageBtn.isHidden = false 97 | commandTextField.isHidden = true 98 | refreshImage.isHidden = true 99 | openTerminalButton.isHidden = true 100 | installButton.isHidden = false 101 | } 102 | 103 | titleText.stringValue = TITLE[PAGES[currentPage]]! 104 | bodyText.stringValue = BODY[PAGES[currentPage]]! 105 | commandTextField.stringValue = INSTALLATION_COMMANDS[PAGES[currentPage]]! 106 | } 107 | @IBAction func openTerminalButtonClicked(_ sender: Any) { 108 | _ = subIt.execute(commandSynchronous: "open /Applications/Utilities/Terminal.app") 109 | } 110 | 111 | @IBAction func installBtnClicked(_ sender: Any) { 112 | var cmd = "" 113 | 114 | switch currentPage { 115 | case 1: cmd = "export PATH=$PATH:/usr/local/bin && " + INSTALLATION_COMMANDS["xcode"]! 116 | case 3: cmd = "export PATH=$PATH:/usr/local/bin && " + INSTALLATION_COMMANDS["python"]! 117 | default: cmd = "export PATH=$PATH:/usr/local/bin && " + INSTALLATION_COMMANDS["ytdl"]! 118 | } 119 | 120 | //DJProgressHUD.showStatus(" Installing\nPlease wait...", from: self.view) 121 | _ = subIt.execute(commandSynchronous: cmd) 122 | //DJProgressHUD.dismiss() 123 | installButton.isEnabled = false 124 | } 125 | 126 | @IBAction func nextPageBtnClicked(_ sender: Any) { 127 | 128 | if(currentPage == 0 && subIt.isXcodeInstalled && subIt.isBrewInstalled && subIt.isPythonInstalled) { currentPage = 4 } 129 | else if(currentPage == 0 && subIt.isXcodeInstalled && subIt.isBrewInstalled) { currentPage = 3 } 130 | else if(currentPage == 0 && subIt.isXcodeInstalled) { currentPage = 2 } 131 | else if(currentPage == 1 && subIt.isBrewInstalled && subIt.isPythonInstalled) { currentPage = 4 } 132 | else if(currentPage == 1 && subIt.isBrewInstalled) { currentPage = 3 } 133 | else if(currentPage == 2 && subIt.isPythonInstalled) { currentPage = 4 } 134 | else{ currentPage = currentPage + 1 } 135 | 136 | displayPage() 137 | } 138 | 139 | @IBAction func previousPageBtnClicked(_ sender: Any) { 140 | 141 | if(currentPage == 4 && subIt.isXcodeInstalled && subIt.isBrewInstalled && subIt.isPythonInstalled) { currentPage = 0 } 142 | else if(currentPage == 4 && subIt.isPythonInstalled && subIt.isBrewInstalled) { currentPage = 1 } 143 | else if(currentPage == 4 && subIt.isPythonInstalled) { currentPage = 2 } 144 | else if(currentPage == 3 && subIt.isXcodeInstalled && subIt.isBrewInstalled) { currentPage = 0 } 145 | else if(currentPage == 3 && subIt.isBrewInstalled) { currentPage = 1 } 146 | else if(currentPage == 2 && subIt.isXcodeInstalled) { currentPage = 0 } 147 | else{ currentPage = currentPage - 1 } 148 | 149 | displayPage() 150 | } 151 | 152 | 153 | 154 | } 155 | -------------------------------------------------------------------------------- /Sub It/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Sub It 4 | // 5 | // Created by Kevin De Koninck on 23/05/16. 6 | // Copyright © 2016 Kevin De Koninck. All rights reserved. 7 | // 8 | 9 | //TODO: regex check for urls in input field 10 | 11 | 12 | import Cocoa 13 | 14 | class ViewController: NSViewController { 15 | 16 | @IBOutlet weak var settingsBtn: NSButton! 17 | @IBOutlet weak var installationGuideBtn: NSButton! 18 | @IBOutlet weak var refreshInstallationBtn: NSButton! 19 | @IBOutlet weak var drop: DropView! 20 | 21 | @IBOutlet weak var logoBtn: NSButton! 22 | 23 | @IBOutlet weak var progressView: ProgressView! 24 | @IBOutlet weak var progressTitle: NSTextField! 25 | @IBOutlet weak var progressDetails: NSTextField! 26 | 27 | 28 | //global variables 29 | var subIt = SubIt() 30 | 31 | override func awakeFromNib() { 32 | if self.view.layer != nil { 33 | let color : CGColor = CGColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0) 34 | self.view.layer?.backgroundColor = color 35 | } 36 | } 37 | 38 | override func viewDidLoad() { 39 | super.viewDidLoad() 40 | 41 | NotificationCenter.default.addObserver(self, selector: #selector(openSettingsView), name: NSNotification.Name(rawValue: "openSettingsView"), object: nil) 42 | NotificationCenter.default.addObserver(self, selector: #selector(somethingWasDropped), name: NSNotification.Name(rawValue: "somethingWasDropped"), object: nil) 43 | 44 | dismissProgressIndicator() 45 | } 46 | func openSettingsView(notif: AnyObject) { 47 | self.performSegue(withIdentifier: "settingsSegue", sender: self) 48 | } 49 | 50 | func somethingWasDropped(notif: AnyObject) { 51 | var command = subIt.getCommand() 52 | for path in drop.filePaths { command += "'" + path + "' " } 53 | execute(commmandAsynchronous: command) 54 | } 55 | 56 | override func viewWillAppear() { 57 | super.viewWillAppear() 58 | 59 | subIt.checkIfSoftwareIsInstalled() 60 | installationGuideViewSetUp(activate: !subIt.isSubliminalInstalled) 61 | // installationGuideViewSetUp(activate: true) //TODO - remove (is for testing purposes) 62 | } 63 | 64 | func installationGuideViewSetUp(activate: Bool) { 65 | settingsBtn.isEnabled = !activate 66 | drop.isHidden = activate 67 | installationGuideBtn.isEnabled = activate 68 | installationGuideBtn.isHidden = !activate 69 | refreshInstallationBtn.isEnabled = activate 70 | refreshInstallationBtn.isHidden = !activate 71 | } 72 | 73 | @IBAction func refreshInstallationBtnClicked(_ sender: Any) { 74 | subIt.checkIfSoftwareIsInstalled() 75 | installationGuideViewSetUp(activate: !subIt.isSubliminalInstalled) 76 | // installationGuideViewSetUp(activate: true) //TODO - remove (is for testing purposes) 77 | } 78 | 79 | func enableAll(enabled: Bool){ 80 | settingsBtn.isEnabled = enabled 81 | logoBtn.isEnabled = enabled 82 | } 83 | 84 | func showProgressIndicator(title: String, details: String) { 85 | self.enableAll(enabled: false) 86 | progressTitle.stringValue = title 87 | progressDetails.stringValue = details 88 | progressView.isHidden = false 89 | progressTitle.isHidden = false 90 | progressDetails.isHidden = false 91 | } 92 | 93 | func dismissProgressIndicator() { 94 | self.enableAll(enabled: true) 95 | progressView.isHidden = true 96 | progressTitle.isHidden = true 97 | progressDetails.isHidden = true 98 | } 99 | 100 | func execute(commmandAsynchronous: String){ 101 | 102 | //Prepare command 103 | var arguments:[String] = [] 104 | arguments.append("-c") 105 | arguments.append( commmandAsynchronous ) 106 | print( commmandAsynchronous ) 107 | 108 | //Start execution of command 109 | let task = Process() 110 | task.launchPath = "/bin/sh" 111 | task.arguments = arguments 112 | 113 | let pipe = Pipe() 114 | task.standardOutput = pipe 115 | let outHandle = pipe.fileHandleForReading 116 | outHandle.waitForDataInBackgroundAndNotify() 117 | 118 | var obs1 : NSObjectProtocol! 119 | obs1 = NotificationCenter.default.addObserver(forName: NSNotification.Name.NSFileHandleDataAvailable, object: outHandle, queue: nil) { notification -> Void in 120 | let data = outHandle.availableData 121 | if data.count > 0 { 122 | if let s = NSString(data: data, encoding: String.Encoding.utf8.rawValue) { 123 | //RECEIVED OUTPUT 124 | let receivedStr = s.components(separatedBy: "\n")[0] 125 | var str = receivedStr.replacingOccurrences(of: "/ ", with: "\n") 126 | 127 | print(str) 128 | 129 | //After we receive "1 video collected / 0 video ignored / 0 error" we start downloading 130 | if(receivedStr != str){ str = "Downloading subtitles" } 131 | 132 | //After we receive something that starts with "downloaded" then we 'freeze' the output for a couple of seconds 133 | if(String(str.characters.prefix(4)) == "Some") { } // ignore messages that start with 'some' 134 | else if(String(str.characters.prefix(10)) == "Downloaded"){ 135 | self.showProgressIndicator(title: "Finished!", details: str) 136 | DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(3), execute: { 137 | self.dismissProgressIndicator() 138 | }) 139 | //otherwise we just output the received text 140 | } else { 141 | self.showProgressIndicator(title: str, details: "") 142 | } 143 | } 144 | outHandle.waitForDataInBackgroundAndNotify() 145 | } else { 146 | //EOF ON STDOUT FROM PROCESS 147 | NotificationCenter.default.removeObserver(obs1) 148 | } 149 | } 150 | 151 | var obs2 : NSObjectProtocol! 152 | obs2 = NotificationCenter.default.addObserver(forName: Process.didTerminateNotification, object: task, queue: nil) { notification -> Void in 153 | NotificationCenter.default.removeObserver(obs2) 154 | } 155 | 156 | task.launch() 157 | } 158 | 159 | } 160 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Sub It/Pods-Sub It-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then 7 | # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # resources to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 13 | 14 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 15 | > "$RESOURCES_TO_COPY" 16 | 17 | XCASSET_FILES=() 18 | 19 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 20 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 21 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 22 | 23 | case "${TARGETED_DEVICE_FAMILY:-}" in 24 | 1,2) 25 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 26 | ;; 27 | 1) 28 | TARGET_DEVICE_ARGS="--target-device iphone" 29 | ;; 30 | 2) 31 | TARGET_DEVICE_ARGS="--target-device ipad" 32 | ;; 33 | 3) 34 | TARGET_DEVICE_ARGS="--target-device tv" 35 | ;; 36 | 4) 37 | TARGET_DEVICE_ARGS="--target-device watch" 38 | ;; 39 | *) 40 | TARGET_DEVICE_ARGS="--target-device mac" 41 | ;; 42 | esac 43 | 44 | install_resource() 45 | { 46 | if [[ "$1" = /* ]] ; then 47 | RESOURCE_PATH="$1" 48 | else 49 | RESOURCE_PATH="${PODS_ROOT}/$1" 50 | fi 51 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 52 | cat << EOM 53 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 54 | EOM 55 | exit 1 56 | fi 57 | case $RESOURCE_PATH in 58 | *.storyboard) 59 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 60 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 61 | ;; 62 | *.xib) 63 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 64 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 65 | ;; 66 | *.framework) 67 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 68 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 69 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 70 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 71 | ;; 72 | *.xcdatamodel) 73 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 74 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 75 | ;; 76 | *.xcdatamodeld) 77 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 78 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 79 | ;; 80 | *.xcmappingmodel) 81 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 82 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 83 | ;; 84 | *.xcassets) 85 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 86 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 87 | ;; 88 | *) 89 | echo "$RESOURCE_PATH" || true 90 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 91 | ;; 92 | esac 93 | } 94 | 95 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 96 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 97 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 98 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 99 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 100 | fi 101 | rm -f "$RESOURCES_TO_COPY" 102 | 103 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] 104 | then 105 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 106 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 107 | while read line; do 108 | if [[ $line != "${PODS_ROOT}*" ]]; then 109 | XCASSET_FILES+=("$line") 110 | fi 111 | done <<<"$OTHER_XCASSETS" 112 | 113 | if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then 114 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 115 | else 116 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_BUILD_DIR}/assetcatalog_generated_info.plist" 117 | fi 118 | fi 119 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Sub It/Pods-Sub It-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then 7 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # frameworks to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 13 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 14 | 15 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" 16 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 17 | 18 | # Used as a return value for each invocation of `strip_invalid_archs` function. 19 | STRIP_BINARY_RETVAL=0 20 | 21 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 22 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 23 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 24 | 25 | # Copies and strips a vendored framework 26 | install_framework() 27 | { 28 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 29 | local source="${BUILT_PRODUCTS_DIR}/$1" 30 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 31 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 32 | elif [ -r "$1" ]; then 33 | local source="$1" 34 | fi 35 | 36 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 37 | 38 | if [ -L "${source}" ]; then 39 | echo "Symlinked..." 40 | source="$(readlink "${source}")" 41 | fi 42 | 43 | # Use filter instead of exclude so missing patterns don't throw errors. 44 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 45 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 46 | 47 | local basename 48 | basename="$(basename -s .framework "$1")" 49 | binary="${destination}/${basename}.framework/${basename}" 50 | if ! [ -r "$binary" ]; then 51 | binary="${destination}/${basename}" 52 | fi 53 | 54 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 55 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 56 | strip_invalid_archs "$binary" 57 | fi 58 | 59 | # Resign the code if required by the build settings to avoid unstable apps 60 | code_sign_if_enabled "${destination}/$(basename "$1")" 61 | 62 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 63 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 64 | local swift_runtime_libs 65 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 66 | for lib in $swift_runtime_libs; do 67 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 68 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 69 | code_sign_if_enabled "${destination}/${lib}" 70 | done 71 | fi 72 | } 73 | 74 | # Copies and strips a vendored dSYM 75 | install_dsym() { 76 | local source="$1" 77 | if [ -r "$source" ]; then 78 | # Copy the dSYM into a the targets temp dir. 79 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 80 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 81 | 82 | local basename 83 | basename="$(basename -s .framework.dSYM "$source")" 84 | binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" 85 | 86 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 87 | if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then 88 | strip_invalid_archs "$binary" 89 | fi 90 | 91 | if [[ $STRIP_BINARY_RETVAL == 1 ]]; then 92 | # Move the stripped file into its final destination. 93 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 94 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 95 | else 96 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 97 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" 98 | fi 99 | fi 100 | } 101 | 102 | # Signs a framework with the provided identity 103 | code_sign_if_enabled() { 104 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 105 | # Use the current code_sign_identitiy 106 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 107 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" 108 | 109 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 110 | code_sign_cmd="$code_sign_cmd &" 111 | fi 112 | echo "$code_sign_cmd" 113 | eval "$code_sign_cmd" 114 | fi 115 | } 116 | 117 | # Strip invalid architectures 118 | strip_invalid_archs() { 119 | binary="$1" 120 | # Get architectures for current target binary 121 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 122 | # Intersect them with the architectures we are building for 123 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 124 | # If there are no archs supported by this binary then warn the user 125 | if [[ -z "$intersected_archs" ]]; then 126 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 127 | STRIP_BINARY_RETVAL=0 128 | return 129 | fi 130 | stripped="" 131 | for arch in $binary_archs; do 132 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 133 | # Strip non-valid architectures in-place 134 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 135 | stripped="$stripped $arch" 136 | fi 137 | done 138 | if [[ "$stripped" ]]; then 139 | echo "Stripped $binary of architectures:$stripped" 140 | fi 141 | STRIP_BINARY_RETVAL=1 142 | } 143 | 144 | 145 | if [[ "$CONFIGURATION" == "Debug" ]]; then 146 | install_framework "${BUILT_PRODUCTS_DIR}/ITSwitch/ITSwitch.framework" 147 | install_framework "${BUILT_PRODUCTS_DIR}/LetsMove/LetsMove.framework" 148 | fi 149 | if [[ "$CONFIGURATION" == "Release" ]]; then 150 | install_framework "${BUILT_PRODUCTS_DIR}/ITSwitch/ITSwitch.framework" 151 | install_framework "${BUILT_PRODUCTS_DIR}/LetsMove/LetsMove.framework" 152 | fi 153 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 154 | wait 155 | fi 156 | -------------------------------------------------------------------------------- /Sub It/OptionsViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OptionsViewController.swift 3 | // Sub It 4 | // 5 | // Created by Kevin De Koninck on 28/01/2017. 6 | // Copyright © 2017 Kevin De Koninck. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | import ITSwitch 11 | 12 | class OptionsViewController: NSViewController { 13 | 14 | //Subtitles tab 15 | @IBOutlet weak var languageSubs1: NSPopUpButton! 16 | @IBOutlet weak var languageSubs2: NSPopUpButton! 17 | @IBOutlet weak var singleFile: ITSwitch! 18 | @IBOutlet weak var forceDownload: ITSwitch! 19 | @IBOutlet weak var preferHearingImpaired: ITSwitch! 20 | 21 | //Others tab 22 | @IBOutlet weak var useFilter: ITSwitch! 23 | @IBOutlet weak var seperateDownloadsFolder: ITSwitch! 24 | @IBOutlet weak var selectedPath: NSTextField! 25 | @IBOutlet weak var folderIcon: NSButton! 26 | 27 | //SubIt 28 | var subIt = SubIt() 29 | 30 | 31 | override func viewDidLoad() { 32 | super.viewDidLoad() 33 | self.view.wantsLayer = true 34 | 35 | //Switch color 36 | singleFile.tintColor = blueColor 37 | forceDownload.tintColor = blueColor 38 | preferHearingImpaired.tintColor = blueColor 39 | useFilter.tintColor = blueColor 40 | seperateDownloadsFolder.tintColor = blueColor 41 | 42 | loadSettingsAndSetElements() 43 | } 44 | 45 | @IBAction func seperateDownloadFolderSwitchClicked(_ sender: Any) { 46 | selectedPath.isHidden = !seperateDownloadsFolder.checked 47 | folderIcon.isHidden = !seperateDownloadsFolder.checked 48 | } 49 | 50 | override func awakeFromNib() { 51 | if self.view.layer != nil { 52 | let color : CGColor = CGColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0) 53 | self.view.layer?.backgroundColor = color 54 | } 55 | } 56 | 57 | override func viewWillDisappear() { 58 | super.viewWillDisappear() 59 | 60 | //we want to save the settings 61 | saveSettings() 62 | 63 | //Save the command 64 | UserDefaults.standard.setValue(createCommand(), forKey: SAVED_COMMAND) 65 | UserDefaults.standard.synchronize() 66 | } 67 | 68 | 69 | @IBAction func loadDefaultsBtnClicked(_ sender: Any) { 70 | UserDefaults.standard.set(DEFAULT_SETTINGS, forKey: SETTINGS_KEY) 71 | UserDefaults.standard.setValue(DEFAULT_SETTINGS["selectedPath"]!, forKey: OUTPUT_PATH) 72 | UserDefaults.standard.synchronize() 73 | loadSettingsAndSetElements() 74 | } 75 | 76 | 77 | func saveSettings() { 78 | var settingsDict = [String: String]() 79 | 80 | settingsDict["singleFile"] = String(singleFile.checked) == "true" ? "1" : "0" 81 | settingsDict["forceDownload"] = String(forceDownload.checked) == "true" ? "1" : "0" 82 | settingsDict["preferHearingImpaired"] = String(preferHearingImpaired.checked) == "true" ? "1" : "0" 83 | settingsDict["useFilter"] = String(useFilter.checked) == "true" ? "1" : "0" 84 | settingsDict["seperateDownloadsFolder"] = String(seperateDownloadsFolder.checked) == "true" ? "1" : "0" 85 | settingsDict["languageSubs1"] = String(languageSubs1.indexOfSelectedItem) 86 | settingsDict["languageSubs2"] = String(languageSubs2.indexOfSelectedItem) 87 | settingsDict["selectedPath"] = UserDefaults.standard.value(forKey: OUTPUT_PATH) as? String 88 | 89 | UserDefaults.standard.set(settingsDict, forKey: SETTINGS_KEY) 90 | UserDefaults.standard.synchronize() 91 | } 92 | 93 | 94 | func loadSettingsAndSetElements() { 95 | 96 | if let arr = UserDefaults.standard.value(forKey: SETTINGS_KEY) as? [String:String] { 97 | 98 | 99 | //Get and set all saved settings 100 | 101 | if arr["selectedPath"] != nil { 102 | if let temp = UserDefaults.standard.value(forKey: OUTPUT_PATH) as? String { 103 | selectedPath.stringValue = NSURL(fileURLWithPath: temp).lastPathComponent! 104 | } else { // BUG FIX 105 | UserDefaults.standard.setValue(DEFAULT_OUTPUTPATH, forKey: OUTPUT_PATH) 106 | UserDefaults.standard.synchronize() 107 | selectedPath.stringValue = NSURL(fileURLWithPath: DEFAULT_OUTPUTPATH).lastPathComponent! 108 | } 109 | } 110 | else { selectedPath.stringValue = DEFAULT_SETTINGS["selectedPath"]! } 111 | 112 | if let val = arr["singleFile"] { singleFile.checked = val == "1" ? true : false } 113 | else { singleFile.checked = DEFAULT_SETTINGS["singleFile"]! == "1" ? true : false } 114 | 115 | if let val = arr["forceDownload"] { forceDownload.checked = val == "1" ? true : false } 116 | else { forceDownload.checked = DEFAULT_SETTINGS["forceDownload"]! == "1" ? true : false } 117 | 118 | if let val = arr["preferHearingImpaired"] { preferHearingImpaired.checked = val == "1" ? true : false } 119 | else { preferHearingImpaired.checked = DEFAULT_SETTINGS["preferHearingImpaired"]! == "1" ? true : false } 120 | 121 | if let val = arr["useFilter"] { useFilter.checked = val == "1" ? true : false } 122 | else { useFilter.checked = DEFAULT_SETTINGS["useFilter"]! == "1" ? true : false } 123 | 124 | if let val = arr["seperateDownloadsFolder"] { seperateDownloadsFolder.checked = val == "1" ? true : false } 125 | else { seperateDownloadsFolder.checked = DEFAULT_SETTINGS["seperateDownloadsFolder"]! == "1" ? true : false } 126 | 127 | if let val = arr["languageSubs1"] { languageSubs1.selectItem(at: Int(val)!) } 128 | else { languageSubs1.selectItem(at: Int(DEFAULT_SETTINGS["languageSubs1"]!)!) } 129 | 130 | if let val = arr["languageSubs2"] { languageSubs2.selectItem(at: Int(val)!) } 131 | else { languageSubs2.selectItem(at: Int(DEFAULT_SETTINGS["languageSubs2"]!)!) } 132 | 133 | } else { 134 | // No saved settings?, save the defaults and retry 135 | UserDefaults.standard.setValue(DEFAULT_SETTINGS, forKey: SETTINGS_KEY) 136 | UserDefaults.standard.setValue(DEFAULT_OUTPUTPATH, forKey: OUTPUT_PATH) 137 | UserDefaults.standard.synchronize() 138 | loadSettingsAndSetElements() 139 | } 140 | 141 | selectedPath.isHidden = !seperateDownloadsFolder.checked 142 | folderIcon.isHidden = !seperateDownloadsFolder.checked 143 | } 144 | 145 | 146 | 147 | func createCommand() -> String { 148 | //Start of creating the command 149 | var command = "export PATH=$PATH:/usr/local/bin && subliminal download"; 150 | 151 | 152 | //Creating the command 153 | if singleFile.checked { command += " -s" } 154 | if forceDownload.checked { command += " -f" } 155 | if preferHearingImpaired.checked { command += " --hearing-impaired" } 156 | 157 | 158 | 159 | //TODO use filter 160 | 161 | //sed -i “regex” file.srt ? 162 | 163 | 164 | 165 | //seperate downloadsfolder 166 | if(seperateDownloadsFolder.checked){ command += " -d " + subIt.getOutputPath() } 167 | 168 | 169 | 170 | //languages 171 | if languageSubs1.selectedItem!.tag > 0 { 172 | var subLanguage = "" 173 | switch languageSubs1.selectedItem!.tag { 174 | case 1: subLanguage = "en" 175 | case 2: subLanguage = "gr" 176 | case 3: subLanguage = "pt" 177 | case 4: subLanguage = "fr" 178 | case 5: subLanguage = "it" 179 | case 6: subLanguage = "ru" 180 | case 7: subLanguage = "es" 181 | case 8: subLanguage = "de" 182 | case 9: subLanguage = "nl" 183 | default: subLanguage = "en" 184 | } 185 | command += " -l \(subLanguage)" 186 | } 187 | if languageSubs2.selectedItem!.tag > 0 { 188 | var subLanguage = "" 189 | switch languageSubs2.selectedItem!.tag { 190 | case 1: subLanguage = "en" 191 | case 2: subLanguage = "gr" 192 | case 3: subLanguage = "pt" 193 | case 4: subLanguage = "fr" 194 | case 5: subLanguage = "it" 195 | case 6: subLanguage = "ru" 196 | case 7: subLanguage = "es" 197 | case 8: subLanguage = "de" 198 | case 9: subLanguage = "nl" 199 | default: subLanguage = "en" 200 | } 201 | command += " -l \(subLanguage)" 202 | } 203 | 204 | return command 205 | } 206 | 207 | @IBAction func folderIconClicked(_ sender: Any) { 208 | let dialog = NSOpenPanel(); 209 | 210 | dialog.title = "Choose a folder" 211 | dialog.showsResizeIndicator = true 212 | dialog.showsHiddenFiles = false 213 | dialog.canChooseFiles = false 214 | dialog.canChooseDirectories = true 215 | dialog.canCreateDirectories = true 216 | dialog.allowsMultipleSelection = false 217 | 218 | if (dialog.runModal() == NSModalResponseOK) { 219 | let result = dialog.url 220 | if (result != nil) { 221 | let path = result!.path 222 | UserDefaults.standard.setValue(path, forKey: OUTPUT_PATH) 223 | UserDefaults.standard.synchronize() 224 | 225 | selectedPath.stringValue = NSURL(fileURLWithPath: path).lastPathComponent! 226 | } 227 | } 228 | 229 | //post notification to viewcontroller.swift to open the settingsview again (segue) 230 | NotificationCenter.default.post(NSNotification(name: NSNotification.Name(rawValue: "openSettingsView"), object: nil) as Notification) 231 | 232 | } 233 | 234 | 235 | 236 | @IBAction func clearCacheBtnClicked(_ sender: Any) { 237 | _ = subIt.execute(commandSynchronous: "export PATH=$PATH:/usr/local/bin && subliminal cache --clear-subliminal") 238 | } 239 | 240 | 241 | } 242 | -------------------------------------------------------------------------------- /Pods/ITSwitch/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2014 Ilija Tovilo 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Sub It/Pods-Sub It-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## ITSwitch 5 | 6 | Apache License 7 | Version 2.0, January 2004 8 | http://www.apache.org/licenses/ 9 | 10 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 11 | 12 | 1. Definitions. 13 | 14 | "License" shall mean the terms and conditions for use, reproduction, 15 | and distribution as defined by Sections 1 through 9 of this document. 16 | 17 | "Licensor" shall mean the copyright owner or entity authorized by 18 | the copyright owner that is granting the License. 19 | 20 | "Legal Entity" shall mean the union of the acting entity and all 21 | other entities that control, are controlled by, or are under common 22 | control with that entity. For the purposes of this definition, 23 | "control" means (i) the power, direct or indirect, to cause the 24 | direction or management of such entity, whether by contract or 25 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 26 | outstanding shares, or (iii) beneficial ownership of such entity. 27 | 28 | "You" (or "Your") shall mean an individual or Legal Entity 29 | exercising permissions granted by this License. 30 | 31 | "Source" form shall mean the preferred form for making modifications, 32 | including but not limited to software source code, documentation 33 | source, and configuration files. 34 | 35 | "Object" form shall mean any form resulting from mechanical 36 | transformation or translation of a Source form, including but 37 | not limited to compiled object code, generated documentation, 38 | and conversions to other media types. 39 | 40 | "Work" shall mean the work of authorship, whether in Source or 41 | Object form, made available under the License, as indicated by a 42 | copyright notice that is included in or attached to the work 43 | (an example is provided in the Appendix below). 44 | 45 | "Derivative Works" shall mean any work, whether in Source or Object 46 | form, that is based on (or derived from) the Work and for which the 47 | editorial revisions, annotations, elaborations, or other modifications 48 | represent, as a whole, an original work of authorship. For the purposes 49 | of this License, Derivative Works shall not include works that remain 50 | separable from, or merely link (or bind by name) to the interfaces of, 51 | the Work and Derivative Works thereof. 52 | 53 | "Contribution" shall mean any work of authorship, including 54 | the original version of the Work and any modifications or additions 55 | to that Work or Derivative Works thereof, that is intentionally 56 | submitted to Licensor for inclusion in the Work by the copyright owner 57 | or by an individual or Legal Entity authorized to submit on behalf of 58 | the copyright owner. For the purposes of this definition, "submitted" 59 | means any form of electronic, verbal, or written communication sent 60 | to the Licensor or its representatives, including but not limited to 61 | communication on electronic mailing lists, source code control systems, 62 | and issue tracking systems that are managed by, or on behalf of, the 63 | Licensor for the purpose of discussing and improving the Work, but 64 | excluding communication that is conspicuously marked or otherwise 65 | designated in writing by the copyright owner as "Not a Contribution." 66 | 67 | "Contributor" shall mean Licensor and any individual or Legal Entity 68 | on behalf of whom a Contribution has been received by Licensor and 69 | subsequently incorporated within the Work. 70 | 71 | 2. Grant of Copyright License. Subject to the terms and conditions of 72 | this License, each Contributor hereby grants to You a perpetual, 73 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 74 | copyright license to reproduce, prepare Derivative Works of, 75 | publicly display, publicly perform, sublicense, and distribute the 76 | Work and such Derivative Works in Source or Object form. 77 | 78 | 3. Grant of Patent License. Subject to the terms and conditions of 79 | this License, each Contributor hereby grants to You a perpetual, 80 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 81 | (except as stated in this section) patent license to make, have made, 82 | use, offer to sell, sell, import, and otherwise transfer the Work, 83 | where such license applies only to those patent claims licensable 84 | by such Contributor that are necessarily infringed by their 85 | Contribution(s) alone or by combination of their Contribution(s) 86 | with the Work to which such Contribution(s) was submitted. If You 87 | institute patent litigation against any entity (including a 88 | cross-claim or counterclaim in a lawsuit) alleging that the Work 89 | or a Contribution incorporated within the Work constitutes direct 90 | or contributory patent infringement, then any patent licenses 91 | granted to You under this License for that Work shall terminate 92 | as of the date such litigation is filed. 93 | 94 | 4. Redistribution. You may reproduce and distribute copies of the 95 | Work or Derivative Works thereof in any medium, with or without 96 | modifications, and in Source or Object form, provided that You 97 | meet the following conditions: 98 | 99 | (a) You must give any other recipients of the Work or 100 | Derivative Works a copy of this License; and 101 | 102 | (b) You must cause any modified files to carry prominent notices 103 | stating that You changed the files; and 104 | 105 | (c) You must retain, in the Source form of any Derivative Works 106 | that You distribute, all copyright, patent, trademark, and 107 | attribution notices from the Source form of the Work, 108 | excluding those notices that do not pertain to any part of 109 | the Derivative Works; and 110 | 111 | (d) If the Work includes a "NOTICE" text file as part of its 112 | distribution, then any Derivative Works that You distribute must 113 | include a readable copy of the attribution notices contained 114 | within such NOTICE file, excluding those notices that do not 115 | pertain to any part of the Derivative Works, in at least one 116 | of the following places: within a NOTICE text file distributed 117 | as part of the Derivative Works; within the Source form or 118 | documentation, if provided along with the Derivative Works; or, 119 | within a display generated by the Derivative Works, if and 120 | wherever such third-party notices normally appear. The contents 121 | of the NOTICE file are for informational purposes only and 122 | do not modify the License. You may add Your own attribution 123 | notices within Derivative Works that You distribute, alongside 124 | or as an addendum to the NOTICE text from the Work, provided 125 | that such additional attribution notices cannot be construed 126 | as modifying the License. 127 | 128 | You may add Your own copyright statement to Your modifications and 129 | may provide additional or different license terms and conditions 130 | for use, reproduction, or distribution of Your modifications, or 131 | for any such Derivative Works as a whole, provided Your use, 132 | reproduction, and distribution of the Work otherwise complies with 133 | the conditions stated in this License. 134 | 135 | 5. Submission of Contributions. Unless You explicitly state otherwise, 136 | any Contribution intentionally submitted for inclusion in the Work 137 | by You to the Licensor shall be under the terms and conditions of 138 | this License, without any additional terms or conditions. 139 | Notwithstanding the above, nothing herein shall supersede or modify 140 | the terms of any separate license agreement you may have executed 141 | with Licensor regarding such Contributions. 142 | 143 | 6. Trademarks. This License does not grant permission to use the trade 144 | names, trademarks, service marks, or product names of the Licensor, 145 | except as required for reasonable and customary use in describing the 146 | origin of the Work and reproducing the content of the NOTICE file. 147 | 148 | 7. Disclaimer of Warranty. Unless required by applicable law or 149 | agreed to in writing, Licensor provides the Work (and each 150 | Contributor provides its Contributions) on an "AS IS" BASIS, 151 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 152 | implied, including, without limitation, any warranties or conditions 153 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 154 | PARTICULAR PURPOSE. You are solely responsible for determining the 155 | appropriateness of using or redistributing the Work and assume any 156 | risks associated with Your exercise of permissions under this License. 157 | 158 | 8. Limitation of Liability. In no event and under no legal theory, 159 | whether in tort (including negligence), contract, or otherwise, 160 | unless required by applicable law (such as deliberate and grossly 161 | negligent acts) or agreed to in writing, shall any Contributor be 162 | liable to You for damages, including any direct, indirect, special, 163 | incidental, or consequential damages of any character arising as a 164 | result of this License or out of the use or inability to use the 165 | Work (including but not limited to damages for loss of goodwill, 166 | work stoppage, computer failure or malfunction, or any and all 167 | other commercial damages or losses), even if such Contributor 168 | has been advised of the possibility of such damages. 169 | 170 | 9. Accepting Warranty or Additional Liability. While redistributing 171 | the Work or Derivative Works thereof, You may choose to offer, 172 | and charge a fee for, acceptance of support, warranty, indemnity, 173 | or other liability obligations and/or rights consistent with this 174 | License. However, in accepting such obligations, You may act only 175 | on Your own behalf and on Your sole responsibility, not on behalf 176 | of any other Contributor, and only if You agree to indemnify, 177 | defend, and hold each Contributor harmless for any liability 178 | incurred by, or claims asserted against, such Contributor by reason 179 | of your accepting any such warranty or additional liability. 180 | 181 | END OF TERMS AND CONDITIONS 182 | 183 | APPENDIX: How to apply the Apache License to your work. 184 | 185 | To apply the Apache License to your work, attach the following 186 | boilerplate notice, with the fields enclosed by brackets "{}" 187 | replaced with your own identifying information. (Don't include 188 | the brackets!) The text should be enclosed in the appropriate 189 | comment syntax for the file format. We also recommend that a 190 | file or class name and description of purpose be included on the 191 | same "printed page" as the copyright notice for easier 192 | identification within third-party archives. 193 | 194 | Copyright 2014 Ilija Tovilo 195 | 196 | Licensed under the Apache License, Version 2.0 (the "License"); 197 | you may not use this file except in compliance with the License. 198 | You may obtain a copy of the License at 199 | 200 | http://www.apache.org/licenses/LICENSE-2.0 201 | 202 | Unless required by applicable law or agreed to in writing, software 203 | distributed under the License is distributed on an "AS IS" BASIS, 204 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 205 | See the License for the specific language governing permissions and 206 | limitations under the License. 207 | 208 | 209 | Generated by CocoaPods - https://cocoapods.org 210 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Sub It/Pods-Sub It-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Apache License 18 | Version 2.0, January 2004 19 | http://www.apache.org/licenses/ 20 | 21 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 22 | 23 | 1. Definitions. 24 | 25 | "License" shall mean the terms and conditions for use, reproduction, 26 | and distribution as defined by Sections 1 through 9 of this document. 27 | 28 | "Licensor" shall mean the copyright owner or entity authorized by 29 | the copyright owner that is granting the License. 30 | 31 | "Legal Entity" shall mean the union of the acting entity and all 32 | other entities that control, are controlled by, or are under common 33 | control with that entity. For the purposes of this definition, 34 | "control" means (i) the power, direct or indirect, to cause the 35 | direction or management of such entity, whether by contract or 36 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 37 | outstanding shares, or (iii) beneficial ownership of such entity. 38 | 39 | "You" (or "Your") shall mean an individual or Legal Entity 40 | exercising permissions granted by this License. 41 | 42 | "Source" form shall mean the preferred form for making modifications, 43 | including but not limited to software source code, documentation 44 | source, and configuration files. 45 | 46 | "Object" form shall mean any form resulting from mechanical 47 | transformation or translation of a Source form, including but 48 | not limited to compiled object code, generated documentation, 49 | and conversions to other media types. 50 | 51 | "Work" shall mean the work of authorship, whether in Source or 52 | Object form, made available under the License, as indicated by a 53 | copyright notice that is included in or attached to the work 54 | (an example is provided in the Appendix below). 55 | 56 | "Derivative Works" shall mean any work, whether in Source or Object 57 | form, that is based on (or derived from) the Work and for which the 58 | editorial revisions, annotations, elaborations, or other modifications 59 | represent, as a whole, an original work of authorship. For the purposes 60 | of this License, Derivative Works shall not include works that remain 61 | separable from, or merely link (or bind by name) to the interfaces of, 62 | the Work and Derivative Works thereof. 63 | 64 | "Contribution" shall mean any work of authorship, including 65 | the original version of the Work and any modifications or additions 66 | to that Work or Derivative Works thereof, that is intentionally 67 | submitted to Licensor for inclusion in the Work by the copyright owner 68 | or by an individual or Legal Entity authorized to submit on behalf of 69 | the copyright owner. For the purposes of this definition, "submitted" 70 | means any form of electronic, verbal, or written communication sent 71 | to the Licensor or its representatives, including but not limited to 72 | communication on electronic mailing lists, source code control systems, 73 | and issue tracking systems that are managed by, or on behalf of, the 74 | Licensor for the purpose of discussing and improving the Work, but 75 | excluding communication that is conspicuously marked or otherwise 76 | designated in writing by the copyright owner as "Not a Contribution." 77 | 78 | "Contributor" shall mean Licensor and any individual or Legal Entity 79 | on behalf of whom a Contribution has been received by Licensor and 80 | subsequently incorporated within the Work. 81 | 82 | 2. Grant of Copyright License. Subject to the terms and conditions of 83 | this License, each Contributor hereby grants to You a perpetual, 84 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 85 | copyright license to reproduce, prepare Derivative Works of, 86 | publicly display, publicly perform, sublicense, and distribute the 87 | Work and such Derivative Works in Source or Object form. 88 | 89 | 3. Grant of Patent License. Subject to the terms and conditions of 90 | this License, each Contributor hereby grants to You a perpetual, 91 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 92 | (except as stated in this section) patent license to make, have made, 93 | use, offer to sell, sell, import, and otherwise transfer the Work, 94 | where such license applies only to those patent claims licensable 95 | by such Contributor that are necessarily infringed by their 96 | Contribution(s) alone or by combination of their Contribution(s) 97 | with the Work to which such Contribution(s) was submitted. If You 98 | institute patent litigation against any entity (including a 99 | cross-claim or counterclaim in a lawsuit) alleging that the Work 100 | or a Contribution incorporated within the Work constitutes direct 101 | or contributory patent infringement, then any patent licenses 102 | granted to You under this License for that Work shall terminate 103 | as of the date such litigation is filed. 104 | 105 | 4. Redistribution. You may reproduce and distribute copies of the 106 | Work or Derivative Works thereof in any medium, with or without 107 | modifications, and in Source or Object form, provided that You 108 | meet the following conditions: 109 | 110 | (a) You must give any other recipients of the Work or 111 | Derivative Works a copy of this License; and 112 | 113 | (b) You must cause any modified files to carry prominent notices 114 | stating that You changed the files; and 115 | 116 | (c) You must retain, in the Source form of any Derivative Works 117 | that You distribute, all copyright, patent, trademark, and 118 | attribution notices from the Source form of the Work, 119 | excluding those notices that do not pertain to any part of 120 | the Derivative Works; and 121 | 122 | (d) If the Work includes a "NOTICE" text file as part of its 123 | distribution, then any Derivative Works that You distribute must 124 | include a readable copy of the attribution notices contained 125 | within such NOTICE file, excluding those notices that do not 126 | pertain to any part of the Derivative Works, in at least one 127 | of the following places: within a NOTICE text file distributed 128 | as part of the Derivative Works; within the Source form or 129 | documentation, if provided along with the Derivative Works; or, 130 | within a display generated by the Derivative Works, if and 131 | wherever such third-party notices normally appear. The contents 132 | of the NOTICE file are for informational purposes only and 133 | do not modify the License. You may add Your own attribution 134 | notices within Derivative Works that You distribute, alongside 135 | or as an addendum to the NOTICE text from the Work, provided 136 | that such additional attribution notices cannot be construed 137 | as modifying the License. 138 | 139 | You may add Your own copyright statement to Your modifications and 140 | may provide additional or different license terms and conditions 141 | for use, reproduction, or distribution of Your modifications, or 142 | for any such Derivative Works as a whole, provided Your use, 143 | reproduction, and distribution of the Work otherwise complies with 144 | the conditions stated in this License. 145 | 146 | 5. Submission of Contributions. Unless You explicitly state otherwise, 147 | any Contribution intentionally submitted for inclusion in the Work 148 | by You to the Licensor shall be under the terms and conditions of 149 | this License, without any additional terms or conditions. 150 | Notwithstanding the above, nothing herein shall supersede or modify 151 | the terms of any separate license agreement you may have executed 152 | with Licensor regarding such Contributions. 153 | 154 | 6. Trademarks. This License does not grant permission to use the trade 155 | names, trademarks, service marks, or product names of the Licensor, 156 | except as required for reasonable and customary use in describing the 157 | origin of the Work and reproducing the content of the NOTICE file. 158 | 159 | 7. Disclaimer of Warranty. Unless required by applicable law or 160 | agreed to in writing, Licensor provides the Work (and each 161 | Contributor provides its Contributions) on an "AS IS" BASIS, 162 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 163 | implied, including, without limitation, any warranties or conditions 164 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 165 | PARTICULAR PURPOSE. You are solely responsible for determining the 166 | appropriateness of using or redistributing the Work and assume any 167 | risks associated with Your exercise of permissions under this License. 168 | 169 | 8. Limitation of Liability. In no event and under no legal theory, 170 | whether in tort (including negligence), contract, or otherwise, 171 | unless required by applicable law (such as deliberate and grossly 172 | negligent acts) or agreed to in writing, shall any Contributor be 173 | liable to You for damages, including any direct, indirect, special, 174 | incidental, or consequential damages of any character arising as a 175 | result of this License or out of the use or inability to use the 176 | Work (including but not limited to damages for loss of goodwill, 177 | work stoppage, computer failure or malfunction, or any and all 178 | other commercial damages or losses), even if such Contributor 179 | has been advised of the possibility of such damages. 180 | 181 | 9. Accepting Warranty or Additional Liability. While redistributing 182 | the Work or Derivative Works thereof, You may choose to offer, 183 | and charge a fee for, acceptance of support, warranty, indemnity, 184 | or other liability obligations and/or rights consistent with this 185 | License. However, in accepting such obligations, You may act only 186 | on Your own behalf and on Your sole responsibility, not on behalf 187 | of any other Contributor, and only if You agree to indemnify, 188 | defend, and hold each Contributor harmless for any liability 189 | incurred by, or claims asserted against, such Contributor by reason 190 | of your accepting any such warranty or additional liability. 191 | 192 | END OF TERMS AND CONDITIONS 193 | 194 | APPENDIX: How to apply the Apache License to your work. 195 | 196 | To apply the Apache License to your work, attach the following 197 | boilerplate notice, with the fields enclosed by brackets "{}" 198 | replaced with your own identifying information. (Don't include 199 | the brackets!) The text should be enclosed in the appropriate 200 | comment syntax for the file format. We also recommend that a 201 | file or class name and description of purpose be included on the 202 | same "printed page" as the copyright notice for easier 203 | identification within third-party archives. 204 | 205 | Copyright 2014 Ilija Tovilo 206 | 207 | Licensed under the Apache License, Version 2.0 (the "License"); 208 | you may not use this file except in compliance with the License. 209 | You may obtain a copy of the License at 210 | 211 | http://www.apache.org/licenses/LICENSE-2.0 212 | 213 | Unless required by applicable law or agreed to in writing, software 214 | distributed under the License is distributed on an "AS IS" BASIS, 215 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 216 | See the License for the specific language governing permissions and 217 | limitations under the License. 218 | 219 | 220 | License 221 | Apache License 222 | Title 223 | ITSwitch 224 | Type 225 | PSGroupSpecifier 226 | 227 | 228 | FooterText 229 | Generated by CocoaPods - https://cocoapods.org 230 | Title 231 | 232 | Type 233 | PSGroupSpecifier 234 | 235 | 236 | StringsTable 237 | Acknowledgements 238 | Title 239 | Acknowledgements 240 | 241 | 242 | -------------------------------------------------------------------------------- /Pods/ITSwitch/ITSwitch/ITSwitch.m: -------------------------------------------------------------------------------- 1 | // 2 | // ITSwitch.m 3 | // ITSwitch-Demo 4 | // 5 | // Created by Ilija Tovilo on 01/02/14. 6 | // Copyright (c) 2014 Ilija Tovilo. All rights reserved. 7 | // 8 | 9 | #import "ITSwitch.h" 10 | #import 11 | 12 | 13 | // ---------------------------------------------------- 14 | #pragma mark - Static Constants 15 | // ---------------------------------------------------- 16 | 17 | static NSTimeInterval const kAnimationDuration = 0.4f; 18 | 19 | static CGFloat const kBorderLineWidth = 1.f; 20 | 21 | static CGFloat const kGoldenRatio = 1.61803398875f; 22 | static CGFloat const kDecreasedGoldenRatio = 1.38; 23 | 24 | static CGFloat const kEnabledOpacity = 1.f; 25 | static CGFloat const kDisabledOpacity = 0.5f; 26 | 27 | // ---------------------------------------------------- 28 | #pragma mark - Preprocessor 29 | // ---------------------------------------------------- 30 | 31 | 32 | #define kKnobBackgroundColor [NSColor colorWithCalibratedWhite:1.f alpha:1.f] 33 | 34 | #define kDisabledBorderColor [NSColor colorWithCalibratedWhite:0.f alpha:0.2f] 35 | #define kDisabledBackgroundColor [NSColor clearColor] 36 | #define kDefaultTintColor [NSColor colorWithCalibratedRed:0.27f green:0.86f blue:0.36f alpha:1.f] 37 | #define kInactiveBackgroundColor [NSColor colorWithCalibratedWhite:0 alpha:0.3] 38 | 39 | // --------------------------------------------------------------------------------------- 40 | #pragma mark - Interface Extension 41 | // --------------------------------------------------------------------------------------- 42 | 43 | @interface ITSwitch () { 44 | __weak id _target; 45 | SEL _action; 46 | } 47 | 48 | @property (nonatomic, getter = isActive) BOOL active; 49 | @property (nonatomic, getter = hasDragged) BOOL dragged; 50 | @property (nonatomic, getter = isDraggingTowardsOn) BOOL draggingTowardsOn; 51 | 52 | @property (nonatomic, readonly, strong) CALayer *rootLayer; 53 | @property (nonatomic, readonly, strong) CALayer *backgroundLayer; 54 | @property (nonatomic, readonly, strong) CALayer *knobLayer; 55 | @property (nonatomic, readonly, strong) CALayer *knobInsideLayer; 56 | 57 | - (void)propagateValue:(id)value forBinding:(NSString*)binding; 58 | 59 | @end 60 | 61 | 62 | 63 | // --------------------------------------------------------------------------------------- 64 | #pragma mark - ITSwitch 65 | // --------------------------------------------------------------------------------------- 66 | 67 | @implementation ITSwitch 68 | @synthesize tintColor = _tintColor; 69 | 70 | 71 | 72 | // ---------------------------------------------------- 73 | #pragma mark - Init 74 | // ---------------------------------------------------- 75 | 76 | - (id)initWithCoder:(NSCoder *)coder { 77 | self = [super initWithCoder:coder]; 78 | if (!self) return nil; 79 | 80 | [self setUp]; 81 | 82 | return self; 83 | } 84 | 85 | - (id)initWithFrame:(NSRect)frame { 86 | self = [super initWithFrame:frame]; 87 | if (!self) return nil; 88 | 89 | [self setUp]; 90 | 91 | return self; 92 | } 93 | 94 | - (void)setUp { 95 | // The Switch is enabled per default 96 | self.enabled = YES; 97 | 98 | // Set up the layer hierarchy 99 | [self setUpLayers]; 100 | } 101 | 102 | - (void)setUpLayers { 103 | // Root layer 104 | _rootLayer = [CALayer layer]; 105 | //_rootLayer.delegate = self; 106 | self.layer = _rootLayer; 107 | self.wantsLayer = YES; 108 | 109 | // Background layer 110 | _backgroundLayer = [CALayer layer]; 111 | _backgroundLayer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable; 112 | _backgroundLayer.bounds = _rootLayer.bounds; 113 | _backgroundLayer.anchorPoint = (CGPoint){ .x = 0.f, .y = 0.f }; 114 | _backgroundLayer.borderWidth = kBorderLineWidth; 115 | [_rootLayer addSublayer:_backgroundLayer]; 116 | 117 | // Knob layer 118 | _knobLayer = [CALayer layer]; 119 | _knobLayer.frame = [self rectForKnob]; 120 | _knobLayer.autoresizingMask = kCALayerHeightSizable; 121 | _knobLayer.backgroundColor = [kKnobBackgroundColor CGColor]; 122 | _knobLayer.shadowColor = [[NSColor blackColor] CGColor]; 123 | _knobLayer.shadowOffset = (CGSize){ .width = 0.f, .height = -2.f }; 124 | _knobLayer.shadowRadius = 1.f; 125 | _knobLayer.shadowOpacity = 0.3f; 126 | [_rootLayer addSublayer:_knobLayer]; 127 | 128 | _knobInsideLayer = [CALayer layer]; 129 | _knobInsideLayer.frame = _knobLayer.bounds; 130 | _knobInsideLayer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable; 131 | _knobInsideLayer.shadowColor = [[NSColor blackColor] CGColor]; 132 | _knobInsideLayer.shadowOffset = (CGSize){ .width = 0.f, .height = 0.f }; 133 | _knobInsideLayer.backgroundColor = [[NSColor whiteColor] CGColor]; 134 | _knobInsideLayer.shadowRadius = 1.f; 135 | _knobInsideLayer.shadowOpacity = 0.35f; 136 | [_knobLayer addSublayer:_knobInsideLayer]; 137 | 138 | // Initial 139 | [self reloadLayerSize]; 140 | [self reloadLayer]; 141 | } 142 | 143 | 144 | 145 | // ---------------------------------------------------- 146 | #pragma mark - NSView 147 | // ---------------------------------------------------- 148 | 149 | - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent { 150 | return YES; 151 | } 152 | 153 | - (void)setFrame:(NSRect)frameRect { 154 | [super setFrame:frameRect]; 155 | 156 | [self reloadLayerSize]; 157 | } 158 | 159 | - (void)drawFocusRingMask { 160 | CGFloat cornerRadius = NSHeight([self bounds])/2.0; 161 | NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:[self bounds] xRadius:cornerRadius yRadius:cornerRadius]; 162 | [[NSColor blackColor] set]; 163 | [path fill]; 164 | } 165 | 166 | - (BOOL)canBecomeKeyView { 167 | return [NSApp isFullKeyboardAccessEnabled]; 168 | } 169 | 170 | - (NSRect)focusRingMaskBounds { 171 | return [self bounds]; 172 | } 173 | 174 | 175 | // ---------------------------------------------------- 176 | #pragma mark - Update Layer 177 | // ---------------------------------------------------- 178 | 179 | - (void)reloadLayer { 180 | [CATransaction begin]; 181 | [CATransaction setAnimationDuration:kAnimationDuration]; 182 | { 183 | // ------------------------------- Animate Border 184 | // The green part also animates, which looks kinda weird 185 | // We'll use the background-color for now 186 | // _backgroundLayer.borderWidth = (YES || self.isActive || self.isOn) ? NSHeight(_backgroundLayer.bounds) / 2 : kBorderLineWidth; 187 | 188 | // ------------------------------- Animate Colors 189 | if (([self hasDragged] && [self isDraggingTowardsOn]) || (![self hasDragged] && [self checked])) { 190 | _backgroundLayer.borderColor = [self.tintColor CGColor]; 191 | _backgroundLayer.backgroundColor = [self.tintColor CGColor]; 192 | } else { 193 | _backgroundLayer.borderColor = [kDisabledBorderColor CGColor]; 194 | _backgroundLayer.backgroundColor = [kDisabledBackgroundColor CGColor]; 195 | } 196 | 197 | // ------------------------------- Animate Enabled-Disabled state 198 | _rootLayer.opacity = (self.isEnabled) ? kEnabledOpacity : kDisabledOpacity; 199 | 200 | // ------------------------------- Animate Frame 201 | if (![self hasDragged]) { 202 | CAMediaTimingFunction *function = [CAMediaTimingFunction functionWithControlPoints:0.25f :1.5f :0.5f :1.f]; 203 | [CATransaction setAnimationTimingFunction:function]; 204 | } 205 | 206 | self.knobLayer.frame = [self rectForKnob]; 207 | self.knobInsideLayer.frame = self.knobLayer.bounds; 208 | } 209 | [CATransaction commit]; 210 | } 211 | 212 | - (void)reloadLayerSize { 213 | [CATransaction begin]; 214 | [CATransaction setDisableActions:YES]; 215 | { 216 | self.knobLayer.frame = [self rectForKnob]; 217 | self.knobInsideLayer.frame = self.knobLayer.bounds; 218 | 219 | [_backgroundLayer setCornerRadius:_backgroundLayer.bounds.size.height / 2.f]; 220 | [_knobLayer setCornerRadius:_knobLayer.bounds.size.height / 2.f]; 221 | [_knobInsideLayer setCornerRadius:_knobLayer.bounds.size.height / 2.f]; 222 | } 223 | [CATransaction commit]; 224 | } 225 | 226 | - (CGFloat)knobHeightForSize:(NSSize)size 227 | { 228 | return size.height - (kBorderLineWidth * 2.f); 229 | } 230 | 231 | - (CGRect)rectForKnob { 232 | CGFloat height = [self knobHeightForSize:_backgroundLayer.bounds.size]; 233 | CGFloat width = ![self isActive] ? (NSWidth(_backgroundLayer.bounds) - 2.f * kBorderLineWidth) * 1.f / kGoldenRatio : 234 | (NSWidth(_backgroundLayer.bounds) - 2.f * kBorderLineWidth) * 1.f / kDecreasedGoldenRatio; 235 | CGFloat x = ((![self hasDragged] && ![self checked]) || (self.hasDragged && ![self isDraggingTowardsOn])) ? 236 | kBorderLineWidth : 237 | NSWidth(_backgroundLayer.bounds) - width - kBorderLineWidth; 238 | 239 | return (CGRect) { 240 | .size.width = width, 241 | .size.height = height, 242 | .origin.x = x, 243 | .origin.y = kBorderLineWidth, 244 | }; 245 | } 246 | 247 | 248 | 249 | // ---------------------------------------------------- 250 | #pragma mark - NSResponder 251 | // ---------------------------------------------------- 252 | 253 | - (BOOL)acceptsFirstResponder { 254 | return [NSApp isFullKeyboardAccessEnabled]; 255 | } 256 | 257 | - (void)mouseDown:(NSEvent *)theEvent { 258 | if (!self.isEnabled) return; 259 | 260 | self.active = YES; 261 | 262 | [self reloadLayer]; 263 | } 264 | 265 | - (void)mouseDragged:(NSEvent *)theEvent { 266 | if (!self.isEnabled) return; 267 | 268 | self.dragged = YES; 269 | 270 | NSPoint draggingPoint = [self convertPoint:[theEvent locationInWindow] fromView:nil]; 271 | self.draggingTowardsOn = draggingPoint.x >= NSWidth(self.bounds) / 2.f; 272 | 273 | [self reloadLayer]; 274 | } 275 | 276 | - (void)mouseUp:(NSEvent *)theEvent { 277 | if (!self.isEnabled) return; 278 | 279 | self.active = NO; 280 | 281 | BOOL checked = (![self hasDragged]) ? ![self checked] : [self isDraggingTowardsOn]; 282 | BOOL invokeTargetAction = (checked != [self checked]); 283 | 284 | self.checked = checked; 285 | if (invokeTargetAction) [self _invokeTargetAction]; 286 | 287 | // Reset 288 | self.dragged = NO; 289 | self.draggingTowardsOn = NO; 290 | 291 | [self reloadLayer]; 292 | } 293 | 294 | - (void)moveLeft:(id)sender { 295 | if ([self checked]) { 296 | self.checked = NO; 297 | [self _invokeTargetAction]; 298 | } 299 | } 300 | 301 | - (void)moveRight:(id)sender { 302 | if ([self checked] == NO) { 303 | self.checked = YES; 304 | [self _invokeTargetAction]; 305 | } 306 | } 307 | 308 | - (BOOL)performKeyEquivalent:(NSEvent *)theEvent { 309 | BOOL handledKeyEquivalent = NO; 310 | if ([[self window] firstResponder] == self) { 311 | NSInteger ch = [theEvent keyCode]; 312 | 313 | if (ch == 49) //Space 314 | { 315 | self.checked = ![self checked]; 316 | [self _invokeTargetAction]; 317 | handledKeyEquivalent = YES; 318 | } 319 | } 320 | return handledKeyEquivalent; 321 | } 322 | 323 | 324 | // ---------------------------------------------------- 325 | #pragma mark - Accessors 326 | // ---------------------------------------------------- 327 | 328 | - (id)target { 329 | return _target; 330 | } 331 | 332 | - (void)setTarget:(id)target { 333 | _target = target; 334 | } 335 | 336 | - (SEL)action { 337 | return _action; 338 | } 339 | 340 | - (void)setAction:(SEL)action { 341 | _action = action; 342 | } 343 | 344 | - (void)setChecked:(BOOL)checked { 345 | if (_checked != checked) { 346 | _checked = checked; 347 | [self propagateValue:@(checked) forBinding:@"checked"]; 348 | } 349 | 350 | [self reloadLayer]; 351 | } 352 | 353 | - (NSColor *)tintColor { 354 | if (!_tintColor) return kDefaultTintColor; 355 | 356 | return _tintColor; 357 | } 358 | 359 | - (void)setTintColor:(NSColor *)tintColor { 360 | _tintColor = tintColor; 361 | 362 | [self reloadLayer]; 363 | } 364 | 365 | - (void)setEnabled:(BOOL)enabled { 366 | [super setEnabled:enabled]; 367 | [self reloadLayer]; 368 | } 369 | 370 | // ----------------------------------- 371 | #pragma mark - Helpers 372 | // ----------------------------------- 373 | 374 | - (void)_invokeTargetAction { 375 | if (self.target && self.action) { 376 | NSMethodSignature *signature = [[self.target class] instanceMethodSignatureForSelector:self.action]; 377 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; 378 | [invocation setTarget:self.target]; 379 | [invocation setSelector:self.action]; 380 | [invocation setArgument:(void *)&self atIndex:2]; 381 | 382 | [invocation invoke]; 383 | } 384 | } 385 | 386 | // ----------------------------------- 387 | #pragma mark - Accessibility 388 | // ----------------------------------- 389 | 390 | - (BOOL)accessibilityIsIgnored { 391 | return NO; 392 | } 393 | 394 | - (id)accessibilityHitTest:(NSPoint)point { 395 | return self; 396 | } 397 | 398 | - (NSArray *)accessibilityAttributeNames { 399 | static NSArray *attributes = nil; 400 | if (attributes == nil) 401 | { 402 | NSMutableArray *mutableAttributes = [[super accessibilityAttributeNames] mutableCopy]; 403 | if (mutableAttributes == nil) 404 | mutableAttributes = [NSMutableArray new]; 405 | 406 | // Add attributes 407 | if (![mutableAttributes containsObject:NSAccessibilityValueAttribute]) 408 | [mutableAttributes addObject:NSAccessibilityValueAttribute]; 409 | 410 | if (![mutableAttributes containsObject:NSAccessibilityEnabledAttribute]) 411 | [mutableAttributes addObject:NSAccessibilityEnabledAttribute]; 412 | 413 | if (![mutableAttributes containsObject:NSAccessibilityDescriptionAttribute]) 414 | [mutableAttributes addObject:NSAccessibilityDescriptionAttribute]; 415 | 416 | // Remove attributes 417 | if ([mutableAttributes containsObject:NSAccessibilityChildrenAttribute]) 418 | [mutableAttributes removeObject:NSAccessibilityChildrenAttribute]; 419 | 420 | attributes = [mutableAttributes copy]; 421 | } 422 | return attributes; 423 | } 424 | 425 | - (id)accessibilityAttributeValue:(NSString *)attribute { 426 | id retVal = nil; 427 | if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) 428 | retVal = NSAccessibilityCheckBoxRole; 429 | else if ([attribute isEqualToString:NSAccessibilityValueAttribute]) 430 | retVal = [NSNumber numberWithInt:self.checked]; 431 | else if ([attribute isEqualToString:NSAccessibilityEnabledAttribute]) 432 | retVal = [NSNumber numberWithBool:self.enabled]; 433 | else 434 | retVal = [super accessibilityAttributeValue:attribute]; 435 | return retVal; 436 | } 437 | 438 | - (BOOL)accessibilityIsAttributeSettable:(NSString *)attribute { 439 | BOOL retVal; 440 | if ([attribute isEqualToString:NSAccessibilityValueAttribute]) 441 | retVal = YES; 442 | else if ([attribute isEqualToString:NSAccessibilityEnabledAttribute]) 443 | retVal = NO; 444 | else if ([attribute isEqualToString:NSAccessibilityDescriptionAttribute]) 445 | retVal = NO; 446 | else 447 | retVal = [super accessibilityIsAttributeSettable:attribute]; 448 | return retVal; 449 | } 450 | 451 | - (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute { 452 | if ([attribute isEqualToString:NSAccessibilityValueAttribute]) { 453 | BOOL invokeTargetAction = self.checked != [value boolValue]; 454 | self.checked = [value boolValue]; 455 | if (invokeTargetAction) { 456 | [self _invokeTargetAction]; 457 | } 458 | } 459 | else { 460 | [super accessibilitySetValue:value forAttribute:attribute]; 461 | } 462 | } 463 | 464 | - (NSArray *)accessibilityActionNames { 465 | static NSArray *actions = nil; 466 | if (actions == nil) 467 | { 468 | NSMutableArray *mutableActions = [[super accessibilityActionNames] mutableCopy]; 469 | if (mutableActions == nil) 470 | mutableActions = [NSMutableArray new]; 471 | if (![mutableActions containsObject:NSAccessibilityPressAction]) 472 | [mutableActions addObject:NSAccessibilityPressAction]; 473 | actions = [mutableActions copy]; 474 | } 475 | return actions; 476 | } 477 | 478 | - (void)accessibilityPerformAction:(NSString *)actionString { 479 | if ([actionString isEqualToString:NSAccessibilityPressAction]) { 480 | self.checked = ![self checked]; 481 | [self _invokeTargetAction]; 482 | } 483 | else { 484 | [super accessibilityPerformAction:actionString]; 485 | } 486 | } 487 | 488 | #pragma mark - 489 | #pragma mark Bindings Extension 490 | 491 | - (void)propagateValue:(id)value forBinding:(NSString*)binding 492 | { 493 | NSParameterAssert(binding != nil); 494 | 495 | // WARNING: bindingInfo contains NSNull, so it must be accounted for 496 | NSDictionary* bindingInfo = [self infoForBinding:binding]; 497 | if(!bindingInfo) 498 | return; //there is no binding 499 | 500 | // apply the value transformer, if one has been set 501 | NSDictionary* bindingOptions = [bindingInfo objectForKey:NSOptionsKey]; 502 | if(bindingOptions){ 503 | NSValueTransformer* transformer = [bindingOptions valueForKey:NSValueTransformerBindingOption]; 504 | if(!transformer || (id)transformer == [NSNull null]){ 505 | NSString* transformerName = [bindingOptions valueForKey:NSValueTransformerNameBindingOption]; 506 | if(transformerName && (id)transformerName != [NSNull null]){ 507 | transformer = [NSValueTransformer valueTransformerForName:transformerName]; 508 | } 509 | } 510 | 511 | if(transformer && (id)transformer != [NSNull null]){ 512 | if([[transformer class] allowsReverseTransformation]){ 513 | value = [transformer reverseTransformedValue:value]; 514 | } else { 515 | NSLog(@"WARNING: binding \"%@\" has value transformer, but it doesn't allow reverse transformations in %s", binding, __PRETTY_FUNCTION__); 516 | } 517 | } 518 | } 519 | 520 | id boundObject = [bindingInfo objectForKey:NSObservedObjectKey]; 521 | if(!boundObject || boundObject == [NSNull null]){ 522 | NSLog(@"ERROR: NSObservedObjectKey was nil for binding \"%@\" in %s", binding, __PRETTY_FUNCTION__); 523 | return; 524 | } 525 | 526 | NSString* boundKeyPath = [bindingInfo objectForKey:NSObservedKeyPathKey]; 527 | if(!boundKeyPath || (id)boundKeyPath == [NSNull null]){ 528 | NSLog(@"ERROR: NSObservedKeyPathKey was nil for binding \"%@\" in %s", binding, __PRETTY_FUNCTION__); 529 | return; 530 | } 531 | 532 | [boundObject setValue:value forKeyPath:boundKeyPath]; 533 | } 534 | 535 | @end 536 | -------------------------------------------------------------------------------- /Pods/LetsMove/PFMoveApplication.m: -------------------------------------------------------------------------------- 1 | // 2 | // PFMoveApplication.m, version 1.22 3 | // LetsMove 4 | // 5 | // Created by Andy Kim at Potion Factory LLC on 9/17/09 6 | // 7 | // The contents of this file are dedicated to the public domain. 8 | 9 | #import "PFMoveApplication.h" 10 | 11 | #import 12 | #import 13 | #import 14 | #import 15 | #import 16 | #import 17 | 18 | // Strings 19 | // These are macros to be able to use custom i18n tools 20 | #define _I10NS(nsstr) NSLocalizedStringFromTable(nsstr, @"MoveApplication", nil) 21 | #define kStrMoveApplicationCouldNotMove _I10NS(@"Could not move to Applications folder") 22 | #define kStrMoveApplicationQuestionTitle _I10NS(@"Move to Applications folder?") 23 | #define kStrMoveApplicationQuestionTitleHome _I10NS(@"Move to Applications folder in your Home folder?") 24 | #define kStrMoveApplicationQuestionMessage _I10NS(@"I can move myself to the Applications folder if you'd like.") 25 | #define kStrMoveApplicationButtonMove _I10NS(@"Move to Applications Folder") 26 | #define kStrMoveApplicationButtonDoNotMove _I10NS(@"Do Not Move") 27 | #define kStrMoveApplicationQuestionInfoWillRequirePasswd _I10NS(@"Note that this will require an administrator password.") 28 | #define kStrMoveApplicationQuestionInfoInDownloadsFolder _I10NS(@"This will keep your Downloads folder uncluttered.") 29 | 30 | // Needs to be defined for compiling under 10.5 SDK 31 | #ifndef NSAppKitVersionNumber10_5 32 | #define NSAppKitVersionNumber10_5 949 33 | #endif 34 | 35 | // By default, we use a small control/font for the suppression button. 36 | // If you prefer to use the system default (to match your other alerts), 37 | // set this to 0. 38 | #define PFUseSmallAlertSuppressCheckbox 1 39 | 40 | 41 | static NSString *AlertSuppressKey = @"moveToApplicationsFolderAlertSuppress"; 42 | 43 | 44 | // Helper functions 45 | static NSString *PreferredInstallLocation(BOOL *isUserDirectory); 46 | static BOOL IsInApplicationsFolder(NSString *path); 47 | static BOOL IsInDownloadsFolder(NSString *path); 48 | static BOOL IsApplicationAtPathRunning(NSString *path); 49 | static BOOL IsApplicationAtPathNested(NSString *path); 50 | static NSString *ContainingDiskImageDevice(NSString *path); 51 | static BOOL Trash(NSString *path); 52 | static BOOL DeleteOrTrash(NSString *path); 53 | static BOOL AuthorizedInstall(NSString *srcPath, NSString *dstPath, BOOL *canceled); 54 | static BOOL CopyBundle(NSString *srcPath, NSString *dstPath); 55 | static NSString *ShellQuotedString(NSString *string); 56 | static void Relaunch(NSString *destinationPath); 57 | 58 | // Main worker function 59 | void PFMoveToApplicationsFolderIfNecessary(void) { 60 | // Skip if user suppressed the alert before 61 | if ([[NSUserDefaults standardUserDefaults] boolForKey:AlertSuppressKey]) return; 62 | 63 | // Path of the bundle 64 | NSString *bundlePath = [[NSBundle mainBundle] bundlePath]; 65 | 66 | // Check if the bundle is embedded in another application 67 | BOOL isNestedApplication = IsApplicationAtPathNested(bundlePath); 68 | 69 | // Skip if the application is already in some Applications folder, 70 | // unless it's inside another app's bundle. 71 | if (IsInApplicationsFolder(bundlePath) && !isNestedApplication) return; 72 | 73 | // File Manager 74 | NSFileManager *fm = [NSFileManager defaultManager]; 75 | 76 | // Are we on a disk image? 77 | NSString *diskImageDevice = ContainingDiskImageDevice(bundlePath); 78 | 79 | // Since we are good to go, get the preferred installation directory. 80 | BOOL installToUserApplications = NO; 81 | NSString *applicationsDirectory = PreferredInstallLocation(&installToUserApplications); 82 | NSString *bundleName = [bundlePath lastPathComponent]; 83 | NSString *destinationPath = [applicationsDirectory stringByAppendingPathComponent:bundleName]; 84 | 85 | // Check if we need admin password to write to the Applications directory 86 | BOOL needAuthorization = ([fm isWritableFileAtPath:applicationsDirectory] == NO); 87 | 88 | // Check if the destination bundle is already there but not writable 89 | needAuthorization |= ([fm fileExistsAtPath:destinationPath] && ![fm isWritableFileAtPath:destinationPath]); 90 | 91 | // Setup the alert 92 | NSAlert *alert = [[[NSAlert alloc] init] autorelease]; 93 | { 94 | NSString *informativeText = nil; 95 | 96 | [alert setMessageText:(installToUserApplications ? kStrMoveApplicationQuestionTitleHome : kStrMoveApplicationQuestionTitle)]; 97 | 98 | informativeText = kStrMoveApplicationQuestionMessage; 99 | 100 | if (needAuthorization) { 101 | informativeText = [informativeText stringByAppendingString:@" "]; 102 | informativeText = [informativeText stringByAppendingString:kStrMoveApplicationQuestionInfoWillRequirePasswd]; 103 | } 104 | else if (IsInDownloadsFolder(bundlePath)) { 105 | // Don't mention this stuff if we need authentication. The informative text is long enough as it is in that case. 106 | informativeText = [informativeText stringByAppendingString:@" "]; 107 | informativeText = [informativeText stringByAppendingString:kStrMoveApplicationQuestionInfoInDownloadsFolder]; 108 | } 109 | 110 | [alert setInformativeText:informativeText]; 111 | 112 | // Add accept button 113 | [alert addButtonWithTitle:kStrMoveApplicationButtonMove]; 114 | 115 | // Add deny button 116 | NSButton *cancelButton = [alert addButtonWithTitle:kStrMoveApplicationButtonDoNotMove]; 117 | [cancelButton setKeyEquivalent:[NSString stringWithFormat:@"%C", 0x1b]]; // Escape key 118 | 119 | // Setup suppression button 120 | [alert setShowsSuppressionButton:YES]; 121 | 122 | if (PFUseSmallAlertSuppressCheckbox) { 123 | NSCell *cell = [[alert suppressionButton] cell]; 124 | [cell setControlSize:NSSmallControlSize]; 125 | [cell setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; 126 | } 127 | } 128 | 129 | // Activate app -- work-around for focus issues related to "scary file from internet" OS dialog. 130 | if (![NSApp isActive]) { 131 | [NSApp activateIgnoringOtherApps:YES]; 132 | } 133 | 134 | if ([alert runModal] == NSAlertFirstButtonReturn) { 135 | NSLog(@"INFO -- Moving myself to the Applications folder"); 136 | 137 | // Move 138 | if (needAuthorization) { 139 | BOOL authorizationCanceled; 140 | 141 | if (!AuthorizedInstall(bundlePath, destinationPath, &authorizationCanceled)) { 142 | if (authorizationCanceled) { 143 | NSLog(@"INFO -- Not moving because user canceled authorization"); 144 | return; 145 | } 146 | else { 147 | NSLog(@"ERROR -- Could not copy myself to /Applications with authorization"); 148 | goto fail; 149 | } 150 | } 151 | } 152 | else { 153 | // If a copy already exists in the Applications folder, put it in the Trash 154 | if ([fm fileExistsAtPath:destinationPath]) { 155 | // But first, make sure that it's not running 156 | if (IsApplicationAtPathRunning(destinationPath)) { 157 | // Give the running app focus and terminate myself 158 | NSLog(@"INFO -- Switching to an already running version"); 159 | [[NSTask launchedTaskWithLaunchPath:@"/usr/bin/open" arguments:[NSArray arrayWithObject:destinationPath]] waitUntilExit]; 160 | exit(0); 161 | } 162 | else { 163 | if (!Trash([applicationsDirectory stringByAppendingPathComponent:bundleName])) 164 | goto fail; 165 | } 166 | } 167 | 168 | if (!CopyBundle(bundlePath, destinationPath)) { 169 | NSLog(@"ERROR -- Could not copy myself to %@", destinationPath); 170 | goto fail; 171 | } 172 | } 173 | 174 | // Trash the original app. It's okay if this fails. 175 | // NOTE: This final delete does not work if the source bundle is in a network mounted volume. 176 | // Calling rm or file manager's delete method doesn't work either. It's unlikely to happen 177 | // but it'd be great if someone could fix this. 178 | if (!isNestedApplication && diskImageDevice == nil && !DeleteOrTrash(bundlePath)) { 179 | NSLog(@"WARNING -- Could not delete application after moving it to Applications folder"); 180 | } 181 | 182 | // Relaunch. 183 | Relaunch(destinationPath); 184 | 185 | // Launched from within a disk image? -- unmount (if no files are open after 5 seconds, 186 | // otherwise leave it mounted). 187 | if (diskImageDevice && !isNestedApplication) { 188 | NSString *script = [NSString stringWithFormat:@"(/bin/sleep 5 && /usr/bin/hdiutil detach %@) &", ShellQuotedString(diskImageDevice)]; 189 | [NSTask launchedTaskWithLaunchPath:@"/bin/sh" arguments:[NSArray arrayWithObjects:@"-c", script, nil]]; 190 | } 191 | 192 | exit(0); 193 | } 194 | // Save the alert suppress preference if checked 195 | else if ([[alert suppressionButton] state] == NSOnState) { 196 | [[NSUserDefaults standardUserDefaults] setBool:YES forKey:AlertSuppressKey]; 197 | } 198 | 199 | return; 200 | 201 | fail: 202 | { 203 | // Show failure message 204 | alert = [[[NSAlert alloc] init] autorelease]; 205 | [alert setMessageText:kStrMoveApplicationCouldNotMove]; 206 | [alert runModal]; 207 | } 208 | } 209 | 210 | #pragma mark - 211 | #pragma mark Helper Functions 212 | 213 | static NSString *PreferredInstallLocation(BOOL *isUserDirectory) { 214 | // Return the preferred install location. 215 | // Assume that if the user has a ~/Applications folder, they'd prefer their 216 | // applications to go there. 217 | 218 | NSFileManager *fm = [NSFileManager defaultManager]; 219 | 220 | NSArray *userApplicationsDirs = NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSUserDomainMask, YES); 221 | 222 | if ([userApplicationsDirs count] > 0) { 223 | NSString *userApplicationsDir = [userApplicationsDirs objectAtIndex:0]; 224 | BOOL isDirectory; 225 | 226 | if ([fm fileExistsAtPath:userApplicationsDir isDirectory:&isDirectory] && isDirectory) { 227 | // User Applications directory exists. Get the directory contents. 228 | NSArray *contents = [fm contentsOfDirectoryAtPath:userApplicationsDir error:NULL]; 229 | 230 | // Check if there is at least one ".app" inside the directory. 231 | for (NSString *contentsPath in contents) { 232 | if ([[contentsPath pathExtension] isEqualToString:@"app"]) { 233 | if (isUserDirectory) *isUserDirectory = YES; 234 | return [userApplicationsDir stringByResolvingSymlinksInPath]; 235 | } 236 | } 237 | } 238 | } 239 | 240 | // No user Applications directory in use. Return the machine local Applications directory 241 | if (isUserDirectory) *isUserDirectory = NO; 242 | 243 | return [[NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSLocalDomainMask, YES) lastObject] stringByResolvingSymlinksInPath]; 244 | } 245 | 246 | static BOOL IsInApplicationsFolder(NSString *path) { 247 | // Check all the normal Application directories 248 | NSArray *applicationDirs = NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSAllDomainsMask, YES); 249 | for (NSString *appDir in applicationDirs) { 250 | if ([path hasPrefix:appDir]) return YES; 251 | } 252 | 253 | // Also, handle the case that the user has some other Application directory (perhaps on a separate data partition). 254 | if ([[path pathComponents] containsObject:@"Applications"]) return YES; 255 | 256 | return NO; 257 | } 258 | 259 | static BOOL IsInDownloadsFolder(NSString *path) { 260 | NSArray *downloadDirs = NSSearchPathForDirectoriesInDomains(NSDownloadsDirectory, NSAllDomainsMask, YES); 261 | for (NSString *downloadsDirPath in downloadDirs) { 262 | if ([path hasPrefix:downloadsDirPath]) return YES; 263 | } 264 | 265 | return NO; 266 | } 267 | 268 | static BOOL IsApplicationAtPathRunning(NSString *bundlePath) { 269 | bundlePath = [bundlePath stringByStandardizingPath]; 270 | 271 | #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 272 | // Use the new API on 10.6 or higher to determine if the app is already running 273 | if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_5) { 274 | for (NSRunningApplication *runningApplication in [[NSWorkspace sharedWorkspace] runningApplications]) { 275 | NSString *runningAppBundlePath = [[[runningApplication bundleURL] path] stringByStandardizingPath]; 276 | if ([runningAppBundlePath isEqualToString:bundlePath]) { 277 | return YES; 278 | } 279 | } 280 | return NO; 281 | } 282 | #endif 283 | // Use the shell to determine if the app is already running on systems 10.5 or lower 284 | NSString *script = [NSString stringWithFormat:@"/bin/ps ax -o comm | /usr/bin/grep %@/ | /usr/bin/grep -v grep >/dev/null", ShellQuotedString(bundlePath)]; 285 | NSTask *task = [NSTask launchedTaskWithLaunchPath:@"/bin/sh" arguments:[NSArray arrayWithObjects:@"-c", script, nil]]; 286 | [task waitUntilExit]; 287 | 288 | // If the task terminated with status 0, it means that the final grep produced 1 or more lines of output. 289 | // Which means that the app is already running 290 | return [task terminationStatus] == 0; 291 | } 292 | 293 | static BOOL IsApplicationAtPathNested(NSString *path) { 294 | NSString *containingPath = [path stringByDeletingLastPathComponent]; 295 | 296 | NSArray *components = [containingPath pathComponents]; 297 | for (NSString *component in components) { 298 | if ([[component pathExtension] isEqualToString:@"app"]) { 299 | return YES; 300 | } 301 | } 302 | 303 | return NO; 304 | } 305 | 306 | static NSString *ContainingDiskImageDevice(NSString *path) { 307 | NSString *containingPath = [path stringByDeletingLastPathComponent]; 308 | 309 | struct statfs fs; 310 | if (statfs([containingPath fileSystemRepresentation], &fs) || (fs.f_flags & MNT_ROOTFS)) 311 | return nil; 312 | 313 | NSString *device = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:fs.f_mntfromname length:strlen(fs.f_mntfromname)]; 314 | 315 | NSTask *hdiutil = [[[NSTask alloc] init] autorelease]; 316 | [hdiutil setLaunchPath:@"/usr/bin/hdiutil"]; 317 | [hdiutil setArguments:[NSArray arrayWithObjects:@"info", @"-plist", nil]]; 318 | [hdiutil setStandardOutput:[NSPipe pipe]]; 319 | [hdiutil launch]; 320 | [hdiutil waitUntilExit]; 321 | 322 | NSData *data = [[[hdiutil standardOutput] fileHandleForReading] readDataToEndOfFile]; 323 | NSDictionary *info = nil; 324 | #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 325 | if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_5) { 326 | info = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListImmutable format:NULL error:NULL]; 327 | } 328 | else { 329 | #endif 330 | #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10 331 | info = [NSPropertyListSerialization propertyListFromData:data mutabilityOption:NSPropertyListImmutable format:NULL errorDescription:NULL]; 332 | #endif 333 | #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 334 | } 335 | #endif 336 | 337 | if (![info isKindOfClass:[NSDictionary class]]) return nil; 338 | 339 | NSArray *images = (NSArray *)[info objectForKey:@"images"]; 340 | if (![images isKindOfClass:[NSArray class]]) return nil; 341 | 342 | for (NSDictionary *image in images) { 343 | if (![image isKindOfClass:[NSDictionary class]]) return nil; 344 | 345 | id systemEntities = [image objectForKey:@"system-entities"]; 346 | if (![systemEntities isKindOfClass:[NSArray class]]) return nil; 347 | 348 | for (NSDictionary *systemEntity in systemEntities) { 349 | if (![systemEntity isKindOfClass:[NSDictionary class]]) return nil; 350 | 351 | NSString *devEntry = [systemEntity objectForKey:@"dev-entry"]; 352 | if (![devEntry isKindOfClass:[NSString class]]) return nil; 353 | 354 | if ([devEntry isEqualToString:device]) 355 | return device; 356 | } 357 | } 358 | 359 | return nil; 360 | } 361 | 362 | static BOOL Trash(NSString *path) { 363 | BOOL result = NO; 364 | #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 365 | if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_8) { 366 | result = [[NSFileManager defaultManager] trashItemAtURL:[NSURL fileURLWithPath:path] resultingItemURL:NULL error:NULL]; 367 | } 368 | #endif 369 | #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11 370 | if (!result) { 371 | result = [[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation 372 | source:[path stringByDeletingLastPathComponent] 373 | destination:@"" 374 | files:[NSArray arrayWithObject:[path lastPathComponent]] 375 | tag:NULL]; 376 | } 377 | #endif 378 | 379 | // As a last resort try trashing with AppleScript. 380 | // This allows us to trash the app in macOS Sierra even when the app is running inside 381 | // an app translocation image. 382 | if (!result) { 383 | NSAppleScript *appleScript = [[[NSAppleScript alloc] initWithSource: 384 | [NSString stringWithFormat:@"\ 385 | set theFile to POSIX file \"%@\" \n\ 386 | tell application \"Finder\" \n\ 387 | move theFile to trash \n\ 388 | end tell", path]] autorelease]; 389 | NSDictionary *errorDict = nil; 390 | NSAppleEventDescriptor *scriptResult = [appleScript executeAndReturnError:&errorDict]; 391 | if (scriptResult == nil) { 392 | NSLog(@"Trash AppleScript error: %@", errorDict); 393 | } 394 | result = (scriptResult != nil); 395 | } 396 | 397 | if (!result) { 398 | NSLog(@"ERROR -- Could not trash '%@'", path); 399 | } 400 | 401 | return result; 402 | } 403 | 404 | static BOOL DeleteOrTrash(NSString *path) { 405 | NSError *error; 406 | 407 | if ([[NSFileManager defaultManager] removeItemAtPath:path error:&error]) { 408 | return YES; 409 | } 410 | else { 411 | // Don't log warning if on Sierra and running inside App Translocation path 412 | if (![path containsString:@"/AppTranslocation/"]) 413 | NSLog(@"WARNING -- Could not delete '%@': %@", path, [error localizedDescription]); 414 | 415 | return Trash(path); 416 | } 417 | } 418 | 419 | static BOOL AuthorizedInstall(NSString *srcPath, NSString *dstPath, BOOL *canceled) { 420 | if (canceled) *canceled = NO; 421 | 422 | // Make sure that the destination path is an app bundle. We're essentially running 'sudo rm -rf' 423 | // so we really don't want to fuck this up. 424 | if (![[dstPath pathExtension] isEqualToString:@"app"]) return NO; 425 | 426 | // Do some more checks 427 | if ([[dstPath stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length] == 0) return NO; 428 | if ([[srcPath stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length] == 0) return NO; 429 | 430 | int pid, status; 431 | AuthorizationRef myAuthorizationRef; 432 | 433 | // Get the authorization 434 | OSStatus err = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &myAuthorizationRef); 435 | if (err != errAuthorizationSuccess) return NO; 436 | 437 | AuthorizationItem myItems = {kAuthorizationRightExecute, 0, NULL, 0}; 438 | AuthorizationRights myRights = {1, &myItems}; 439 | AuthorizationFlags myFlags = (AuthorizationFlags)(kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights | kAuthorizationFlagPreAuthorize); 440 | 441 | err = AuthorizationCopyRights(myAuthorizationRef, &myRights, NULL, myFlags, NULL); 442 | if (err != errAuthorizationSuccess) { 443 | if (err == errAuthorizationCanceled && canceled) 444 | *canceled = YES; 445 | goto fail; 446 | } 447 | 448 | static OSStatus (*security_AuthorizationExecuteWithPrivileges)(AuthorizationRef authorization, const char *pathToTool, 449 | AuthorizationFlags options, char * const *arguments, 450 | FILE **communicationsPipe) = NULL; 451 | if (!security_AuthorizationExecuteWithPrivileges) { 452 | // On 10.7, AuthorizationExecuteWithPrivileges is deprecated. We want to still use it since there's no 453 | // good alternative (without requiring code signing). We'll look up the function through dyld and fail 454 | // if it is no longer accessible. If Apple removes the function entirely this will fail gracefully. If 455 | // they keep the function and throw some sort of exception, this won't fail gracefully, but that's a 456 | // risk we'll have to take for now. 457 | security_AuthorizationExecuteWithPrivileges = (OSStatus (*)(AuthorizationRef, const char*, 458 | AuthorizationFlags, char* const*, 459 | FILE **)) dlsym(RTLD_DEFAULT, "AuthorizationExecuteWithPrivileges"); 460 | } 461 | if (!security_AuthorizationExecuteWithPrivileges) goto fail; 462 | 463 | // Delete the destination 464 | { 465 | char *args[] = {"-rf", (char *)[dstPath fileSystemRepresentation], NULL}; 466 | err = security_AuthorizationExecuteWithPrivileges(myAuthorizationRef, "/bin/rm", kAuthorizationFlagDefaults, args, NULL); 467 | if (err != errAuthorizationSuccess) goto fail; 468 | 469 | // Wait until it's done 470 | pid = wait(&status); 471 | if (pid == -1 || !WIFEXITED(status)) goto fail; // We don't care about exit status as the destination most likely does not exist 472 | } 473 | 474 | // Copy 475 | { 476 | char *args[] = {"-pR", (char *)[srcPath fileSystemRepresentation], (char *)[dstPath fileSystemRepresentation], NULL}; 477 | err = security_AuthorizationExecuteWithPrivileges(myAuthorizationRef, "/bin/cp", kAuthorizationFlagDefaults, args, NULL); 478 | if (err != errAuthorizationSuccess) goto fail; 479 | 480 | // Wait until it's done 481 | pid = wait(&status); 482 | if (pid == -1 || !WIFEXITED(status) || WEXITSTATUS(status)) goto fail; 483 | } 484 | 485 | AuthorizationFree(myAuthorizationRef, kAuthorizationFlagDefaults); 486 | return YES; 487 | 488 | fail: 489 | AuthorizationFree(myAuthorizationRef, kAuthorizationFlagDefaults); 490 | return NO; 491 | } 492 | 493 | static BOOL CopyBundle(NSString *srcPath, NSString *dstPath) { 494 | NSFileManager *fm = [NSFileManager defaultManager]; 495 | NSError *error = nil; 496 | 497 | if ([fm copyItemAtPath:srcPath toPath:dstPath error:&error]) { 498 | return YES; 499 | } 500 | else { 501 | NSLog(@"ERROR -- Could not copy '%@' to '%@' (%@)", srcPath, dstPath, error); 502 | return NO; 503 | } 504 | } 505 | 506 | static NSString *ShellQuotedString(NSString *string) { 507 | return [NSString stringWithFormat:@"'%@'", [string stringByReplacingOccurrencesOfString:@"'" withString:@"'\\''"]]; 508 | } 509 | 510 | static void Relaunch(NSString *destinationPath) { 511 | // The shell script waits until the original app process terminates. 512 | // This is done so that the relaunched app opens as the front-most app. 513 | int pid = [[NSProcessInfo processInfo] processIdentifier]; 514 | 515 | // Command run just before running open /final/path 516 | NSString *preOpenCmd = @""; 517 | 518 | NSString *quotedDestinationPath = ShellQuotedString(destinationPath); 519 | 520 | // OS X >=10.5: 521 | // Before we launch the new app, clear xattr:com.apple.quarantine to avoid 522 | // duplicate "scary file from the internet" dialog. 523 | if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_5) { 524 | // Add the -r flag on 10.6 525 | preOpenCmd = [NSString stringWithFormat:@"/usr/bin/xattr -d -r com.apple.quarantine %@", quotedDestinationPath]; 526 | } 527 | else { 528 | preOpenCmd = [NSString stringWithFormat:@"/usr/bin/xattr -d com.apple.quarantine %@", quotedDestinationPath]; 529 | } 530 | 531 | NSString *script = [NSString stringWithFormat:@"(while /bin/kill -0 %d >&/dev/null; do /bin/sleep 0.1; done; %@; /usr/bin/open %@) &", pid, preOpenCmd, quotedDestinationPath]; 532 | 533 | [NSTask launchedTaskWithLaunchPath:@"/bin/sh" arguments:[NSArray arrayWithObjects:@"-c", script, nil]]; 534 | } 535 | -------------------------------------------------------------------------------- /Sub It.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0A11B1E520A87CB9007D77BF /* ProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A11B1E420A87CB9007D77BF /* ProgressView.swift */; }; 11 | 0A244C9A1E50BBE000907042 /* optionsTextfield.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A244C991E50BBE000907042 /* optionsTextfield.swift */; }; 12 | 0A244C9C1E50C6CB00907042 /* dropView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A244C9B1E50C6CB00907042 /* dropView.swift */; }; 13 | 0A3153191CF37A660020DBB8 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A3153181CF37A660020DBB8 /* AppDelegate.swift */; }; 14 | 0A31531B1CF37A660020DBB8 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A31531A1CF37A660020DBB8 /* ViewController.swift */; }; 15 | 0A31531D1CF37A660020DBB8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0A31531C1CF37A660020DBB8 /* Assets.xcassets */; }; 16 | 0A3153201CF37A660020DBB8 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0A31531E1CF37A660020DBB8 /* Main.storyboard */; }; 17 | 0A59C26E1E3D01A700E40A2B /* WindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A59C26D1E3D01A700E40A2B /* WindowController.swift */; }; 18 | 0A59C2701E3D01F400E40A2B /* OptionsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A59C26F1E3D01F400E40A2B /* OptionsViewController.swift */; }; 19 | 0A59C2721E3D09CE00E40A2B /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A59C2711E3D09CE00E40A2B /* Constants.swift */; }; 20 | 0A59C2741E3D0C0E00E40A2B /* SubIt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A59C2731E3D0C0E00E40A2B /* SubIt.swift */; }; 21 | 0A8DA5DA1E3E808500148315 /* AboutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A8DA5D91E3E808500148315 /* AboutViewController.swift */; }; 22 | 0AAC75B61E3E24800086BB87 /* DownloadButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AAC75B51E3E24800086BB87 /* DownloadButton.swift */; }; 23 | 0AAC75B81E3E25820086BB87 /* GrayButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AAC75B71E3E25820086BB87 /* GrayButton.swift */; }; 24 | 0AF763CF1E474D2A00403BA1 /* InstallationGuideViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF763CD1E474D2A00403BA1 /* InstallationGuideViewController.swift */; }; 25 | 0AF763D21E476D4C00403BA1 /* openTerminalButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF763D11E476D4C00403BA1 /* openTerminalButton.swift */; }; 26 | 0AF763D41E47B90D00403BA1 /* InstallationGuideTexts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF763D31E47B90D00403BA1 /* InstallationGuideTexts.swift */; }; 27 | 0AF763D61E47C71500403BA1 /* installationGuideTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF763D51E47C71500403BA1 /* installationGuideTextField.swift */; }; 28 | E1CB81EBC24956F46D360362 /* Pods_Sub_It.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43E40AE6E2BF3D1F280A511D /* Pods_Sub_It.framework */; }; 29 | /* End PBXBuildFile section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | 06FB12017990FFC819383928 /* Pods-Sub It.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sub It.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Sub It/Pods-Sub It.debug.xcconfig"; sourceTree = ""; }; 33 | 0A11B1E420A87CB9007D77BF /* ProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressView.swift; sourceTree = ""; }; 34 | 0A244C991E50BBE000907042 /* optionsTextfield.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = optionsTextfield.swift; sourceTree = ""; }; 35 | 0A244C9B1E50C6CB00907042 /* dropView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = dropView.swift; sourceTree = ""; }; 36 | 0A3153151CF37A660020DBB8 /* Sub It.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Sub It.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 37 | 0A3153181CF37A660020DBB8 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 38 | 0A31531A1CF37A660020DBB8 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 39 | 0A31531C1CF37A660020DBB8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 40 | 0A31531F1CF37A660020DBB8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 41 | 0A3153211CF37A660020DBB8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 42 | 0A59C26D1E3D01A700E40A2B /* WindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WindowController.swift; sourceTree = ""; }; 43 | 0A59C26F1E3D01F400E40A2B /* OptionsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OptionsViewController.swift; sourceTree = ""; }; 44 | 0A59C2711E3D09CE00E40A2B /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; 45 | 0A59C2731E3D0C0E00E40A2B /* SubIt.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubIt.swift; sourceTree = ""; }; 46 | 0A8DA5D91E3E808500148315 /* AboutViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AboutViewController.swift; sourceTree = ""; }; 47 | 0AAC75B51E3E24800086BB87 /* DownloadButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownloadButton.swift; sourceTree = ""; }; 48 | 0AAC75B71E3E25820086BB87 /* GrayButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GrayButton.swift; sourceTree = ""; }; 49 | 0AF763CD1E474D2A00403BA1 /* InstallationGuideViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InstallationGuideViewController.swift; sourceTree = ""; }; 50 | 0AF763D11E476D4C00403BA1 /* openTerminalButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = openTerminalButton.swift; sourceTree = ""; }; 51 | 0AF763D31E47B90D00403BA1 /* InstallationGuideTexts.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InstallationGuideTexts.swift; sourceTree = ""; }; 52 | 0AF763D51E47C71500403BA1 /* installationGuideTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = installationGuideTextField.swift; sourceTree = ""; }; 53 | 2F2FF097A134B03DBD16D354 /* Pods-Youtube-dl-GUI.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Youtube-dl-GUI.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Youtube-dl-GUI/Pods-Youtube-dl-GUI.debug.xcconfig"; sourceTree = ""; }; 54 | 3D0235652B5434027EFB9C78 /* Pods-Get It.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Get It.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Get It/Pods-Get It.debug.xcconfig"; sourceTree = ""; }; 55 | 3F840AEEA491FC0DE6DE63CC /* Pods_Get_It.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Get_It.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 56 | 43E40AE6E2BF3D1F280A511D /* Pods_Sub_It.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Sub_It.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 685C0FDD28B58EDB6BF51860 /* Pods_Youtube_dl_GUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Youtube_dl_GUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | A365635D80B3EAADF2E92571 /* Pods-Sub It.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sub It.release.xcconfig"; path = "Pods/Target Support Files/Pods-Sub It/Pods-Sub It.release.xcconfig"; sourceTree = ""; }; 59 | D8AD15C7EEEEB58800AD01EB /* Pods-Get It.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Get It.release.xcconfig"; path = "Pods/Target Support Files/Pods-Get It/Pods-Get It.release.xcconfig"; sourceTree = ""; }; 60 | E0AC0061A8071094C1AD4E53 /* Pods-Youtube-dl-GUI.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Youtube-dl-GUI.release.xcconfig"; path = "Pods/Target Support Files/Pods-Youtube-dl-GUI/Pods-Youtube-dl-GUI.release.xcconfig"; sourceTree = ""; }; 61 | /* End PBXFileReference section */ 62 | 63 | /* Begin PBXFrameworksBuildPhase section */ 64 | 0A3153121CF37A660020DBB8 /* Frameworks */ = { 65 | isa = PBXFrameworksBuildPhase; 66 | buildActionMask = 2147483647; 67 | files = ( 68 | E1CB81EBC24956F46D360362 /* Pods_Sub_It.framework in Frameworks */, 69 | ); 70 | runOnlyForDeploymentPostprocessing = 0; 71 | }; 72 | /* End PBXFrameworksBuildPhase section */ 73 | 74 | /* Begin PBXGroup section */ 75 | 0A31530C1CF37A660020DBB8 = { 76 | isa = PBXGroup; 77 | children = ( 78 | 0A3153171CF37A660020DBB8 /* Sub It */, 79 | 0A3153161CF37A660020DBB8 /* Products */, 80 | 75A610843FD48A3979701E9A /* Pods */, 81 | 6D963A9BD010E4E700CDC28B /* Frameworks */, 82 | ); 83 | sourceTree = ""; 84 | }; 85 | 0A3153161CF37A660020DBB8 /* Products */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | 0A3153151CF37A660020DBB8 /* Sub It.app */, 89 | ); 90 | name = Products; 91 | sourceTree = ""; 92 | }; 93 | 0A3153171CF37A660020DBB8 /* Sub It */ = { 94 | isa = PBXGroup; 95 | children = ( 96 | 0A59C26C1E3D002900E40A2B /* Constants and Text */, 97 | 0A59C26B1E3D001200E40A2B /* Model */, 98 | 0A59C26A1E3D000E00E40A2B /* View */, 99 | 0A59C2691E3D000800E40A2B /* Controller */, 100 | 0A31531C1CF37A660020DBB8 /* Assets.xcassets */, 101 | 0A3153211CF37A660020DBB8 /* Info.plist */, 102 | ); 103 | path = "Sub It"; 104 | sourceTree = ""; 105 | }; 106 | 0A59C2691E3D000800E40A2B /* Controller */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | 0A31531A1CF37A660020DBB8 /* ViewController.swift */, 110 | 0A3153181CF37A660020DBB8 /* AppDelegate.swift */, 111 | 0A59C26D1E3D01A700E40A2B /* WindowController.swift */, 112 | 0A59C26F1E3D01F400E40A2B /* OptionsViewController.swift */, 113 | 0A8DA5D91E3E808500148315 /* AboutViewController.swift */, 114 | 0AF763CD1E474D2A00403BA1 /* InstallationGuideViewController.swift */, 115 | ); 116 | name = Controller; 117 | sourceTree = ""; 118 | }; 119 | 0A59C26A1E3D000E00E40A2B /* View */ = { 120 | isa = PBXGroup; 121 | children = ( 122 | 0A31531E1CF37A660020DBB8 /* Main.storyboard */, 123 | 0AAC75B51E3E24800086BB87 /* DownloadButton.swift */, 124 | 0AAC75B71E3E25820086BB87 /* GrayButton.swift */, 125 | 0A244C991E50BBE000907042 /* optionsTextfield.swift */, 126 | 0AF763D11E476D4C00403BA1 /* openTerminalButton.swift */, 127 | 0AF763D51E47C71500403BA1 /* installationGuideTextField.swift */, 128 | 0A244C9B1E50C6CB00907042 /* dropView.swift */, 129 | 0A11B1E420A87CB9007D77BF /* ProgressView.swift */, 130 | ); 131 | name = View; 132 | sourceTree = ""; 133 | }; 134 | 0A59C26B1E3D001200E40A2B /* Model */ = { 135 | isa = PBXGroup; 136 | children = ( 137 | 0A59C2731E3D0C0E00E40A2B /* SubIt.swift */, 138 | ); 139 | name = Model; 140 | sourceTree = ""; 141 | }; 142 | 0A59C26C1E3D002900E40A2B /* Constants and Text */ = { 143 | isa = PBXGroup; 144 | children = ( 145 | 0A59C2711E3D09CE00E40A2B /* Constants.swift */, 146 | 0AF763D31E47B90D00403BA1 /* InstallationGuideTexts.swift */, 147 | ); 148 | name = "Constants and Text"; 149 | sourceTree = ""; 150 | }; 151 | 6D963A9BD010E4E700CDC28B /* Frameworks */ = { 152 | isa = PBXGroup; 153 | children = ( 154 | 685C0FDD28B58EDB6BF51860 /* Pods_Youtube_dl_GUI.framework */, 155 | 3F840AEEA491FC0DE6DE63CC /* Pods_Get_It.framework */, 156 | 43E40AE6E2BF3D1F280A511D /* Pods_Sub_It.framework */, 157 | ); 158 | name = Frameworks; 159 | sourceTree = ""; 160 | }; 161 | 75A610843FD48A3979701E9A /* Pods */ = { 162 | isa = PBXGroup; 163 | children = ( 164 | 2F2FF097A134B03DBD16D354 /* Pods-Youtube-dl-GUI.debug.xcconfig */, 165 | E0AC0061A8071094C1AD4E53 /* Pods-Youtube-dl-GUI.release.xcconfig */, 166 | 3D0235652B5434027EFB9C78 /* Pods-Get It.debug.xcconfig */, 167 | D8AD15C7EEEEB58800AD01EB /* Pods-Get It.release.xcconfig */, 168 | 06FB12017990FFC819383928 /* Pods-Sub It.debug.xcconfig */, 169 | A365635D80B3EAADF2E92571 /* Pods-Sub It.release.xcconfig */, 170 | ); 171 | name = Pods; 172 | sourceTree = ""; 173 | }; 174 | /* End PBXGroup section */ 175 | 176 | /* Begin PBXNativeTarget section */ 177 | 0A3153141CF37A660020DBB8 /* Sub It */ = { 178 | isa = PBXNativeTarget; 179 | buildConfigurationList = 0A31533A1CF37A660020DBB8 /* Build configuration list for PBXNativeTarget "Sub It" */; 180 | buildPhases = ( 181 | 8EF4B3A8A704C93C8E5590DF /* [CP] Check Pods Manifest.lock */, 182 | 0A3153111CF37A660020DBB8 /* Sources */, 183 | 0A3153121CF37A660020DBB8 /* Frameworks */, 184 | 0A3153131CF37A660020DBB8 /* Resources */, 185 | A74C311D5C3277F0388523F0 /* [CP] Embed Pods Frameworks */, 186 | ); 187 | buildRules = ( 188 | ); 189 | dependencies = ( 190 | ); 191 | name = "Sub It"; 192 | productName = "Youtube-dl-GUI"; 193 | productReference = 0A3153151CF37A660020DBB8 /* Sub It.app */; 194 | productType = "com.apple.product-type.application"; 195 | }; 196 | /* End PBXNativeTarget section */ 197 | 198 | /* Begin PBXProject section */ 199 | 0A31530D1CF37A660020DBB8 /* Project object */ = { 200 | isa = PBXProject; 201 | attributes = { 202 | LastSwiftUpdateCheck = 0730; 203 | LastUpgradeCheck = 0820; 204 | ORGANIZATIONNAME = "Kevin De Koninck"; 205 | TargetAttributes = { 206 | 0A3153141CF37A660020DBB8 = { 207 | CreatedOnToolsVersion = 7.3.1; 208 | LastSwiftMigration = 0820; 209 | SystemCapabilities = { 210 | com.apple.Sandbox = { 211 | enabled = 0; 212 | }; 213 | }; 214 | }; 215 | }; 216 | }; 217 | buildConfigurationList = 0A3153101CF37A660020DBB8 /* Build configuration list for PBXProject "Sub It" */; 218 | compatibilityVersion = "Xcode 3.2"; 219 | developmentRegion = English; 220 | hasScannedForEncodings = 0; 221 | knownRegions = ( 222 | en, 223 | Base, 224 | ); 225 | mainGroup = 0A31530C1CF37A660020DBB8; 226 | productRefGroup = 0A3153161CF37A660020DBB8 /* Products */; 227 | projectDirPath = ""; 228 | projectRoot = ""; 229 | targets = ( 230 | 0A3153141CF37A660020DBB8 /* Sub It */, 231 | ); 232 | }; 233 | /* End PBXProject section */ 234 | 235 | /* Begin PBXResourcesBuildPhase section */ 236 | 0A3153131CF37A660020DBB8 /* Resources */ = { 237 | isa = PBXResourcesBuildPhase; 238 | buildActionMask = 2147483647; 239 | files = ( 240 | 0A31531D1CF37A660020DBB8 /* Assets.xcassets in Resources */, 241 | 0A3153201CF37A660020DBB8 /* Main.storyboard in Resources */, 242 | ); 243 | runOnlyForDeploymentPostprocessing = 0; 244 | }; 245 | /* End PBXResourcesBuildPhase section */ 246 | 247 | /* Begin PBXShellScriptBuildPhase section */ 248 | 8EF4B3A8A704C93C8E5590DF /* [CP] Check Pods Manifest.lock */ = { 249 | isa = PBXShellScriptBuildPhase; 250 | buildActionMask = 2147483647; 251 | files = ( 252 | ); 253 | inputPaths = ( 254 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 255 | "${PODS_ROOT}/Manifest.lock", 256 | ); 257 | name = "[CP] Check Pods Manifest.lock"; 258 | outputPaths = ( 259 | "$(DERIVED_FILE_DIR)/Pods-Sub It-checkManifestLockResult.txt", 260 | ); 261 | runOnlyForDeploymentPostprocessing = 0; 262 | shellPath = /bin/sh; 263 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 264 | showEnvVarsInLog = 0; 265 | }; 266 | A74C311D5C3277F0388523F0 /* [CP] Embed Pods Frameworks */ = { 267 | isa = PBXShellScriptBuildPhase; 268 | buildActionMask = 2147483647; 269 | files = ( 270 | ); 271 | inputPaths = ( 272 | "${SRCROOT}/Pods/Target Support Files/Pods-Sub It/Pods-Sub It-frameworks.sh", 273 | "${BUILT_PRODUCTS_DIR}/ITSwitch/ITSwitch.framework", 274 | "${BUILT_PRODUCTS_DIR}/LetsMove/LetsMove.framework", 275 | ); 276 | name = "[CP] Embed Pods Frameworks"; 277 | outputPaths = ( 278 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ITSwitch.framework", 279 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/LetsMove.framework", 280 | ); 281 | runOnlyForDeploymentPostprocessing = 0; 282 | shellPath = /bin/sh; 283 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Sub It/Pods-Sub It-frameworks.sh\"\n"; 284 | showEnvVarsInLog = 0; 285 | }; 286 | /* End PBXShellScriptBuildPhase section */ 287 | 288 | /* Begin PBXSourcesBuildPhase section */ 289 | 0A3153111CF37A660020DBB8 /* Sources */ = { 290 | isa = PBXSourcesBuildPhase; 291 | buildActionMask = 2147483647; 292 | files = ( 293 | 0AAC75B61E3E24800086BB87 /* DownloadButton.swift in Sources */, 294 | 0A59C2721E3D09CE00E40A2B /* Constants.swift in Sources */, 295 | 0AF763D21E476D4C00403BA1 /* openTerminalButton.swift in Sources */, 296 | 0AAC75B81E3E25820086BB87 /* GrayButton.swift in Sources */, 297 | 0A244C9C1E50C6CB00907042 /* dropView.swift in Sources */, 298 | 0A244C9A1E50BBE000907042 /* optionsTextfield.swift in Sources */, 299 | 0A8DA5DA1E3E808500148315 /* AboutViewController.swift in Sources */, 300 | 0AF763D61E47C71500403BA1 /* installationGuideTextField.swift in Sources */, 301 | 0A31531B1CF37A660020DBB8 /* ViewController.swift in Sources */, 302 | 0A59C2701E3D01F400E40A2B /* OptionsViewController.swift in Sources */, 303 | 0A59C26E1E3D01A700E40A2B /* WindowController.swift in Sources */, 304 | 0A3153191CF37A660020DBB8 /* AppDelegate.swift in Sources */, 305 | 0A59C2741E3D0C0E00E40A2B /* SubIt.swift in Sources */, 306 | 0A11B1E520A87CB9007D77BF /* ProgressView.swift in Sources */, 307 | 0AF763CF1E474D2A00403BA1 /* InstallationGuideViewController.swift in Sources */, 308 | 0AF763D41E47B90D00403BA1 /* InstallationGuideTexts.swift in Sources */, 309 | ); 310 | runOnlyForDeploymentPostprocessing = 0; 311 | }; 312 | /* End PBXSourcesBuildPhase section */ 313 | 314 | /* Begin PBXVariantGroup section */ 315 | 0A31531E1CF37A660020DBB8 /* Main.storyboard */ = { 316 | isa = PBXVariantGroup; 317 | children = ( 318 | 0A31531F1CF37A660020DBB8 /* Base */, 319 | ); 320 | name = Main.storyboard; 321 | sourceTree = ""; 322 | }; 323 | /* End PBXVariantGroup section */ 324 | 325 | /* Begin XCBuildConfiguration section */ 326 | 0A3153381CF37A660020DBB8 /* Debug */ = { 327 | isa = XCBuildConfiguration; 328 | buildSettings = { 329 | ALWAYS_SEARCH_USER_PATHS = NO; 330 | CLANG_ANALYZER_NONNULL = YES; 331 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 332 | CLANG_CXX_LIBRARY = "libc++"; 333 | CLANG_ENABLE_MODULES = YES; 334 | CLANG_ENABLE_OBJC_ARC = YES; 335 | CLANG_WARN_BOOL_CONVERSION = YES; 336 | CLANG_WARN_CONSTANT_CONVERSION = YES; 337 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 338 | CLANG_WARN_EMPTY_BODY = YES; 339 | CLANG_WARN_ENUM_CONVERSION = YES; 340 | CLANG_WARN_INFINITE_RECURSION = YES; 341 | CLANG_WARN_INT_CONVERSION = YES; 342 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 343 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 344 | CLANG_WARN_UNREACHABLE_CODE = YES; 345 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 346 | CODE_SIGN_IDENTITY = "-"; 347 | COPY_PHASE_STRIP = NO; 348 | DEBUG_INFORMATION_FORMAT = dwarf; 349 | ENABLE_STRICT_OBJC_MSGSEND = YES; 350 | ENABLE_TESTABILITY = YES; 351 | GCC_C_LANGUAGE_STANDARD = gnu99; 352 | GCC_DYNAMIC_NO_PIC = NO; 353 | GCC_NO_COMMON_BLOCKS = YES; 354 | GCC_OPTIMIZATION_LEVEL = 0; 355 | GCC_PREPROCESSOR_DEFINITIONS = ( 356 | "DEBUG=1", 357 | "$(inherited)", 358 | ); 359 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 360 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 361 | GCC_WARN_UNDECLARED_SELECTOR = YES; 362 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 363 | GCC_WARN_UNUSED_FUNCTION = YES; 364 | GCC_WARN_UNUSED_VARIABLE = YES; 365 | MACOSX_DEPLOYMENT_TARGET = 10.11; 366 | MTL_ENABLE_DEBUG_INFO = YES; 367 | ONLY_ACTIVE_ARCH = YES; 368 | SDKROOT = macosx; 369 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 370 | }; 371 | name = Debug; 372 | }; 373 | 0A3153391CF37A660020DBB8 /* Release */ = { 374 | isa = XCBuildConfiguration; 375 | buildSettings = { 376 | ALWAYS_SEARCH_USER_PATHS = NO; 377 | CLANG_ANALYZER_NONNULL = YES; 378 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 379 | CLANG_CXX_LIBRARY = "libc++"; 380 | CLANG_ENABLE_MODULES = YES; 381 | CLANG_ENABLE_OBJC_ARC = YES; 382 | CLANG_WARN_BOOL_CONVERSION = YES; 383 | CLANG_WARN_CONSTANT_CONVERSION = YES; 384 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 385 | CLANG_WARN_EMPTY_BODY = YES; 386 | CLANG_WARN_ENUM_CONVERSION = YES; 387 | CLANG_WARN_INFINITE_RECURSION = YES; 388 | CLANG_WARN_INT_CONVERSION = YES; 389 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 390 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 391 | CLANG_WARN_UNREACHABLE_CODE = YES; 392 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 393 | CODE_SIGN_IDENTITY = "-"; 394 | COPY_PHASE_STRIP = NO; 395 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 396 | ENABLE_NS_ASSERTIONS = NO; 397 | ENABLE_STRICT_OBJC_MSGSEND = YES; 398 | GCC_C_LANGUAGE_STANDARD = gnu99; 399 | GCC_NO_COMMON_BLOCKS = YES; 400 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 401 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 402 | GCC_WARN_UNDECLARED_SELECTOR = YES; 403 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 404 | GCC_WARN_UNUSED_FUNCTION = YES; 405 | GCC_WARN_UNUSED_VARIABLE = YES; 406 | MACOSX_DEPLOYMENT_TARGET = 10.11; 407 | MTL_ENABLE_DEBUG_INFO = NO; 408 | SDKROOT = macosx; 409 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 410 | }; 411 | name = Release; 412 | }; 413 | 0A31533B1CF37A660020DBB8 /* Debug */ = { 414 | isa = XCBuildConfiguration; 415 | baseConfigurationReference = 06FB12017990FFC819383928 /* Pods-Sub It.debug.xcconfig */; 416 | buildSettings = { 417 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 418 | COMBINE_HIDPI_IMAGES = YES; 419 | INFOPLIST_FILE = "$(SRCROOT)/Sub It/Info.plist"; 420 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 421 | MACOSX_DEPLOYMENT_TARGET = 10.11; 422 | PRODUCT_BUNDLE_IDENTIFIER = com.KevinDeKoninck.SubIt; 423 | PRODUCT_NAME = "$(TARGET_NAME)"; 424 | SWIFT_VERSION = 3.0; 425 | }; 426 | name = Debug; 427 | }; 428 | 0A31533C1CF37A660020DBB8 /* Release */ = { 429 | isa = XCBuildConfiguration; 430 | baseConfigurationReference = A365635D80B3EAADF2E92571 /* Pods-Sub It.release.xcconfig */; 431 | buildSettings = { 432 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 433 | COMBINE_HIDPI_IMAGES = YES; 434 | INFOPLIST_FILE = "$(SRCROOT)/Sub It/Info.plist"; 435 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 436 | MACOSX_DEPLOYMENT_TARGET = 10.11; 437 | PRODUCT_BUNDLE_IDENTIFIER = com.KevinDeKoninck.SubIt; 438 | PRODUCT_NAME = "$(TARGET_NAME)"; 439 | SWIFT_VERSION = 3.0; 440 | }; 441 | name = Release; 442 | }; 443 | /* End XCBuildConfiguration section */ 444 | 445 | /* Begin XCConfigurationList section */ 446 | 0A3153101CF37A660020DBB8 /* Build configuration list for PBXProject "Sub It" */ = { 447 | isa = XCConfigurationList; 448 | buildConfigurations = ( 449 | 0A3153381CF37A660020DBB8 /* Debug */, 450 | 0A3153391CF37A660020DBB8 /* Release */, 451 | ); 452 | defaultConfigurationIsVisible = 0; 453 | defaultConfigurationName = Release; 454 | }; 455 | 0A31533A1CF37A660020DBB8 /* Build configuration list for PBXNativeTarget "Sub It" */ = { 456 | isa = XCConfigurationList; 457 | buildConfigurations = ( 458 | 0A31533B1CF37A660020DBB8 /* Debug */, 459 | 0A31533C1CF37A660020DBB8 /* Release */, 460 | ); 461 | defaultConfigurationIsVisible = 0; 462 | defaultConfigurationName = Release; 463 | }; 464 | /* End XCConfigurationList section */ 465 | }; 466 | rootObject = 0A31530D1CF37A660020DBB8 /* Project object */; 467 | } 468 | --------------------------------------------------------------------------------