mirror of
https://github.com/leonboe1/QuickDrop.git
synced 2026-11-11 02:51:11 +00:00
Merge master
This commit is contained in:
1 parent
71c6e8bb3a
commit
149c375230
2 files changed
+64
-86
No files matched your search
+15
-11
@@ -14,10 +14,9 @@ import SwiftUI
|
||||
import UserNotifications
|
||||
|
||||
@main
|
||||
class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDelegate, NSWindowDelegate, MainAppDelegate {
|
||||
class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDelegate, NSWindowDelegate {
|
||||
|
||||
private var statusItem: NSStatusItem?
|
||||
private var activeIncomingTransfers: [String: TransferInfo] = [:]
|
||||
|
||||
var welcomeWindow: NSWindow?
|
||||
var plusWindow: NSWindow?
|
||||
@@ -27,6 +26,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
private var errorAlertHandler = ErrorAlertHandler.shared
|
||||
|
||||
private var iapManager: IAPManager?
|
||||
private var receiveModel: ReceiveModel?
|
||||
|
||||
var showsFirewallAlert = false
|
||||
var visibleItem: NSMenuItem? = nil
|
||||
@@ -65,9 +65,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
statusItem?.menu = menu
|
||||
statusItem?.behavior = .removalAllowed
|
||||
|
||||
NearbyConnectionManager.shared.mainAppDelegate = self
|
||||
NearbyConnectionManager.shared.becomeVisible()
|
||||
|
||||
iapManager = IAPManager.sharedInstance
|
||||
iapManager?.startObserving()
|
||||
|
||||
@@ -112,7 +109,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
|
||||
let queue2 = DispatchQueue(label: "NetworkConnectionMonitor")
|
||||
hasConnectionMonitor.start(queue: queue2)
|
||||
|
||||
|
||||
receiveModel = ReceiveModel(controlPlusScreen: { shouldOpen in
|
||||
if shouldOpen {
|
||||
self.openPlusScreen()
|
||||
@@ -136,7 +133,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
welcomeWindow = nil
|
||||
NSApp.setActivationPolicy(.accessory)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func applicationShouldHandleReopen(_: NSApplication, hasVisibleWindows _: Bool) -> Bool {
|
||||
@@ -187,8 +184,15 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
let pasteboard = NSPasteboard.general
|
||||
let clipboardString = pasteboard.string(forType: .string) ?? ""
|
||||
|
||||
let sharingService = NSSharingService(named: NSSharingService.Name("com.leonboettger.neardrop.ShareExtension"))
|
||||
sharingService?.perform(withItems: [clipboardString])
|
||||
if clipboardString.isEmpty {
|
||||
DispatchQueue.main.async {
|
||||
BezelNotification.show(messageText: "ClipboardEmpty".localized(), icon: .clipboard)
|
||||
}
|
||||
}
|
||||
else {
|
||||
let sharingService = NSSharingService(named: NSSharingService.Name("com.leonboettger.neardrop.ShareExtension"))
|
||||
sharingService?.perform(withItems: [clipboardString])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -243,7 +247,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
log("Plus screen already open, bringing to front")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
log("Opening Plus screen")
|
||||
|
||||
// Create the welcome screen SwiftUI view
|
||||
@@ -318,7 +322,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// MARK: - Helper Functions
|
||||
|
||||
private func performDeviceToDeviceCheck() {
|
||||
|
||||
@@ -8,8 +8,10 @@
|
||||
import Cocoa
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import QRCode
|
||||
|
||||
class ShareViewController: NSViewController, ShareExtensionDelegate {
|
||||
class ShareViewController: NSViewController, OutboundAppDelegate {
|
||||
|
||||
private var urls: [URL] = []
|
||||
private var textToSend: String? = nil
|
||||
private var foundDevices: [RemoteDeviceInfo] = []
|
||||
@@ -46,11 +48,12 @@ class ShareViewController: NSViewController, ShareExtensionDelegate {
|
||||
|
||||
|
||||
override func loadView() {
|
||||
|
||||
super.loadView()
|
||||
loadAttachments(with: extensionContext, loadedItems: { result in
|
||||
|
||||
|
||||
log("Loaded attachments: \(result)")
|
||||
|
||||
|
||||
self.urls = result.urls
|
||||
self.textToSend = result.textToSend
|
||||
self.filesLabel?.stringValue = result.shortDescription
|
||||
@@ -93,6 +96,7 @@ class ShareViewController: NSViewController, ShareExtensionDelegate {
|
||||
|
||||
|
||||
override func viewDidLoad() {
|
||||
|
||||
super.viewDidLoad()
|
||||
|
||||
dicoverDevices()
|
||||
@@ -128,7 +132,27 @@ class ShareViewController: NSViewController, ShareExtensionDelegate {
|
||||
|
||||
private func openQrCodeView() {
|
||||
if qrCodeSheetView == nil {
|
||||
let contentView = SmallSheetView(type: .sendToDeviceQrCode) {
|
||||
|
||||
var image: Image? = nil
|
||||
|
||||
do {
|
||||
let qrKey = NearbyConnectionManager.shared.generateQrCodeKey()
|
||||
let qrCodeImage = try QRCode.build
|
||||
.text("https://quickshare.google/qrcode#key=\(qrKey)")
|
||||
.backgroundColor(CGColor(srgbRed: 1, green: 1, blue: 1, alpha: 0))
|
||||
.quietZonePixelCount(3)
|
||||
.onPixels.shape(.circle())
|
||||
.eye.shape(.squircle())
|
||||
.errorCorrection(.low)
|
||||
.generate.image(dimension: 1000)
|
||||
|
||||
image = Image(nsImage: NSImage(cgImage: qrCodeImage, size: qrCodeImage.size))
|
||||
}
|
||||
catch {
|
||||
log("Error generating QR code: \(error)")
|
||||
}
|
||||
|
||||
let contentView = SmallSheetView(type: .sendToDeviceQrCode, dynamicQrCode: image) {
|
||||
self.closeQrCodeView()
|
||||
}
|
||||
|
||||
@@ -161,71 +185,11 @@ class ShareViewController: NSViewController, ShareExtensionDelegate {
|
||||
}
|
||||
|
||||
|
||||
private func zipFolderAndSetUpIcon() {
|
||||
for url in urls {
|
||||
if url.isFileURL {
|
||||
let isDirectory = UnsafeMutablePointer<ObjCBool>.allocate(capacity: 1)
|
||||
if FileManager.default.fileExists(atPath: url.path, isDirectory: isDirectory) && isDirectory.pointee.boolValue {
|
||||
do {
|
||||
let zipUrl = try createZipAtTmp(zipFilename: url.lastPathComponent, fromDirectory: url)
|
||||
|
||||
let index = urls.firstIndex(of: url)
|
||||
urls[index!] = zipUrl
|
||||
} catch {
|
||||
log("Error creating zip file: \(error)")
|
||||
|
||||
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
|
||||
|
||||
alert.messageText = "TypeNotSupported".localized()
|
||||
alert.informativeText = "TypeNotSupportedDescription".localized()
|
||||
alert.addButton(withTitle: "TypeNotSupportedButton".localized())
|
||||
|
||||
alert.beginSheetModal(for: self.view.window!) { _ in
|
||||
let cancelError = NSError(domain: NSCocoaErrorDomain, code: NSUserCancelledError, userInfo: nil)
|
||||
self.extensionContext!.cancelRequest(withError: cancelError)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let textToSend = textToSend {
|
||||
let maxLength = 50
|
||||
let cleanedText = textToSend.replacingOccurrences(of: "\n", with: " ").replacingOccurrences(of: "\r", with: "")
|
||||
|
||||
if cleanedText.count > maxLength {
|
||||
let index = cleanedText.index(cleanedText.startIndex, offsetBy: maxLength)
|
||||
filesLabel!.stringValue = String(cleanedText[..<index]) + "..."
|
||||
} else {
|
||||
filesLabel!.stringValue = cleanedText
|
||||
}
|
||||
|
||||
filesIcon!.image = NSImage(named: NSImage.multipleDocumentsName)
|
||||
}
|
||||
else if urls.count == 1 {
|
||||
if urls[0].isFileURL {
|
||||
filesLabel!.stringValue = urls[0].lastPathComponent
|
||||
filesIcon!.image = NSWorkspace.shared.icon(forFile: urls[0].path)
|
||||
} else if urls[0].scheme == "http" || urls[0].scheme == "https" {
|
||||
filesLabel!.stringValue = urls[0].absoluteString
|
||||
filesIcon!.image = NSImage(named: NSImage.networkName)
|
||||
}
|
||||
} else {
|
||||
filesLabel!.stringValue = String.localizedStringWithFormat("NFiles".localized(), urls.count)
|
||||
filesIcon!.image = NSImage(named: NSImage.multipleDocumentsName)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func addDevice(device: RemoteDeviceInfo) {
|
||||
|
||||
if chosenDevice != nil {
|
||||
return
|
||||
}
|
||||
if foundDevices.isEmpty {
|
||||
loadingOverlay?.animator().isHidden = true
|
||||
}
|
||||
@@ -237,6 +201,7 @@ class ShareViewController: NSViewController, ShareExtensionDelegate {
|
||||
|
||||
|
||||
func removeDevice(id: String) {
|
||||
|
||||
if chosenDevice != nil {
|
||||
return
|
||||
}
|
||||
@@ -253,6 +218,12 @@ class ShareViewController: NSViewController, ShareExtensionDelegate {
|
||||
}
|
||||
|
||||
|
||||
func startTransferWithQrCode(device: RemoteDeviceInfo) {
|
||||
closeQrCodeView()
|
||||
selectDevice(device: device)
|
||||
}
|
||||
|
||||
|
||||
func connectionWasEstablished(pinCode: String) {
|
||||
connectionEstablished = true
|
||||
|
||||
@@ -291,7 +262,6 @@ class ShareViewController: NSViewController, ShareExtensionDelegate {
|
||||
|
||||
|
||||
func selectDevice(device: RemoteDeviceInfo) {
|
||||
NearbyConnectionManager.shared.stopDeviceDiscovery()
|
||||
|
||||
listViewWrapper?.animator().isHidden = true
|
||||
dontSeeDeviceButton?.animator().isHidden = true
|
||||
@@ -301,6 +271,7 @@ class ShareViewController: NSViewController, ShareExtensionDelegate {
|
||||
progressProgressBar?.startAnimation(nil)
|
||||
progressState?.stringValue = "Connecting".localized()
|
||||
chosenDevice = device
|
||||
NearbyConnectionManager.shared.stopDeviceDiscovery()
|
||||
NearbyConnectionManager.shared.startOutgoingTransfer(deviceID: device.id!, delegate: self, urls: urls, textToSend: textToSend)
|
||||
|
||||
let timeoutAlert = DispatchWorkItem {
|
||||
@@ -334,6 +305,7 @@ class ShareViewController: NSViewController, ShareExtensionDelegate {
|
||||
|
||||
|
||||
private func dicoverDevices() {
|
||||
|
||||
let bundleIdentifier = "com.leonboettger.neardrop"
|
||||
let runningApps = NSWorkspace.shared.runningApplications
|
||||
|
||||
@@ -346,13 +318,13 @@ class ShareViewController: NSViewController, ShareExtensionDelegate {
|
||||
let configuration = NSWorkspace.OpenConfiguration()
|
||||
NSWorkspace.shared.openApplication(at: url, configuration: configuration) { app, error in
|
||||
if let error = error {
|
||||
print("Failed to launch application: \(error)")
|
||||
log("Failed to launch application: \(error)")
|
||||
} else {
|
||||
print("Application launched successfully")
|
||||
log("Application launched successfully")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
print("Could not find application with bundle identifier \(bundleIdentifier)")
|
||||
log("Could not find application with bundle identifier \(bundleIdentifier)")
|
||||
}
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
|
||||
@@ -368,6 +340,7 @@ class ShareViewController: NSViewController, ShareExtensionDelegate {
|
||||
|
||||
|
||||
private func scheduleAutomaticQrCodeView() {
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 2.5) {
|
||||
if self.foundDevices.isEmpty {
|
||||
self.openQrCodeView()
|
||||
@@ -421,9 +394,10 @@ extension ShareViewController: NSCollectionViewDataSource {
|
||||
|
||||
|
||||
func getDeviceName(device: RemoteDeviceInfo) -> String {
|
||||
if device.name.count <= 1 {
|
||||
return "Android"
|
||||
if let name = device.name, name.count > 1 {
|
||||
return name
|
||||
}
|
||||
return device.name
|
||||
|
||||
return "Android"
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user