├── airslide
├── Assets.xcassets
│ ├── Contents.json
│ └── AppIcon.appiconset
│ │ ├── 1024-128.png
│ │ ├── 1024-16.png
│ │ ├── 1024-256.png
│ │ ├── 1024-32.png
│ │ ├── 1024-512.png
│ │ ├── 1024-64.png
│ │ ├── 1024-1024.png
│ │ └── Contents.json
├── nologin.sh
├── login.sh
├── Info.plist
├── airslide.entitlements
├── Credits.rtf
├── PreferenceViewController.swift
├── Base.lproj
│ └── Main.storyboard
└── AppDelegate.swift
├── AirSlide.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcuserdata
│ │ └── lucas.xcuserdatad
│ │ │ ├── UserInterfaceState.xcuserstate
│ │ │ └── WorkspaceSettings.xcsettings
│ └── xcshareddata
│ │ ├── WorkspaceSettings.xcsettings
│ │ └── IDEWorkspaceChecks.plist
├── xcuserdata
│ └── lucas.xcuserdatad
│ │ ├── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
├── xcshareddata
│ └── xcschemes
│ │ └── AirSlide.xcscheme
└── project.pbxproj
├── airslideUITests
├── airslideUITestsLaunchTests.swift
└── airslideUITests.swift
├── README.md
└── airslideTests
└── airslideTests.swift
/airslide/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/airslide/nologin.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | osascript -e 'tell application "System Events" to delete login item "Airslide"'
3 |
4 |
5 |
--------------------------------------------------------------------------------
/airslide/Assets.xcassets/AppIcon.appiconset/1024-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mmmago/airslide/HEAD/airslide/Assets.xcassets/AppIcon.appiconset/1024-128.png
--------------------------------------------------------------------------------
/airslide/Assets.xcassets/AppIcon.appiconset/1024-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mmmago/airslide/HEAD/airslide/Assets.xcassets/AppIcon.appiconset/1024-16.png
--------------------------------------------------------------------------------
/airslide/Assets.xcassets/AppIcon.appiconset/1024-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mmmago/airslide/HEAD/airslide/Assets.xcassets/AppIcon.appiconset/1024-256.png
--------------------------------------------------------------------------------
/airslide/Assets.xcassets/AppIcon.appiconset/1024-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mmmago/airslide/HEAD/airslide/Assets.xcassets/AppIcon.appiconset/1024-32.png
--------------------------------------------------------------------------------
/airslide/Assets.xcassets/AppIcon.appiconset/1024-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mmmago/airslide/HEAD/airslide/Assets.xcassets/AppIcon.appiconset/1024-512.png
--------------------------------------------------------------------------------
/airslide/Assets.xcassets/AppIcon.appiconset/1024-64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mmmago/airslide/HEAD/airslide/Assets.xcassets/AppIcon.appiconset/1024-64.png
--------------------------------------------------------------------------------
/airslide/Assets.xcassets/AppIcon.appiconset/1024-1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mmmago/airslide/HEAD/airslide/Assets.xcassets/AppIcon.appiconset/1024-1024.png
--------------------------------------------------------------------------------
/airslide/login.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | osascript -e 'tell application "System Events" to make login item at end with properties {path:"/Applications/Airslide.app", hidden:false}'
3 |
--------------------------------------------------------------------------------
/AirSlide.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/airslide/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/AirSlide.xcodeproj/project.xcworkspace/xcuserdata/lucas.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mmmago/airslide/HEAD/AirSlide.xcodeproj/project.xcworkspace/xcuserdata/lucas.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/AirSlide.xcodeproj/xcuserdata/lucas.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/airslide/airslide.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.automation.apple-events
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/AirSlide.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/AirSlide.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/airslide/Credits.rtf:
--------------------------------------------------------------------------------
1 | {\rtf1\ansi\ansicpg1252\cocoartf2639
2 | \cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
3 | {\colortbl;\red255\green255\blue255;}
4 | {\*\expandedcolortbl;;}
5 | \paperw11900\paperh16840\margl1440\margr1440\vieww11520\viewh8400\viewkind0
6 | \pard\tx566\tx1133\tx1700\tx2267\tqr\tx2623\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\qc\partightenfactor0
7 |
8 | \f0\fs24 \cf0 Copyright \'a9 2023 mago. All rights reserved.}
--------------------------------------------------------------------------------
/AirSlide.xcodeproj/project.xcworkspace/xcuserdata/lucas.xcuserdatad/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildLocationStyle
6 | UseAppPreferences
7 | CustomBuildLocationType
8 | RelativeToDerivedData
9 | DerivedDataLocationStyle
10 | Default
11 | ShowSharedSchemesAutomaticallyEnabled
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/airslideUITests/airslideUITestsLaunchTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // airslideUITestsLaunchTests.swift
3 | // airslideUITests
4 | //
5 | // Created by Lucas on 26/01/2023.
6 | //
7 |
8 | import XCTest
9 |
10 | final class airslideUITestsLaunchTests: XCTestCase {
11 |
12 | override class var runsForEachTargetApplicationUIConfiguration: Bool {
13 | true
14 | }
15 |
16 | override func setUpWithError() throws {
17 | continueAfterFailure = false
18 | }
19 |
20 | func testLaunch() throws {
21 | let app = XCUIApplication()
22 | app.launch()
23 |
24 | // Insert steps here to perform after app launch but before taking a screenshot,
25 | // such as logging into a test account or navigating somewhere in the app
26 |
27 | let attachment = XCTAttachment(screenshot: app.screenshot())
28 | attachment.name = "Launch Screen"
29 | attachment.lifetime = .keepAlways
30 | add(attachment)
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/AirSlide.xcodeproj/xcuserdata/lucas.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | AirSlide.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 | airslide.xcscheme_^#shared#^_
13 |
14 | orderHint
15 | 0
16 |
17 |
18 | SuppressBuildableAutocreation
19 |
20 | A0EFF9F329833873002FF9B5
21 |
22 | primary
23 |
24 |
25 | A0EFFA0429833873002FF9B5
26 |
27 | primary
28 |
29 |
30 | A0EFFA0E29833873002FF9B5
31 |
32 | primary
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | #
AirSlide
4 |
5 |
6 |
7 |
8 | Quick notch action to airdrop items. Free and open source alternative to [TopDrop](https://apps.apple.com/us/app/topdrop/id1630456052?mt=12).
9 |
10 |
11 | 
12 |
13 | App will ask for access to automations and accessibility settings, please allow both.
14 |
15 | ## Work in progress
16 |
17 | 🟩 14" MBP
18 |
19 | 🟧 16" MBP and MacBook Air M2 (13" and 15") compatibility (need feedbacks !). I don't have acess to these machines so it's pretty much trial and error.
20 |
21 | User experience on any other mac without notch may vary, might implement a solution later on.
22 |
23 | # Useful Tools
24 |
25 | - [ChatGPT](https://chat.openai.com/chat/)
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/airslideTests/airslideTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // airslideTests.swift
3 | // airslideTests
4 | //
5 | // Created by Lucas on 26/01/2023.
6 | //
7 |
8 | import XCTest
9 | @testable import airslide
10 |
11 | final class airslideTests: XCTestCase {
12 |
13 | override func setUpWithError() throws {
14 | // Put setup code here. This method is called before the invocation of each test method in the class.
15 | }
16 |
17 | override func tearDownWithError() throws {
18 | // Put teardown code here. This method is called after the invocation of each test method in the class.
19 | }
20 |
21 | func testExample() throws {
22 | // This is an example of a functional test case.
23 | // Use XCTAssert and related functions to verify your tests produce the correct results.
24 | // Any test you write for XCTest can be annotated as throws and async.
25 | // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error.
26 | // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
27 | }
28 |
29 | func testPerformanceExample() throws {
30 | // This is an example of a performance test case.
31 | self.measure {
32 | // Put the code you want to measure the time of here.
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/airslideUITests/airslideUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // airslideUITests.swift
3 | // airslideUITests
4 | //
5 | // Created by Lucas on 26/01/2023.
6 | //
7 |
8 | import XCTest
9 |
10 | final class airslideUITests: XCTestCase {
11 |
12 | override func setUpWithError() throws {
13 | // Put setup code here. This method is called before the invocation of each test method in the class.
14 |
15 | // In UI tests it is usually best to stop immediately when a failure occurs.
16 | continueAfterFailure = false
17 |
18 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
19 | }
20 |
21 | override func tearDownWithError() throws {
22 | // Put teardown code here. This method is called after the invocation of each test method in the class.
23 | }
24 |
25 | func testExample() throws {
26 | // UI tests must launch the application that they test.
27 | let app = XCUIApplication()
28 | app.launch()
29 |
30 | // Use XCTAssert and related functions to verify your tests produce the correct results.
31 | }
32 |
33 | func testLaunchPerformance() throws {
34 | if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
35 | // This measures how long it takes to launch your application.
36 | measure(metrics: [XCTApplicationLaunchMetric()]) {
37 | XCUIApplication().launch()
38 | }
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/airslide/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "16x16",
5 | "idiom" : "mac",
6 | "filename" : "1024-16.png",
7 | "scale" : "1x"
8 | },
9 | {
10 | "size" : "16x16",
11 | "idiom" : "mac",
12 | "filename" : "1024-32.png",
13 | "scale" : "2x"
14 | },
15 | {
16 | "size" : "32x32",
17 | "idiom" : "mac",
18 | "filename" : "1024-32.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "32x32",
23 | "idiom" : "mac",
24 | "filename" : "1024-64.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "128x128",
29 | "idiom" : "mac",
30 | "filename" : "1024-128.png",
31 | "scale" : "1x"
32 | },
33 | {
34 | "size" : "128x128",
35 | "idiom" : "mac",
36 | "filename" : "1024-256.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "256x256",
41 | "idiom" : "mac",
42 | "filename" : "1024-256.png",
43 | "scale" : "1x"
44 | },
45 | {
46 | "size" : "256x256",
47 | "idiom" : "mac",
48 | "filename" : "1024-512.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "512x512",
53 | "idiom" : "mac",
54 | "filename" : "1024-512.png",
55 | "scale" : "1x"
56 | },
57 | {
58 | "size" : "512x512",
59 | "idiom" : "mac",
60 | "filename" : "1024-1024.png",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/AirSlide.xcodeproj/xcshareddata/xcschemes/AirSlide.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
34 |
40 |
41 |
42 |
45 |
51 |
52 |
53 |
54 |
55 |
65 |
67 |
73 |
74 |
75 |
76 |
82 |
84 |
90 |
91 |
92 |
93 |
95 |
96 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/airslide/PreferenceViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // airslide
4 | //
5 | // Created by Lucas on 26/01/2023.
6 | //
7 |
8 | import Cocoa
9 |
10 |
11 | let userDefaults = UserDefaults.standard
12 |
13 |
14 | class PreferenceViewController: NSViewController {
15 |
16 | @IBOutlet weak var openatlogin: NSButton!
17 | @IBOutlet weak var hideicon: NSButton!
18 | @IBOutlet weak var soundlist: NSComboBoxCell!
19 | @IBOutlet weak var support: NSButton!
20 | @IBOutlet weak var quitapp: NSButton!
21 |
22 | @IBAction func openatlogin(_ sender: Any) {
23 |
24 | if openatlogin.state == .on {
25 |
26 | if Bundle.main.bundlePath == "/Applications/AirSlide.app"{
27 | UserDefaults.standard.set(true, forKey: "openatlogin")
28 | UserDefaults.standard.set(false, forKey: "openprefatlaunch")
29 | let task = Process()
30 | task.launchPath = "/bin/bash"
31 | task.arguments = ["-c", "sh \(Bundle.main.resourcePath!)/login.sh"]
32 | task.launch()
33 | task.waitUntilExit()
34 |
35 | }
36 | else {
37 | openatlogin.state = .off
38 | UserDefaults.standard.set(false, forKey: "openatlogin")
39 | UserDefaults.standard.set(true, forKey: "openprefatlaunch")
40 | let alert = NSAlert()
41 | alert.messageText = "Warning"
42 | alert.informativeText = "Please put app in your Applications folder first !"
43 | alert.alertStyle = .warning
44 | alert.addButton(withTitle: "OK")
45 | alert.runModal()
46 | }
47 |
48 | }
49 | else if openatlogin.state == .off{
50 | UserDefaults.standard.set(false, forKey: "openatlogin")
51 | UserDefaults.standard.set(true, forKey: "openprefatlaunch")
52 | let task = Process()
53 | task.launchPath = "/bin/bash"
54 | task.arguments = ["-c", "sh \(Bundle.main.resourcePath!)/nologin.sh"]
55 | task.launch()
56 | task.waitUntilExit()
57 |
58 | }
59 | }
60 |
61 | @IBAction func hideicon(_ sender: Any) {
62 |
63 | if hideicon.state == .on {
64 |
65 | if let appDelegate = NSApplication.shared.delegate as? AppDelegate {
66 | appDelegate.statusItem?.isVisible = false
67 | }
68 |
69 | UserDefaults.standard.set(true, forKey: "hideicon")
70 |
71 |
72 |
73 |
74 |
75 |
76 | } else {
77 |
78 | let appDelegate = NSApplication.shared.delegate as! AppDelegate
79 | appDelegate.statusItem?.isVisible = true
80 |
81 | UserDefaults.standard.set(false, forKey: "hideicon")
82 |
83 |
84 |
85 |
86 |
87 | }
88 | }
89 |
90 |
91 | @IBAction func soundlist(_ sender: Any) {
92 |
93 |
94 | UserDefaults.standard.set(soundlist.title, forKey: "actualsound")
95 |
96 | //preview sound
97 | let sound = NSSound(named: UserDefaults.standard.value(forKey: "actualsound") as! NSSound.Name)
98 | sound?.play()
99 |
100 | }
101 |
102 |
103 | @IBAction func quitapp(_ sender: Any) {
104 | if let window = NSApplication.shared.keyWindow {
105 |
106 | window.close()
107 |
108 | }
109 | }
110 |
111 | @IBAction func support(_ sender: Any) {
112 | guard let url = URL(string: "https://www.paypal.com/donate/?hosted_button_id=TUH8ECY3KP4BW") else { return }
113 | NSWorkspace.shared.open(url)
114 | }
115 |
116 |
117 | override func viewDidLoad() {
118 | super.viewDidLoad()
119 |
120 | print(UserDefaults.standard.bool(forKey: "hideicon"))
121 | print(UserDefaults.standard.bool(forKey: "actualsound"))
122 | print(UserDefaults.standard.bool(forKey: "openatlogin"))
123 |
124 | let soundOptions = ["Basso", "Blow", "Bottle", "Frog", "Funk", "Glass", "Hero", "Morse", "Ping", "Pop", "Purr", "Sosumi", "Submarine", "Tink"]
125 |
126 | soundlist.addItems(withObjectValues: soundOptions)
127 |
128 | //set default sound to "Puur" cuz it's nice
129 | if UserDefaults.standard.string(forKey: "actualsound") == nil {
130 | soundlist.title = "Purr"
131 | UserDefaults.standard.set("Purr", forKey: "actualsound")
132 | }
133 | else {
134 | soundlist.title = UserDefaults.standard.string(forKey: "actualsound")!
135 | }
136 |
137 |
138 | if UserDefaults.standard.value(forKey: "openatlogin") == nil {
139 | openatlogin.state = .off
140 | UserDefaults.standard.set(false, forKey: "openatlogin")
141 | }
142 | else if UserDefaults.standard.value(forKey: "openatlogin") as! Int == 1{
143 | openatlogin.state = .on
144 | }
145 | else if UserDefaults.standard.value(forKey: "openatlogin") as! Int == 0{
146 | openatlogin.state = .off
147 | }
148 |
149 |
150 |
151 | if UserDefaults.standard.value(forKey: "hideicon") == nil{
152 | hideicon.state = .off
153 | UserDefaults.standard.set(false, forKey: "hideicon")
154 | }
155 | else if UserDefaults.standard.value(forKey: "hideicon") as! Int == 1{
156 | hideicon.state = .on
157 |
158 | }
159 | else if UserDefaults.standard.value(forKey: "hideicon") as! Int == 0{
160 | hideicon.state = .off
161 |
162 | }
163 | }
164 |
165 | override var representedObject: Any? {
166 | didSet {
167 | // Update the view, if already loaded.
168 | }
169 | }
170 |
171 |
172 | }
173 |
174 |
--------------------------------------------------------------------------------
/airslide/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
100 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
159 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
--------------------------------------------------------------------------------
/AirSlide.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 56;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | A0427C27298BEC4600538691 /* login.sh in Resources */ = {isa = PBXBuildFile; fileRef = A0427C25298BEC4600538691 /* login.sh */; };
11 | A0427C28298BEC4600538691 /* nologin.sh in Resources */ = {isa = PBXBuildFile; fileRef = A0427C26298BEC4600538691 /* nologin.sh */; };
12 | A050ADF829893E7200C295A3 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = A050ADF729893E7200C295A3 /* Credits.rtf */; };
13 | A0EFF9F829833873002FF9B5 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0EFF9F729833873002FF9B5 /* AppDelegate.swift */; };
14 | A0EFF9FA29833873002FF9B5 /* PreferenceViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0EFF9F929833873002FF9B5 /* PreferenceViewController.swift */; };
15 | A0EFF9FC29833873002FF9B5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A0EFF9FB29833873002FF9B5 /* Assets.xcassets */; };
16 | A0EFF9FF29833873002FF9B5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A0EFF9FD29833873002FF9B5 /* Main.storyboard */; };
17 | /* End PBXBuildFile section */
18 |
19 | /* Begin PBXCopyFilesBuildPhase section */
20 | A006CA1D2985607500D434B4 /* Embed ExtensionKit Extensions */ = {
21 | isa = PBXCopyFilesBuildPhase;
22 | buildActionMask = 2147483647;
23 | dstPath = "$(EXTENSIONS_FOLDER_PATH)";
24 | dstSubfolderSpec = 16;
25 | files = (
26 | );
27 | name = "Embed ExtensionKit Extensions";
28 | runOnlyForDeploymentPostprocessing = 0;
29 | };
30 | A0EC59BD2986D6E600E23C60 /* Embed Frameworks */ = {
31 | isa = PBXCopyFilesBuildPhase;
32 | buildActionMask = 2147483647;
33 | dstPath = "";
34 | dstSubfolderSpec = 10;
35 | files = (
36 | );
37 | name = "Embed Frameworks";
38 | runOnlyForDeploymentPostprocessing = 0;
39 | };
40 | A0EE52812988004A00CC6884 /* CopyFiles */ = {
41 | isa = PBXCopyFilesBuildPhase;
42 | buildActionMask = 2147483647;
43 | dstPath = "";
44 | dstSubfolderSpec = 16;
45 | files = (
46 | );
47 | runOnlyForDeploymentPostprocessing = 0;
48 | };
49 | /* End PBXCopyFilesBuildPhase section */
50 |
51 | /* Begin PBXFileReference section */
52 | A006CA0C29855D9D00D434B4 /* ServiceManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ServiceManagement.framework; path = System/Library/Frameworks/ServiceManagement.framework; sourceTree = SDKROOT; };
53 | A0427C25298BEC4600538691 /* login.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = login.sh; path = airslide/login.sh; sourceTree = ""; };
54 | A0427C26298BEC4600538691 /* nologin.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = nologin.sh; path = airslide/nologin.sh; sourceTree = ""; };
55 | A050ADF729893E7200C295A3 /* Credits.rtf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.rtf; name = Credits.rtf; path = airslide/Credits.rtf; sourceTree = ""; };
56 | A0EFF9F429833873002FF9B5 /* AirSlide.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AirSlide.app; sourceTree = BUILT_PRODUCTS_DIR; };
57 | A0EFF9F729833873002FF9B5 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
58 | A0EFF9F929833873002FF9B5 /* PreferenceViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferenceViewController.swift; sourceTree = ""; };
59 | A0EFF9FB29833873002FF9B5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
60 | A0EFF9FE29833873002FF9B5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
61 | A0EFFA0029833873002FF9B5 /* airslide.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = airslide.entitlements; sourceTree = ""; };
62 | A0EFFA0929833873002FF9B5 /* airslideTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = airslideTests.swift; sourceTree = ""; };
63 | A0EFFA1329833873002FF9B5 /* airslideUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = airslideUITests.swift; sourceTree = ""; };
64 | A0EFFA1529833873002FF9B5 /* airslideUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = airslideUITestsLaunchTests.swift; sourceTree = ""; };
65 | /* End PBXFileReference section */
66 |
67 | /* Begin PBXFrameworksBuildPhase section */
68 | A0EFF9F129833873002FF9B5 /* Frameworks */ = {
69 | isa = PBXFrameworksBuildPhase;
70 | buildActionMask = 2147483647;
71 | files = (
72 | );
73 | runOnlyForDeploymentPostprocessing = 0;
74 | };
75 | /* End PBXFrameworksBuildPhase section */
76 |
77 | /* Begin PBXGroup section */
78 | A006CA0B29855D9D00D434B4 /* Frameworks */ = {
79 | isa = PBXGroup;
80 | children = (
81 | A006CA0C29855D9D00D434B4 /* ServiceManagement.framework */,
82 | );
83 | name = Frameworks;
84 | sourceTree = "";
85 | };
86 | A0EFF9EB29833873002FF9B5 = {
87 | isa = PBXGroup;
88 | children = (
89 | A0427C25298BEC4600538691 /* login.sh */,
90 | A0427C26298BEC4600538691 /* nologin.sh */,
91 | A050ADF729893E7200C295A3 /* Credits.rtf */,
92 | A0EFF9F629833873002FF9B5 /* airslide */,
93 | A0EFFA0829833873002FF9B5 /* airslideTests */,
94 | A0EFFA1229833873002FF9B5 /* airslideUITests */,
95 | A0EFF9F529833873002FF9B5 /* Products */,
96 | A006CA0B29855D9D00D434B4 /* Frameworks */,
97 | );
98 | sourceTree = "";
99 | };
100 | A0EFF9F529833873002FF9B5 /* Products */ = {
101 | isa = PBXGroup;
102 | children = (
103 | A0EFF9F429833873002FF9B5 /* AirSlide.app */,
104 | );
105 | name = Products;
106 | sourceTree = "";
107 | };
108 | A0EFF9F629833873002FF9B5 /* airslide */ = {
109 | isa = PBXGroup;
110 | children = (
111 | A0EFF9F729833873002FF9B5 /* AppDelegate.swift */,
112 | A0EFF9F929833873002FF9B5 /* PreferenceViewController.swift */,
113 | A0EFF9FB29833873002FF9B5 /* Assets.xcassets */,
114 | A0EFF9FD29833873002FF9B5 /* Main.storyboard */,
115 | A0EFFA0029833873002FF9B5 /* airslide.entitlements */,
116 | );
117 | path = airslide;
118 | sourceTree = "";
119 | };
120 | A0EFFA0829833873002FF9B5 /* airslideTests */ = {
121 | isa = PBXGroup;
122 | children = (
123 | A0EFFA0929833873002FF9B5 /* airslideTests.swift */,
124 | );
125 | path = airslideTests;
126 | sourceTree = "";
127 | };
128 | A0EFFA1229833873002FF9B5 /* airslideUITests */ = {
129 | isa = PBXGroup;
130 | children = (
131 | A0EFFA1329833873002FF9B5 /* airslideUITests.swift */,
132 | A0EFFA1529833873002FF9B5 /* airslideUITestsLaunchTests.swift */,
133 | );
134 | path = airslideUITests;
135 | sourceTree = "";
136 | };
137 | /* End PBXGroup section */
138 |
139 | /* Begin PBXNativeTarget section */
140 | A0EFF9F329833873002FF9B5 /* AirSlide */ = {
141 | isa = PBXNativeTarget;
142 | buildConfigurationList = A0EFFA1929833873002FF9B5 /* Build configuration list for PBXNativeTarget "AirSlide" */;
143 | buildPhases = (
144 | A0EFF9F029833873002FF9B5 /* Sources */,
145 | A0EFF9F129833873002FF9B5 /* Frameworks */,
146 | A0EFF9F229833873002FF9B5 /* Resources */,
147 | A006CA1D2985607500D434B4 /* Embed ExtensionKit Extensions */,
148 | A0EC59BD2986D6E600E23C60 /* Embed Frameworks */,
149 | A0EE52812988004A00CC6884 /* CopyFiles */,
150 | );
151 | buildRules = (
152 | );
153 | dependencies = (
154 | );
155 | name = AirSlide;
156 | packageProductDependencies = (
157 | );
158 | productName = airslide;
159 | productReference = A0EFF9F429833873002FF9B5 /* AirSlide.app */;
160 | productType = "com.apple.product-type.application";
161 | };
162 | /* End PBXNativeTarget section */
163 |
164 | /* Begin PBXProject section */
165 | A0EFF9EC29833873002FF9B5 /* Project object */ = {
166 | isa = PBXProject;
167 | attributes = {
168 | BuildIndependentTargetsInParallel = 1;
169 | LastSwiftUpdateCheck = 1420;
170 | LastUpgradeCheck = 1420;
171 | TargetAttributes = {
172 | A0EFF9F329833873002FF9B5 = {
173 | CreatedOnToolsVersion = 14.2;
174 | };
175 | };
176 | };
177 | buildConfigurationList = A0EFF9EF29833873002FF9B5 /* Build configuration list for PBXProject "AirSlide" */;
178 | compatibilityVersion = "Xcode 14.0";
179 | developmentRegion = en;
180 | hasScannedForEncodings = 0;
181 | knownRegions = (
182 | en,
183 | Base,
184 | );
185 | mainGroup = A0EFF9EB29833873002FF9B5;
186 | packageReferences = (
187 | );
188 | productRefGroup = A0EFF9F529833873002FF9B5 /* Products */;
189 | projectDirPath = "";
190 | projectRoot = "";
191 | targets = (
192 | A0EFF9F329833873002FF9B5 /* AirSlide */,
193 | );
194 | };
195 | /* End PBXProject section */
196 |
197 | /* Begin PBXResourcesBuildPhase section */
198 | A0EFF9F229833873002FF9B5 /* Resources */ = {
199 | isa = PBXResourcesBuildPhase;
200 | buildActionMask = 2147483647;
201 | files = (
202 | A0EFF9FC29833873002FF9B5 /* Assets.xcassets in Resources */,
203 | A0EFF9FF29833873002FF9B5 /* Main.storyboard in Resources */,
204 | A0427C28298BEC4600538691 /* nologin.sh in Resources */,
205 | A0427C27298BEC4600538691 /* login.sh in Resources */,
206 | A050ADF829893E7200C295A3 /* Credits.rtf in Resources */,
207 | );
208 | runOnlyForDeploymentPostprocessing = 0;
209 | };
210 | /* End PBXResourcesBuildPhase section */
211 |
212 | /* Begin PBXSourcesBuildPhase section */
213 | A0EFF9F029833873002FF9B5 /* Sources */ = {
214 | isa = PBXSourcesBuildPhase;
215 | buildActionMask = 2147483647;
216 | files = (
217 | A0EFF9FA29833873002FF9B5 /* PreferenceViewController.swift in Sources */,
218 | A0EFF9F829833873002FF9B5 /* AppDelegate.swift in Sources */,
219 | );
220 | runOnlyForDeploymentPostprocessing = 0;
221 | };
222 | /* End PBXSourcesBuildPhase section */
223 |
224 | /* Begin PBXVariantGroup section */
225 | A0EFF9FD29833873002FF9B5 /* Main.storyboard */ = {
226 | isa = PBXVariantGroup;
227 | children = (
228 | A0EFF9FE29833873002FF9B5 /* Base */,
229 | );
230 | name = Main.storyboard;
231 | sourceTree = "";
232 | };
233 | /* End PBXVariantGroup section */
234 |
235 | /* Begin XCBuildConfiguration section */
236 | A0EFFA1729833873002FF9B5 /* Debug */ = {
237 | isa = XCBuildConfiguration;
238 | buildSettings = {
239 | ALWAYS_SEARCH_USER_PATHS = NO;
240 | CLANG_ANALYZER_NONNULL = YES;
241 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
242 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
243 | CLANG_ENABLE_MODULES = YES;
244 | CLANG_ENABLE_OBJC_ARC = YES;
245 | CLANG_ENABLE_OBJC_WEAK = YES;
246 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
247 | CLANG_WARN_BOOL_CONVERSION = YES;
248 | CLANG_WARN_COMMA = YES;
249 | CLANG_WARN_CONSTANT_CONVERSION = YES;
250 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
251 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
252 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
253 | CLANG_WARN_EMPTY_BODY = YES;
254 | CLANG_WARN_ENUM_CONVERSION = YES;
255 | CLANG_WARN_INFINITE_RECURSION = YES;
256 | CLANG_WARN_INT_CONVERSION = YES;
257 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
258 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
259 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
260 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
261 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
262 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
263 | CLANG_WARN_STRICT_PROTOTYPES = YES;
264 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
265 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
266 | CLANG_WARN_UNREACHABLE_CODE = YES;
267 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
268 | COPY_PHASE_STRIP = NO;
269 | DEBUG_INFORMATION_FORMAT = dwarf;
270 | ENABLE_STRICT_OBJC_MSGSEND = YES;
271 | ENABLE_TESTABILITY = YES;
272 | GCC_C_LANGUAGE_STANDARD = gnu11;
273 | GCC_DYNAMIC_NO_PIC = NO;
274 | GCC_NO_COMMON_BLOCKS = YES;
275 | GCC_OPTIMIZATION_LEVEL = 0;
276 | GCC_PREPROCESSOR_DEFINITIONS = (
277 | "DEBUG=1",
278 | "$(inherited)",
279 | );
280 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
281 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
282 | GCC_WARN_UNDECLARED_SELECTOR = YES;
283 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
284 | GCC_WARN_UNUSED_FUNCTION = YES;
285 | GCC_WARN_UNUSED_VARIABLE = YES;
286 | INFOPLIST_KEY_LSUIElement = YES;
287 | INFOPLIST_KEY_NSAppleEventsUsageDescription = "";
288 | MACOSX_DEPLOYMENT_TARGET = 12.6;
289 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
290 | MTL_FAST_MATH = YES;
291 | ONLY_ACTIVE_ARCH = YES;
292 | SDKROOT = macosx;
293 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
294 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
295 | };
296 | name = Debug;
297 | };
298 | A0EFFA1829833873002FF9B5 /* Release */ = {
299 | isa = XCBuildConfiguration;
300 | buildSettings = {
301 | ALWAYS_SEARCH_USER_PATHS = NO;
302 | CLANG_ANALYZER_NONNULL = YES;
303 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
304 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
305 | CLANG_ENABLE_MODULES = YES;
306 | CLANG_ENABLE_OBJC_ARC = YES;
307 | CLANG_ENABLE_OBJC_WEAK = YES;
308 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
309 | CLANG_WARN_BOOL_CONVERSION = YES;
310 | CLANG_WARN_COMMA = YES;
311 | CLANG_WARN_CONSTANT_CONVERSION = YES;
312 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
313 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
314 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
315 | CLANG_WARN_EMPTY_BODY = YES;
316 | CLANG_WARN_ENUM_CONVERSION = YES;
317 | CLANG_WARN_INFINITE_RECURSION = YES;
318 | CLANG_WARN_INT_CONVERSION = YES;
319 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
320 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
321 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
322 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
323 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
324 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
325 | CLANG_WARN_STRICT_PROTOTYPES = YES;
326 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
327 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
328 | CLANG_WARN_UNREACHABLE_CODE = YES;
329 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
330 | COPY_PHASE_STRIP = NO;
331 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
332 | ENABLE_NS_ASSERTIONS = NO;
333 | ENABLE_STRICT_OBJC_MSGSEND = YES;
334 | GCC_C_LANGUAGE_STANDARD = gnu11;
335 | GCC_NO_COMMON_BLOCKS = YES;
336 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
337 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
338 | GCC_WARN_UNDECLARED_SELECTOR = YES;
339 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
340 | GCC_WARN_UNUSED_FUNCTION = YES;
341 | GCC_WARN_UNUSED_VARIABLE = YES;
342 | INFOPLIST_KEY_LSUIElement = YES;
343 | INFOPLIST_KEY_NSAppleEventsUsageDescription = "";
344 | MACOSX_DEPLOYMENT_TARGET = 12.6;
345 | MTL_ENABLE_DEBUG_INFO = NO;
346 | MTL_FAST_MATH = YES;
347 | SDKROOT = macosx;
348 | SWIFT_COMPILATION_MODE = wholemodule;
349 | SWIFT_OPTIMIZATION_LEVEL = "-O";
350 | };
351 | name = Release;
352 | };
353 | A0EFFA1A29833873002FF9B5 /* Debug */ = {
354 | isa = XCBuildConfiguration;
355 | buildSettings = {
356 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
357 | ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
358 | CODE_SIGN_ENTITLEMENTS = airslide/airslide.entitlements;
359 | "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
360 | CODE_SIGN_STYLE = Automatic;
361 | COMBINE_HIDPI_IMAGES = YES;
362 | DEVELOPMENT_TEAM = 5T9BF883B2;
363 | ENABLE_HARDENED_RUNTIME = YES;
364 | GENERATE_INFOPLIST_FILE = YES;
365 | INFOPLIST_FILE = airslide/Info.plist;
366 | INFOPLIST_KEY_CFBundleDisplayName = AirSlide;
367 | INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity";
368 | INFOPLIST_KEY_LSUIElement = YES;
369 | INFOPLIST_KEY_NSAppleEventsUsageDescription = "";
370 | INFOPLIST_KEY_NSHumanReadableCopyright = "";
371 | INFOPLIST_KEY_NSMainStoryboardFile = Main;
372 | INFOPLIST_KEY_NSPrincipalClass = NSApplication;
373 | LD_RUNPATH_SEARCH_PATHS = (
374 | "$(inherited)",
375 | "@executable_path/../Frameworks",
376 | );
377 | MACOSX_DEPLOYMENT_TARGET = 12.0;
378 | MARKETING_VERSION = 1.2.2;
379 | PRODUCT_BUNDLE_IDENTIFIER = mago.airslide;
380 | PRODUCT_NAME = "$(TARGET_NAME)";
381 | SWIFT_EMIT_LOC_STRINGS = YES;
382 | SWIFT_VERSION = 5.0;
383 | };
384 | name = Debug;
385 | };
386 | A0EFFA1B29833873002FF9B5 /* Release */ = {
387 | isa = XCBuildConfiguration;
388 | buildSettings = {
389 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
390 | ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
391 | CODE_SIGN_ENTITLEMENTS = airslide/airslide.entitlements;
392 | "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
393 | CODE_SIGN_STYLE = Automatic;
394 | COMBINE_HIDPI_IMAGES = YES;
395 | DEVELOPMENT_TEAM = 5T9BF883B2;
396 | ENABLE_HARDENED_RUNTIME = YES;
397 | GENERATE_INFOPLIST_FILE = YES;
398 | INFOPLIST_FILE = airslide/Info.plist;
399 | INFOPLIST_KEY_CFBundleDisplayName = AirSlide;
400 | INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity";
401 | INFOPLIST_KEY_LSUIElement = YES;
402 | INFOPLIST_KEY_NSAppleEventsUsageDescription = "";
403 | INFOPLIST_KEY_NSHumanReadableCopyright = "";
404 | INFOPLIST_KEY_NSMainStoryboardFile = Main;
405 | INFOPLIST_KEY_NSPrincipalClass = NSApplication;
406 | LD_RUNPATH_SEARCH_PATHS = (
407 | "$(inherited)",
408 | "@executable_path/../Frameworks",
409 | );
410 | MACOSX_DEPLOYMENT_TARGET = 12.0;
411 | MARKETING_VERSION = 1.2.2;
412 | PRODUCT_BUNDLE_IDENTIFIER = mago.airslide;
413 | PRODUCT_NAME = "$(TARGET_NAME)";
414 | SWIFT_EMIT_LOC_STRINGS = YES;
415 | SWIFT_VERSION = 5.0;
416 | };
417 | name = Release;
418 | };
419 | /* End XCBuildConfiguration section */
420 |
421 | /* Begin XCConfigurationList section */
422 | A0EFF9EF29833873002FF9B5 /* Build configuration list for PBXProject "AirSlide" */ = {
423 | isa = XCConfigurationList;
424 | buildConfigurations = (
425 | A0EFFA1729833873002FF9B5 /* Debug */,
426 | A0EFFA1829833873002FF9B5 /* Release */,
427 | );
428 | defaultConfigurationIsVisible = 0;
429 | defaultConfigurationName = Release;
430 | };
431 | A0EFFA1929833873002FF9B5 /* Build configuration list for PBXNativeTarget "AirSlide" */ = {
432 | isa = XCConfigurationList;
433 | buildConfigurations = (
434 | A0EFFA1A29833873002FF9B5 /* Debug */,
435 | A0EFFA1B29833873002FF9B5 /* Release */,
436 | );
437 | defaultConfigurationIsVisible = 0;
438 | defaultConfigurationName = Release;
439 | };
440 | /* End XCConfigurationList section */
441 | };
442 | rootObject = A0EFF9EC29833873002FF9B5 /* Project object */;
443 | }
444 |
--------------------------------------------------------------------------------
/airslide/AppDelegate.swift:
--------------------------------------------------------------------------------
1 |
2 | import Cocoa
3 | import AppKit
4 | import Foundation
5 |
6 |
7 |
8 | @NSApplicationMain
9 | class AppDelegate: NSObject, NSApplicationDelegate, NSSharingServiceDelegate {
10 |
11 | var hasExecuted = false //allow view trigger to show and be fired only once
12 | var hasExecuted2 = false //allow airdrop trigger do be fired only once
13 |
14 | var filepath = ""
15 |
16 | @IBOutlet weak var menu: NSMenu?
17 | @IBOutlet weak var firstMenuItem: NSMenuItem?
18 |
19 | var statusBar: NSStatusBar!
20 | var statusItem: NSStatusItem?
21 | let mainScreen = NSScreen.main!
22 |
23 | func applicationDidFinishLaunching(_ notification: Notification) {
24 |
25 | if UserDefaults.standard.bool(forKey: "openprefatlaunch") == true{
26 | let storyboard = NSStoryboard(name: "Main", bundle: nil)
27 | let preferencesVC = storyboard.instantiateController(withIdentifier: "PreferencesViewController") as? NSViewController
28 | preferencesVC?.presentAsModalWindow(preferencesVC!)
29 | }
30 |
31 | //Setting status item
32 | statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
33 | statusItem?.button?.image = NSImage(systemSymbolName: "paperplane.fill", accessibilityDescription: nil)
34 |
35 | if let menu = menu {
36 | statusItem?.menu = menu
37 | }
38 |
39 | //Defining each device screen size
40 | let MBP14 = (NSScreen.main?.frame.height)! == 982
41 | let MBP16 = (NSScreen.main?.frame.height)! > 1000 //to be sure
42 | let MBAM2 = (NSScreen.main?.frame.height)! < 980 //to be sure
43 |
44 | if MBP14{
45 | startMBP14()
46 | }
47 | if MBP16{
48 | startMBP16()
49 | }
50 | if MBAM2 {
51 | startMBAM2()
52 | }
53 |
54 |
55 | //First check for highlited files path
56 | AppKit.NSEvent.addGlobalMonitorForEvents(matching: .leftMouseDown) { event in
57 |
58 | let frontmostApp = NSWorkspace.shared.frontmostApplication
59 | let frontmostAppBundleIdentifier = frontmostApp?.bundleIdentifier
60 |
61 |
62 | if (frontmostAppBundleIdentifier! == "com.apple.finder" || frontmostAppBundleIdentifier! == "mago.airslide"){
63 | let script = """
64 | tell application "Finder"
65 | set theSelection to selection as alias list
66 | set thePaths to {}
67 | repeat with anItem in theSelection
68 | set end of thePaths to POSIX path of anItem
69 | end repeat
70 | return thePaths
71 | end tell
72 | """
73 | let appleScript = NSAppleScript(source: script)
74 | var error: NSDictionary?
75 | if let result = appleScript?.executeAndReturnError(&error) {
76 | let count = result.numberOfItems
77 | self.filepath = ""
78 | if result.numberOfItems != 0{
79 | for index in 1...count {
80 | if index == 1 {
81 | self.filepath += (result.atIndex(index)?.stringValue)!
82 | } else {
83 | self.filepath += ", " + (result.atIndex(index)?.stringValue)!
84 | }
85 | }
86 | }
87 | } else if (error != nil) {
88 | print("error: \(error!)")
89 | }
90 | }
91 |
92 | }
93 |
94 |
95 | if MBP14{
96 | //Create notch view
97 | let window = NSWindow(contentRect: NSMakeRect(635, 880, 250, 100), styleMask: .borderless, backing: .buffered, defer: false)
98 | window.level = .screenSaver
99 | window.isOpaque = false
100 | window.backgroundColor = .clear
101 |
102 | let blueView = NSView(frame: CGRect(x: 29, y: window.contentView!.frame.midY + 20 , width: window.contentView!.frame.width - 66, height: window.contentView!.frame.height - 5))
103 | blueView.wantsLayer = true
104 | blueView.layer?.backgroundColor = NSColor(red: 0, green: 123/255, blue: 254/255, alpha: 1).cgColor
105 | blueView.layer?.cornerRadius = 10
106 | blueView.isHidden = true
107 |
108 | let borderLayer = CALayer()
109 | borderLayer.frame = blueView.bounds
110 | borderLayer.cornerRadius = blueView.layer!.cornerRadius
111 | borderLayer.borderColor = NSColor.white.cgColor
112 | borderLayer.borderWidth = 6.0
113 | blueView.layer?.addSublayer(borderLayer)
114 |
115 | let animation = CABasicAnimation(keyPath: "borderColor")
116 | animation.fromValue = NSColor.clear.cgColor
117 | animation.toValue = NSColor.white.cgColor
118 | animation.duration = 1.618
119 | animation.autoreverses = true
120 | animation.repeatCount = Float.infinity
121 | borderLayer.add(animation, forKey: "borderColor")
122 |
123 | window.contentView?.addSubview(blueView)
124 | window.makeKeyAndOrderFront(nil)
125 |
126 |
127 | //Bring down view when mouse dragging enter top screen zone
128 | AppKit.NSEvent.addGlobalMonitorForEvents(matching: .leftMouseDragged) { event in
129 |
130 | if !self.hasExecuted {
131 |
132 | let mousePoint = event.locationInWindow
133 | let frontmostApp = NSWorkspace.shared.frontmostApplication
134 | let frontmostAppBundleIdentifier = frontmostApp?.bundleIdentifier
135 |
136 | if (frontmostAppBundleIdentifier! == "com.apple.finder" || frontmostAppBundleIdentifier! == "mago.airslide") && mousePoint.y > 840 {
137 |
138 | self.hasExecuted = true
139 |
140 | blueView.isHidden = false
141 |
142 | //down view animation
143 | //print(blueView.frame.midY)
144 | NSAnimationContext.runAnimationGroup({ (context) in
145 | context.duration = 0.7
146 | blueView.animator().frame.origin.y -= 6
147 | }, completionHandler: {
148 | blueView.frame.origin.y -= 0
149 | })
150 | }
151 | }
152 | }
153 |
154 | //Bring it back down if mouse drag quit top screen zone
155 | AppKit.NSEvent.addGlobalMonitorForEvents(matching: .leftMouseDragged) { event in
156 |
157 |
158 | let mousePoint = event.locationInWindow
159 |
160 | if mousePoint.y < 840 {
161 | if blueView.frame.midY == 111.5{
162 | self.hasExecuted = false
163 | NSAnimationContext.runAnimationGroup({ (context) in
164 | context.duration = 0.7
165 | blueView.animator().frame.origin.y -= -6
166 | }, completionHandler: {
167 | blueView.frame.origin.y -= 0
168 | })
169 | }
170 | }
171 | }
172 |
173 |
174 | //Bring animation back up if mouse up
175 | AppKit.NSEvent.addGlobalMonitorForEvents(matching: .leftMouseUp) { event in
176 |
177 | self.hasExecuted = false
178 | self.hasExecuted2 = false
179 |
180 |
181 | let frontmostApp = NSWorkspace.shared.frontmostApplication
182 | let frontmostAppBundleIdentifier = frontmostApp?.bundleIdentifier
183 |
184 |
185 | if (frontmostAppBundleIdentifier! == "com.apple.finder" || frontmostAppBundleIdentifier! == "mago.airslide") {
186 |
187 | //back up animation
188 | if blueView.frame.midY == 111.5{
189 | NSAnimationContext.runAnimationGroup({ (context) in
190 | context.duration = 0.7
191 | blueView.animator().frame.origin.y -= -6
192 | }, completionHandler: {
193 | blueView.frame.origin.y -= 0
194 | })
195 | }
196 | }
197 |
198 | DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) {
199 |
200 | //hide only if in start position
201 | if blueView.frame.midY == 117.5{
202 | blueView.isHidden = true
203 | }
204 |
205 |
206 | }
207 |
208 |
209 | }
210 |
211 | }
212 |
213 | //Same for 16"
214 | else if MBP16{
215 |
216 | let window = NSWindow(contentRect: NSMakeRect(725, 1001, 285.71, 113.74), styleMask: .borderless, backing: .buffered, defer: false) //THEORICAL VALUES
217 | window.level = .screenSaver
218 | window.isOpaque = false
219 | window.backgroundColor = .clear
220 |
221 | let blueView = NSView(frame: CGRect(x: 29, y: window.contentView!.frame.midY + 20 , width: window.contentView!.frame.width - 66, height: window.contentView!.frame.height - 5))
222 | blueView.wantsLayer = true
223 | blueView.layer?.backgroundColor = NSColor(red: 0, green: 123/255, blue: 254/255, alpha: 1).cgColor
224 | blueView.layer?.cornerRadius = 10
225 | blueView.isHidden = true
226 |
227 | let borderLayer = CALayer()
228 | borderLayer.frame = blueView.bounds
229 | borderLayer.cornerRadius = blueView.layer!.cornerRadius
230 | borderLayer.borderColor = NSColor.white.cgColor
231 | borderLayer.borderWidth = 6.0
232 | blueView.layer?.addSublayer(borderLayer)
233 |
234 | let animation = CABasicAnimation(keyPath: "borderColor")
235 | animation.fromValue = NSColor.clear.cgColor
236 | animation.toValue = NSColor.white.cgColor
237 | animation.duration = 1.618
238 | animation.autoreverses = true
239 | animation.repeatCount = Float.infinity
240 | borderLayer.add(animation, forKey: "borderColor")
241 |
242 | window.contentView?.addSubview(blueView)
243 | window.makeKeyAndOrderFront(nil)
244 |
245 | //Show view when dragging mouse reach top of screen
246 | AppKit.NSEvent.addGlobalMonitorForEvents(matching: .leftMouseDragged) { event in
247 |
248 | if !self.hasExecuted {
249 |
250 | let mousePoint = event.locationInWindow
251 | let frontmostApp = NSWorkspace.shared.frontmostApplication
252 | let frontmostAppBundleIdentifier = frontmostApp?.bundleIdentifier
253 |
254 |
255 | if (frontmostAppBundleIdentifier! == "com.apple.finder" || frontmostAppBundleIdentifier! == "mago.airslide") && mousePoint.y > 950 {
256 |
257 | self.hasExecuted = true
258 |
259 | blueView.isHidden = false
260 |
261 | //down view animation
262 | NSAnimationContext.runAnimationGroup({ (context) in
263 | context.duration = 0.7
264 | blueView.animator().frame.origin.y -= 6
265 | }, completionHandler: {
266 | blueView.frame.origin.y -= 0
267 | })
268 | }
269 | }
270 | }
271 |
272 | //Bring it back down if mouse drag quit top screen zone
273 | AppKit.NSEvent.addGlobalMonitorForEvents(matching: .leftMouseDragged) { event in
274 |
275 |
276 | let mousePoint = event.locationInWindow
277 |
278 | if mousePoint.y < 950 {
279 | if blueView.frame.midY == 125.5{
280 | self.hasExecuted = false
281 | NSAnimationContext.runAnimationGroup({ (context) in
282 | context.duration = 0.7
283 | blueView.animator().frame.origin.y -= -6
284 | }, completionHandler: {
285 | blueView.frame.origin.y -= 0
286 | })
287 | }
288 | }
289 | }
290 |
291 | //Hide view when mouse release
292 | AppKit.NSEvent.addGlobalMonitorForEvents(matching: .leftMouseUp) { event in
293 |
294 | self.hasExecuted = false
295 | self.hasExecuted2 = false
296 |
297 | let frontmostApp = NSWorkspace.shared.frontmostApplication
298 | let frontmostAppBundleIdentifier = frontmostApp?.bundleIdentifier
299 |
300 | if (frontmostAppBundleIdentifier! == "com.apple.finder" || frontmostAppBundleIdentifier! == "mago.airslide") {
301 |
302 | //back up animation
303 | if blueView.frame.midY == 125.5{
304 | NSAnimationContext.runAnimationGroup({ (context) in
305 | context.duration = 0.7
306 | blueView.animator().frame.origin.y -= -6
307 | }, completionHandler: {
308 | blueView.frame.origin.y -= 0
309 | })
310 | }
311 | }
312 |
313 | DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) {
314 | //hide only if in start position
315 | if blueView.frame.midY == 131.5{
316 | blueView.isHidden = true
317 | }
318 |
319 | }
320 |
321 |
322 | }
323 |
324 | }
325 |
326 | //Same for MBAir
327 | else if MBAM2 {
328 |
329 | let window = NSWindow(contentRect: NSMakeRect(617.36, 856.70, 243.05, 97.35), styleMask: .borderless, backing: .buffered, defer: false) //THEORICAL VALUES
330 | window.level = .screenSaver
331 | window.isOpaque = false
332 | window.backgroundColor = .clear
333 |
334 | let blueView = NSView(frame: CGRect(x: 29, y: window.contentView!.frame.midY + 20 , width: window.contentView!.frame.width - 66, height: window.contentView!.frame.height - 5))
335 | blueView.wantsLayer = true
336 | blueView.layer?.backgroundColor = NSColor(red: 0, green: 123/255, blue: 254/255, alpha: 1).cgColor
337 | blueView.layer?.cornerRadius = 10
338 | blueView.isHidden = true
339 |
340 | let borderLayer = CALayer()
341 | borderLayer.frame = blueView.bounds
342 | borderLayer.cornerRadius = blueView.layer!.cornerRadius
343 | borderLayer.borderColor = NSColor.white.cgColor
344 | borderLayer.borderWidth = 6.0
345 | blueView.layer?.addSublayer(borderLayer)
346 |
347 | let animation = CABasicAnimation(keyPath: "borderColor")
348 | animation.fromValue = NSColor.clear.cgColor
349 | animation.toValue = NSColor.white.cgColor
350 | animation.duration = 1.618
351 | animation.autoreverses = true
352 | animation.repeatCount = Float.infinity
353 | borderLayer.add(animation, forKey: "borderColor")
354 |
355 | window.contentView?.addSubview(blueView)
356 | window.makeKeyAndOrderFront(nil)
357 |
358 | //Show view when dragging mouse reach top of screen
359 | AppKit.NSEvent.addGlobalMonitorForEvents(matching: .leftMouseDragged) { event in
360 |
361 | if !self.hasExecuted {
362 |
363 | let mousePoint = event.locationInWindow
364 | let frontmostApp = NSWorkspace.shared.frontmostApplication
365 | let frontmostAppBundleIdentifier = frontmostApp?.bundleIdentifier
366 |
367 |
368 | if (frontmostAppBundleIdentifier! == "com.apple.finder" || frontmostAppBundleIdentifier! == "mago.airslide") && mousePoint.y > 827.87 {
369 |
370 | self.hasExecuted = true
371 |
372 | blueView.isHidden = false
373 |
374 | //down view animation
375 | NSAnimationContext.runAnimationGroup({ (context) in
376 | context.duration = 0.7
377 | blueView.animator().frame.origin.y -= 6
378 | }, completionHandler: {
379 | blueView.frame.origin.y -= 0
380 | })
381 | }
382 | }
383 | }
384 |
385 | //Bring it back down if mouse drag quit top screen zone
386 | AppKit.NSEvent.addGlobalMonitorForEvents(matching: .leftMouseDragged) { event in
387 |
388 | //print(blueView.frame.midY)
389 | let mousePoint = event.locationInWindow
390 |
391 | if mousePoint.y < 827.87 {
392 | if blueView.frame.midY == 109.5{
393 | self.hasExecuted = false
394 | NSAnimationContext.runAnimationGroup({ (context) in
395 | context.duration = 0.7
396 | blueView.animator().frame.origin.y -= -6
397 | }, completionHandler: {
398 | blueView.frame.origin.y -= 0
399 | })
400 | }
401 | }
402 | }
403 |
404 | //Hide view when mouse release
405 | AppKit.NSEvent.addGlobalMonitorForEvents(matching: .leftMouseUp) { event in
406 |
407 | self.hasExecuted = false
408 | self.hasExecuted2 = false
409 |
410 | let frontmostApp = NSWorkspace.shared.frontmostApplication
411 | let frontmostAppBundleIdentifier = frontmostApp?.bundleIdentifier
412 |
413 | if (frontmostAppBundleIdentifier! == "com.apple.finder" || frontmostAppBundleIdentifier! == "mago.airslide") {
414 |
415 | //back up animation
416 | if blueView.frame.midY == 109.5{
417 | NSAnimationContext.runAnimationGroup({ (context) in
418 | context.duration = 0.7
419 | blueView.animator().frame.origin.y -= -6
420 | }, completionHandler: {
421 | blueView.frame.origin.y -= 0
422 | })
423 | }
424 | }
425 |
426 | DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) {
427 | //hide only if in start position
428 | if blueView.frame.midY == 115.5{
429 | blueView.isHidden = true
430 | }
431 |
432 | }
433 |
434 |
435 | }
436 |
437 | }
438 |
439 |
440 |
441 |
442 |
443 | //Show pref pane when clicking notch
444 | AppKit.NSEvent.addGlobalMonitorForEvents(matching: .leftMouseDown) { event in
445 |
446 | let mousePoint = event.locationInWindow
447 |
448 | //Focus app on main screen
449 | if self.mainScreen.frame.contains(mousePoint) == true {
450 |
451 | let statusBarHeight = NSStatusBar.system.thickness
452 | let screenHeight = NSScreen.main?.frame.height
453 | let mouseY = event.locationInWindow.y
454 | let mouseX = event.locationInWindow.x
455 | let frontmostApp = NSWorkspace.shared.frontmostApplication
456 | let frontmostAppBundleIdentifier = frontmostApp?.bundleIdentifier
457 |
458 | if MBP14 {
459 |
460 | if mouseY >= (screenHeight! - statusBarHeight) - 12 && mouseX > 665 && mouseX < 850 {
461 |
462 | if (frontmostAppBundleIdentifier! == "com.apple.finder" || frontmostAppBundleIdentifier! == "mago.airslide") {
463 |
464 | let storyboard = NSStoryboard(name: "Main", bundle: nil)
465 | let preferencesVC = storyboard.instantiateController(withIdentifier: "PreferencesViewController") as? NSViewController
466 | preferencesVC?.presentAsModalWindow(preferencesVC!)
467 |
468 |
469 |
470 | }
471 | }
472 | }
473 | else if MBP16 {
474 |
475 | if mouseY >= (screenHeight! - statusBarHeight) - 12 && mouseX > 756.42 && mouseX < 941.42 {
476 |
477 | if (frontmostAppBundleIdentifier! == "com.apple.finder" || frontmostAppBundleIdentifier! == "mago.airslide") {
478 |
479 | let storyboard = NSStoryboard(name: "Main", bundle: nil)
480 | let preferencesVC = storyboard.instantiateController(withIdentifier: "PreferencesViewController") as? NSViewController
481 | preferencesVC?.presentAsModalWindow(preferencesVC!)
482 |
483 | }
484 |
485 | }
486 |
487 | }
488 | else if MBAM2 {
489 |
490 | if mouseY >= (screenHeight! - statusBarHeight) - 12 && mouseX > 646.52 && mouseX < 827.49 {
491 |
492 | if (frontmostAppBundleIdentifier! == "com.apple.finder" || frontmostAppBundleIdentifier! == "mago.airslide") {
493 |
494 | let storyboard = NSStoryboard(name: "Main", bundle: nil)
495 | let preferencesVC = storyboard.instantiateController(withIdentifier: "PreferencesViewController") as? NSViewController
496 | preferencesVC?.presentAsModalWindow(preferencesVC!)
497 |
498 | }
499 |
500 | }
501 |
502 | }
503 | }
504 |
505 | }
506 |
507 | var mouseDraggedinNotch = false
508 |
509 | //Drag on notch event
510 | AppKit.NSEvent.addGlobalMonitorForEvents(matching: .leftMouseDragged) { [self] event in
511 |
512 | let mousePoint = event.locationInWindow
513 |
514 | //Focus app on main screen
515 | if self.mainScreen.frame.contains(mousePoint) == true {
516 |
517 | let statusBarHeight = NSStatusBar.system.thickness
518 | let screenHeight = NSScreen.main?.frame.height
519 | let mouseY = event.locationInWindow.y
520 | let mouseX = event.locationInWindow.x
521 | let frontmostApp = NSWorkspace.shared.frontmostApplication
522 | let frontmostAppBundleIdentifier = frontmostApp?.bundleIdentifier
523 |
524 | if MBP14 {
525 |
526 | if (frontmostAppBundleIdentifier! == "com.apple.finder" || frontmostAppBundleIdentifier! == "mago.airslide") && self.filepath != "" { //So app only works on finder
527 |
528 | if mouseY >= (screenHeight! - statusBarHeight) - 12 && mouseX > 665 && mouseX < 850 {
529 |
530 | if mouseDraggedinNotch == false{
531 | mouseDraggedinNotch = true
532 | }
533 |
534 | }
535 | else {
536 | if mouseDraggedinNotch == true {
537 | mouseDraggedinNotch = false
538 | }
539 |
540 | }
541 | }
542 |
543 | }
544 |
545 | else if MBP16 {
546 |
547 | if (frontmostAppBundleIdentifier! == "com.apple.finder" || frontmostAppBundleIdentifier! == "mago.airslide") && self.filepath != "" {
548 |
549 | if mouseY >= (screenHeight! - statusBarHeight) - 12 && mouseX > 756.42 && mouseX < 941.42 {
550 |
551 | if mouseDraggedinNotch == false{
552 | mouseDraggedinNotch = true
553 | }
554 |
555 | }
556 | else {
557 | if mouseDraggedinNotch == true {
558 | mouseDraggedinNotch = false
559 | }
560 | }
561 |
562 | }
563 |
564 | }
565 | else if MBAM2 {
566 |
567 | if (frontmostAppBundleIdentifier! == "com.apple.finder" || frontmostAppBundleIdentifier! == "mago.airslide") && self.filepath != "" {
568 |
569 | if mouseY >= (screenHeight! - statusBarHeight) - 12 && mouseX > 646.52 && mouseX < 827.49 {
570 |
571 | if mouseDraggedinNotch == false{
572 | mouseDraggedinNotch = true
573 | }
574 |
575 | }
576 | else {
577 | if mouseDraggedinNotch == true {
578 | mouseDraggedinNotch = false
579 | }
580 | }
581 |
582 | }
583 |
584 | }
585 |
586 |
587 | }
588 |
589 | }
590 |
591 |
592 | //This allow the main function to fire only if mouse is in notch area and not on second screen.
593 | AppKit.NSEvent.addGlobalMonitorForEvents(matching: .leftMouseUp) { event in
594 |
595 | let mousePoint = event.locationInWindow
596 |
597 | if mouseDraggedinNotch == true && self.mainScreen.frame.contains(mousePoint) == true {
598 |
599 | self.dotherightthing()
600 |
601 | mouseDraggedinNotch = false
602 | }
603 | else {
604 | mouseDraggedinNotch = false
605 | }
606 |
607 | }
608 |
609 | }
610 |
611 | //Airdrop trigger function
612 | func dotherightthing(){
613 |
614 | if !self.hasExecuted2 {
615 |
616 | self.hasExecuted2 = true
617 |
618 | let sound = NSSound(named: UserDefaults.standard.value(forKey: "actualsound") as! NSSound.Name)
619 | sound?.play()
620 |
621 | //press "esc"
622 | let source = CGEventSource(stateID: .combinedSessionState)
623 | let keyDown = CGEvent(keyboardEventSource: source, virtualKey: 53, keyDown: true)
624 | keyDown?.post(tap: .cghidEventTap)
625 |
626 | FileManager.default.fileExists(atPath: self.filepath)
627 |
628 | let fileURL = URL(fileURLWithPath: self.filepath)
629 |
630 | //if multiple files
631 | if self.filepath.contains(","){
632 |
633 | let separatedElements = self.filepath.components(separatedBy: ",")
634 | let trimmedElements = separatedElements.map { $0.trimmingCharacters(in: .whitespaces) }
635 | var fileURLs = [URL]()
636 | for element in trimmedElements {
637 | let fileURL = URL(fileURLWithPath: element)
638 | fileURLs.append(fileURL)
639 | }
640 | let sharingService = NSSharingService(named: NSSharingService.Name.sendViaAirDrop)
641 | sharingService?.delegate = self
642 | sharingService?.perform(withItems: fileURLs)
643 | }
644 |
645 | //if only one file
646 | else{
647 | let sharingService = NSSharingService(named: NSSharingService.Name.sendViaAirDrop)
648 | sharingService?.delegate = self
649 | sharingService?.perform(withItems: [fileURL])
650 |
651 |
652 | }
653 |
654 | }
655 | }
656 |
657 | //vvv ONLY FOR APP START INDICATOR PURPOSE vvv
658 |
659 | func startMBP14(){
660 | let window = NSWindow(contentRect: NSMakeRect(635, 880, 250, 100), styleMask: .borderless, backing: .buffered, defer: false)
661 | window.level = .screenSaver
662 | window.isOpaque = false
663 | window.backgroundColor = .clear
664 |
665 | let blueView = NSView(frame: CGRect(x: 29, y: window.contentView!.frame.midY + 20 , width: window.contentView!.frame.width - 66, height: window.contentView!.frame.height - 5))
666 | blueView.wantsLayer = true
667 | blueView.layer?.backgroundColor = NSColor(red: 0, green: 123/255, blue: 254/255, alpha: 1).cgColor
668 | blueView.layer?.cornerRadius = 10
669 | blueView.isHidden = false
670 |
671 | let borderLayer = CALayer()
672 | borderLayer.frame = blueView.bounds
673 | borderLayer.cornerRadius = blueView.layer!.cornerRadius
674 | borderLayer.borderColor = NSColor.white.cgColor
675 | borderLayer.borderWidth = 6.0
676 | blueView.layer?.addSublayer(borderLayer)
677 |
678 | let animation = CABasicAnimation(keyPath: "borderColor")
679 | animation.fromValue = NSColor.clear.cgColor
680 | animation.toValue = NSColor.white.cgColor
681 | animation.duration = 1.618
682 | animation.autoreverses = true
683 | animation.repeatCount = Float.infinity
684 | borderLayer.add(animation, forKey: "borderColor")
685 |
686 | window.contentView?.addSubview(blueView)
687 | window.makeKeyAndOrderFront(nil)
688 |
689 |
690 | NSAnimationContext.runAnimationGroup({ (context) in
691 | context.duration = 1
692 | blueView.animator().frame.origin.y -= 6
693 | }, completionHandler: {
694 | blueView.frame.origin.y -= 0
695 | })
696 |
697 |
698 | DispatchQueue.main.asyncAfter(deadline: .now() + 0.6) {
699 | NSAnimationContext.runAnimationGroup({ (context) in
700 | context.duration = 1
701 | blueView.animator().frame.origin.y -= -6
702 | }, completionHandler: {
703 | blueView.frame.origin.y -= 0
704 | })
705 | DispatchQueue.main.asyncAfter(deadline: .now() + 1.4) {
706 | blueView.isHidden = true
707 | }
708 | }
709 | }
710 |
711 | func startMBP16(){
712 | let window = NSWindow(contentRect: NSMakeRect(725, 1001, 285.71, 113.74), styleMask: .borderless, backing: .buffered, defer: false)
713 | window.level = .screenSaver
714 | window.isOpaque = false
715 | window.backgroundColor = .clear
716 |
717 | let blueView = NSView(frame: CGRect(x: 29, y: window.contentView!.frame.midY + 20 , width: window.contentView!.frame.width - 66, height: window.contentView!.frame.height - 5))
718 | blueView.wantsLayer = true
719 | blueView.layer?.backgroundColor = NSColor(red: 0, green: 123/255, blue: 254/255, alpha: 1).cgColor
720 | blueView.layer?.cornerRadius = 10
721 | blueView.isHidden = false
722 |
723 | let borderLayer = CALayer()
724 | borderLayer.frame = blueView.bounds
725 | borderLayer.cornerRadius = blueView.layer!.cornerRadius
726 | borderLayer.borderColor = NSColor.white.cgColor
727 | borderLayer.borderWidth = 6.0
728 | blueView.layer?.addSublayer(borderLayer)
729 |
730 | let animation = CABasicAnimation(keyPath: "borderColor")
731 | animation.fromValue = NSColor.clear.cgColor
732 | animation.toValue = NSColor.white.cgColor
733 | animation.duration = 1.618
734 | animation.autoreverses = true
735 | animation.repeatCount = Float.infinity
736 | borderLayer.add(animation, forKey: "borderColor")
737 |
738 | window.contentView?.addSubview(blueView)
739 | window.makeKeyAndOrderFront(nil)
740 |
741 |
742 | NSAnimationContext.runAnimationGroup({ (context) in
743 | context.duration = 1
744 | blueView.animator().frame.origin.y -= 6
745 | }, completionHandler: {
746 | blueView.frame.origin.y -= 0
747 | })
748 |
749 |
750 | DispatchQueue.main.asyncAfter(deadline: .now() + 0.6) {
751 | NSAnimationContext.runAnimationGroup({ (context) in
752 | context.duration = 1
753 | blueView.animator().frame.origin.y -= -6
754 | }, completionHandler: {
755 | blueView.frame.origin.y -= 0
756 | })
757 | DispatchQueue.main.asyncAfter(deadline: .now() + 1.4) {
758 | blueView.isHidden = true
759 | }
760 | }
761 | }
762 |
763 | func startMBAM2(){
764 | let window = NSWindow(contentRect: NSMakeRect(617.36, 856.70, 243.05, 97.35), styleMask: .borderless, backing: .buffered, defer: false)
765 | window.level = .screenSaver
766 | window.isOpaque = false
767 | window.backgroundColor = .clear
768 |
769 | let blueView = NSView(frame: CGRect(x: 29, y: window.contentView!.frame.midY + 20 , width: window.contentView!.frame.width - 66, height: window.contentView!.frame.height - 5))
770 | blueView.wantsLayer = true
771 | blueView.layer?.backgroundColor = NSColor(red: 0, green: 123/255, blue: 254/255, alpha: 1).cgColor
772 | blueView.layer?.cornerRadius = 10
773 | blueView.isHidden = false
774 |
775 | let borderLayer = CALayer()
776 | borderLayer.frame = blueView.bounds
777 | borderLayer.cornerRadius = blueView.layer!.cornerRadius
778 | borderLayer.borderColor = NSColor.white.cgColor
779 | borderLayer.borderWidth = 6.0
780 | blueView.layer?.addSublayer(borderLayer)
781 |
782 | let animation = CABasicAnimation(keyPath: "borderColor")
783 | animation.fromValue = NSColor.clear.cgColor
784 | animation.toValue = NSColor.white.cgColor
785 | animation.duration = 1.618
786 | animation.autoreverses = true
787 | animation.repeatCount = Float.infinity
788 | borderLayer.add(animation, forKey: "borderColor")
789 |
790 | window.contentView?.addSubview(blueView)
791 | window.makeKeyAndOrderFront(nil)
792 |
793 |
794 | NSAnimationContext.runAnimationGroup({ (context) in
795 | context.duration = 1
796 | blueView.animator().frame.origin.y -= 6
797 | }, completionHandler: {
798 | blueView.frame.origin.y -= 0
799 | })
800 |
801 |
802 | DispatchQueue.main.asyncAfter(deadline: .now() + 0.6) {
803 | NSAnimationContext.runAnimationGroup({ (context) in
804 | context.duration = 1
805 | blueView.animator().frame.origin.y -= -6
806 | }, completionHandler: {
807 | blueView.frame.origin.y -= 0
808 | })
809 | DispatchQueue.main.asyncAfter(deadline: .now() + 1.4) {
810 | blueView.isHidden = true
811 | }
812 | }
813 | }
814 |
815 | }
816 |
817 |
--------------------------------------------------------------------------------