mirror of
https://github.com/leonboe1/QuickDrop.git
synced 2026-11-11 02:51:11 +00:00
Add ability to open app at login
This commit is contained in:
1 parent
eac2df3d44
commit
5bf8469732
12 files changed
+1960
-1533
No files matched your search
@@ -74,6 +74,14 @@
|
||||
EB5C37FF2E377CE70052EFD7 /* wire_format.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69DA9A2929E18CB500A442DA /* wire_format.pb.swift */; };
|
||||
EB5C38002E377CE70052EFD7 /* DataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB5C36E82E3546100052EFD7 /* DataModel.swift */; };
|
||||
EB5C38012E377DE60052EFD7 /* Localized.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB96ED8E2D7F8103004B3FF1 /* Localized.swift */; };
|
||||
EB5C38392E38C1F60052EFD7 /* justMaybe.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = EB5C38382E38C1F60052EFD7 /* justMaybe.mp3 */; };
|
||||
EB5C383A2E38C1F60052EFD7 /* justMaybe.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = EB5C38382E38C1F60052EFD7 /* justMaybe.mp3 */; };
|
||||
EB5C383B2E38C1F60052EFD7 /* justMaybe.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = EB5C38382E38C1F60052EFD7 /* justMaybe.mp3 */; };
|
||||
EB5C383C2E38C2D90052EFD7 /* AudioManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB36435F2D73A29F009CDFF8 /* AudioManager.swift */; };
|
||||
EB5C383D2E38C2D90052EFD7 /* AudioManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB36435F2D73A29F009CDFF8 /* AudioManager.swift */; };
|
||||
EB5C383F2E38C49D0052EFD7 /* LaunchAtLogin.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB5C383E2E38C49D0052EFD7 /* LaunchAtLogin.swift */; };
|
||||
EB5C38402E38C49D0052EFD7 /* LaunchAtLogin.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB5C383E2E38C49D0052EFD7 /* LaunchAtLogin.swift */; };
|
||||
EB5C38412E38C49D0052EFD7 /* LaunchAtLogin.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB5C383E2E38C49D0052EFD7 /* LaunchAtLogin.swift */; };
|
||||
EB6F62D72D91F4AF00534EC2 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB6F62D62D91F4AC00534EC2 /* SettingsView.swift */; };
|
||||
EB7CD1452D6FB0C300CB0CB5 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB7CD1442D6FB0C100CB0CB5 /* Logger.swift */; };
|
||||
EB7CD1462D6FB0E800CB0CB5 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB7CD1442D6FB0C100CB0CB5 /* Logger.swift */; };
|
||||
@@ -201,6 +209,8 @@
|
||||
EB5C36E62E3544FB0052EFD7 /* SaveFilesManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SaveFilesManager.swift; sourceTree = "<group>"; };
|
||||
EB5C36E82E3546100052EFD7 /* DataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataModel.swift; sourceTree = "<group>"; };
|
||||
EB5C37E22E377C2E0052EFD7 /* QuickDropiOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = QuickDropiOS.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
EB5C38382E38C1F60052EFD7 /* justMaybe.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = justMaybe.mp3; sourceTree = "<group>"; };
|
||||
EB5C383E2E38C49D0052EFD7 /* LaunchAtLogin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchAtLogin.swift; sourceTree = "<group>"; };
|
||||
EB6E743D2DD5C76F00331466 /* ConnectionFailureTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionFailureTracker.swift; sourceTree = "<group>"; };
|
||||
EB6F62D62D91F4AC00534EC2 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
|
||||
EB7CD1442D6FB0C100CB0CB5 /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
|
||||
@@ -424,6 +434,7 @@
|
||||
EBC05C6B2E33B57100EECC18 /* Util */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
EB5C383E2E38C49D0052EFD7 /* LaunchAtLogin.swift */,
|
||||
EB36435F2D73A29F009CDFF8 /* AudioManager.swift */,
|
||||
EBC05C5A2E33936C00EECC18 /* ErrorAlertHandler.swift */,
|
||||
);
|
||||
@@ -465,6 +476,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
EB5C36E32E34EC0E0052EFD7 /* License.txt */,
|
||||
EB5C38382E38C1F60052EFD7 /* justMaybe.mp3 */,
|
||||
EBC05C8A2E33B59E00EECC18 /* timeIsNow.mp3 */,
|
||||
);
|
||||
path = Resources;
|
||||
@@ -614,6 +626,7 @@
|
||||
691F53BC2ABB70840089FD92 /* DeviceListCell.xib in Resources */,
|
||||
699DEBA92AB0573200115D22 /* ShareViewController.xib in Resources */,
|
||||
EB96ED8D2D7F7EA3004B3FF1 /* Assets.xcassets in Resources */,
|
||||
EB5C383A2E38C1F60052EFD7 /* justMaybe.mp3 in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -626,6 +639,7 @@
|
||||
EB5C36932E34EBBD0052EFD7 /* Localizable.xcstrings in Resources */,
|
||||
EBC05C8C2E33B59E00EECC18 /* timeIsNow.mp3 in Resources */,
|
||||
69D2C32F29E7898C00EC7E30 /* MainMenu.xib in Resources */,
|
||||
EB5C38392E38C1F60052EFD7 /* justMaybe.mp3 in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -633,6 +647,7 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
EB5C383B2E38C1F60052EFD7 /* justMaybe.mp3 in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -657,12 +672,14 @@
|
||||
EB5C37C72E377A780052EFD7 /* wire_format.pb.swift in Sources */,
|
||||
EB5C37C82E377A780052EFD7 /* ukey.pb.swift in Sources */,
|
||||
EB5C37C92E377A780052EFD7 /* device_to_device_messages.pb.swift in Sources */,
|
||||
EB5C383C2E38C2D90052EFD7 /* AudioManager.swift in Sources */,
|
||||
EB5C37CA2E377A780052EFD7 /* offline_wire_formats.pb.swift in Sources */,
|
||||
EBC05C5C2E3394EF00EECC18 /* ErrorAlertHandler.swift in Sources */,
|
||||
EBC05C7B2E33B58100EECC18 /* ActiveNetworkInterface.swift in Sources */,
|
||||
EBC05C7C2E33B58100EECC18 /* ApIsolationTester.swift in Sources */,
|
||||
691F53BB2ABB70840089FD92 /* DeviceListCell.swift in Sources */,
|
||||
EB5C37BB2E377A700052EFD7 /* ConnectionFailureTracker.swift in Sources */,
|
||||
EB5C383F2E38C49D0052EFD7 /* LaunchAtLogin.swift in Sources */,
|
||||
EB5C37BC2E377A700052EFD7 /* SleepManager.swift in Sources */,
|
||||
EB5C37D02E377A7F0052EFD7 /* OutboundNearbyConnection.swift in Sources */,
|
||||
EB5C37D12E377A7F0052EFD7 /* DataModel.swift in Sources */,
|
||||
@@ -681,6 +698,7 @@
|
||||
EBD2A2172D2860C100BCB8E2 /* WelcomeScreen.swift in Sources */,
|
||||
EB3643602D73A2A2009CDFF8 /* AudioManager.swift in Sources */,
|
||||
EB5C37B72E377A6F0052EFD7 /* ConnectionFailureTracker.swift in Sources */,
|
||||
EB5C38412E38C49D0052EFD7 /* LaunchAtLogin.swift in Sources */,
|
||||
EB5C37B82E377A6F0052EFD7 /* SleepManager.swift in Sources */,
|
||||
EB5C37B92E377A6F0052EFD7 /* SaveFilesManager.swift in Sources */,
|
||||
EB5C37BA2E377A6F0052EFD7 /* Helpers.swift in Sources */,
|
||||
@@ -735,6 +753,8 @@
|
||||
EB5C37FC2E377CE70052EFD7 /* OutboundNearbyConnection.swift in Sources */,
|
||||
EB5C37FD2E377CE70052EFD7 /* Logger.swift in Sources */,
|
||||
EB5C37FE2E377CE70052EFD7 /* offline_wire_formats.pb.swift in Sources */,
|
||||
EB5C383D2E38C2D90052EFD7 /* AudioManager.swift in Sources */,
|
||||
EB5C38402E38C49D0052EFD7 /* LaunchAtLogin.swift in Sources */,
|
||||
EB5C37FF2E377CE70052EFD7 /* wire_format.pb.swift in Sources */,
|
||||
EB5C38002E377CE70052EFD7 /* DataModel.swift in Sources */,
|
||||
);
|
||||
|
||||
@@ -304,6 +304,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
|
||||
DispatchQueue.main.async {
|
||||
|
||||
AudioManager.playErrorSound()
|
||||
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
|
||||
let alert = NSAlert()
|
||||
@@ -337,7 +339,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
|
||||
activeIncomingTransfers[transfer.id] = TransferInfo(device: device, transfer: transfer)
|
||||
|
||||
AudioManager.playSound()
|
||||
AudioManager.playIncomingFileSound()
|
||||
|
||||
let acceptAutomatically = UserDefaults.standard.bool(forKey: UserDefaultsKeys.automaticallyAcceptFiles.rawValue)
|
||||
|
||||
|
||||
+1741
-1527
File diff suppressed because it is too large.
Load diff
@@ -8,17 +8,32 @@
|
||||
import AVFoundation
|
||||
|
||||
class AudioManager {
|
||||
static var audioPlayer: AVAudioPlayer?
|
||||
static private var incomingFileSoundPlayer: AVAudioPlayer?
|
||||
static private var errorSoundPlayer: AVAudioPlayer?
|
||||
|
||||
static func playSound() {
|
||||
static func playIncomingFileSound() {
|
||||
guard let soundURL = Bundle.main.url(forResource: "timeIsNow", withExtension: "mp3") else {
|
||||
log("Sound file not found")
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
audioPlayer = try AVAudioPlayer(contentsOf: soundURL)
|
||||
audioPlayer?.play()
|
||||
incomingFileSoundPlayer = try AVAudioPlayer(contentsOf: soundURL)
|
||||
incomingFileSoundPlayer?.play()
|
||||
} catch {
|
||||
log("Error playing sound: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
|
||||
static func playErrorSound() {
|
||||
guard let soundURL = Bundle.main.url(forResource: "justMaybe", withExtension: "mp3") else {
|
||||
log("Sound file not found")
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
errorSoundPlayer = try AVAudioPlayer(contentsOf: soundURL)
|
||||
errorSoundPlayer?.play()
|
||||
} catch {
|
||||
log("Error playing sound: \(error.localizedDescription)")
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@ class ErrorAlertHandler {
|
||||
return
|
||||
}
|
||||
else {
|
||||
AudioManager.playErrorSound()
|
||||
self.isAlertShown = true
|
||||
log("Showing alert with message: \"\(alert.messageText)\" and description: \"\(alert.informativeText)\"")
|
||||
log("Unsuccessful transmission. Already successful transmissions: \(transmissionCount())")
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
|
||||
LaunchAtLogin-Modern
|
||||
https://github.com/sindresorhus/LaunchAtLogin-Modern
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#if os(macOS) || targetEnvironment(macCatalyst)
|
||||
import SwiftUI
|
||||
import ServiceManagement
|
||||
import os.log
|
||||
|
||||
@available(macOS 13.0, *)
|
||||
public enum LaunchAtLogin {
|
||||
fileprivate static let observable = Observable()
|
||||
|
||||
/**
|
||||
Toggle “launch at login” for your app or check whether it's enabled.
|
||||
*/
|
||||
public static var isEnabled: Bool {
|
||||
get { SMAppService.mainApp.status == .enabled }
|
||||
set {
|
||||
observable.objectWillChange.send()
|
||||
|
||||
do {
|
||||
if newValue {
|
||||
if SMAppService.mainApp.status == .enabled {
|
||||
try? SMAppService.mainApp.unregister()
|
||||
}
|
||||
|
||||
try SMAppService.mainApp.register()
|
||||
} else {
|
||||
try SMAppService.mainApp.unregister()
|
||||
}
|
||||
} catch {
|
||||
log("Failed to \(newValue ? "enable" : "disable") launch at login: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Whether the app was launched at login.
|
||||
|
||||
- Important: This property must only be checked in `NSApplicationDelegate#applicationDidFinishLaunching`.
|
||||
*/
|
||||
public static var wasLaunchedAtLogin: Bool {
|
||||
let event = NSAppleEventManager.shared().currentAppleEvent
|
||||
return event?.eventID == kAEOpenApplication
|
||||
&& event?.paramDescriptor(forKeyword: keyAEPropData)?.enumCodeValue == keyAELaunchedAsLogInItem
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@available(macOS 13.0, *)
|
||||
extension LaunchAtLogin {
|
||||
final class Observable: ObservableObject {
|
||||
var isEnabled: Bool {
|
||||
get { LaunchAtLogin.isEnabled }
|
||||
set {
|
||||
LaunchAtLogin.isEnabled = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@available(macOS 13.0, *)
|
||||
extension LaunchAtLogin {
|
||||
/**
|
||||
This package comes with a `LaunchAtLogin.Toggle` view which is like the built-in `Toggle` but with a predefined binding and label. Clicking the view toggles “launch at login” for your app.
|
||||
|
||||
```
|
||||
struct ContentView: View {
|
||||
var body: some View {
|
||||
LaunchAtLogin.Toggle()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The default label is `"Launch at login"`, but it can be overridden for localization and other needs:
|
||||
|
||||
```
|
||||
struct ContentView: View {
|
||||
var body: some View {
|
||||
LaunchAtLogin.Toggle {
|
||||
Text("Launch at login")
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
*/
|
||||
public struct Toggle<Label: View>: View {
|
||||
@ObservedObject private var launchAtLogin = LaunchAtLogin.observable
|
||||
private let label: Label
|
||||
|
||||
/**
|
||||
Creates a toggle that displays a custom label.
|
||||
|
||||
- Parameters:
|
||||
- label: A view that describes the purpose of the toggle.
|
||||
*/
|
||||
public init(@ViewBuilder label: () -> Label) {
|
||||
self.label = label()
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
SwiftUI.Toggle(isOn: $launchAtLogin.isEnabled) { label }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@available(macOS 13.0, *)
|
||||
extension LaunchAtLogin.Toggle<Text> {
|
||||
/**
|
||||
Creates a toggle that generates its label from a localized string key.
|
||||
|
||||
This initializer creates a ``Text`` view on your behalf with the provided `titleKey`.
|
||||
|
||||
- Parameters:
|
||||
- titleKey: The key for the toggle's localized title, that describes the purpose of the toggle.
|
||||
*/
|
||||
public init(_ titleKey: LocalizedStringKey) {
|
||||
label = Text(titleKey)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a toggle that generates its label from a string.
|
||||
|
||||
This initializer creates a `Text` view on your behalf with the provided `title`.
|
||||
|
||||
- Parameters:
|
||||
- title: A string that describes the purpose of the toggle.
|
||||
*/
|
||||
public init(_ title: some StringProtocol) {
|
||||
label = Text(title)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a toggle with the default title of `Launch at login`.
|
||||
*/
|
||||
public init() {
|
||||
self.init("Launch at login")
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -62,6 +62,7 @@ func openRouterSettingsPage() async {
|
||||
|
||||
guard let routerIP else {
|
||||
DispatchQueue.main.async {
|
||||
AudioManager.playErrorSound()
|
||||
let alert = NSAlert()
|
||||
alert.alertStyle = .critical
|
||||
|
||||
|
||||
@@ -45,6 +45,21 @@ struct SettingsView: View {
|
||||
Toggle("OpenFinderAfterReceiving", isOn: $openFinderAfterReceiving)
|
||||
.padding(.top, 5)
|
||||
|
||||
Text("OpenFinderAfterReceivingFooter")
|
||||
.font(.footnote)
|
||||
.padding(.top, 5)
|
||||
|
||||
|
||||
if #available(macOS 13.0, *) {
|
||||
|
||||
Divider()
|
||||
.padding(.vertical, 10)
|
||||
|
||||
LaunchAtLogin.Toggle {
|
||||
Text("LaunchAtLogin")
|
||||
}
|
||||
.padding(.top, 5)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ struct LargeAppIconView<Content: View>: View {
|
||||
Image("AppIconHighRes")
|
||||
.resizable()
|
||||
.frame(width: 150, height: 150)
|
||||
.padding(.top, 50)
|
||||
.padding(.top, 40)
|
||||
|
||||
Text(title.localized())
|
||||
.font(.largeTitle)
|
||||
|
||||
@@ -327,5 +327,6 @@ Terms of use: https://notificationsounds.com/terms-of-use
|
||||
Sound files:
|
||||
|
||||
https://notificationsounds.com/notification-sounds/time-is-now-585
|
||||
https://notificationsounds.com/notification-sounds/just-maybe-577
|
||||
|
||||
Modifications to sound files: Volume and length, no previous modifications.
|
||||
Binary file not shown.
@@ -203,6 +203,7 @@ class ShareViewController: NSViewController, ShareExtensionDelegate {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
log("Canceling share request because URL \(url) is a directory")
|
||||
|
||||
AudioManager.playErrorSound()
|
||||
let alert = NSAlert()
|
||||
alert.alertStyle = .critical
|
||||
|
||||
@@ -330,6 +331,7 @@ class ShareViewController: NSViewController, ShareExtensionDelegate {
|
||||
|
||||
let timeoutAlert = DispatchWorkItem {
|
||||
if !self.connectionEstablished {
|
||||
AudioManager.playErrorSound()
|
||||
let alert = NSAlert()
|
||||
alert.alertStyle = .critical
|
||||
|
||||
|
||||
Reference in new issue
Block a user