Make it run on Catalina

closes #158, closes #77
This commit is contained in:
Grishka
2024-05-23 00:07:12 +03:00
parent 10d63f13bd
commit 5e69970af8
11 changed files with 102 additions and 59 deletions

View File

@@ -662,7 +662,7 @@
"@executable_path/../Frameworks",
"@executable_path/../../../../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 2.0.2;
PRODUCT_BUNDLE_IDENTIFIER = me.grishka.NearDrop.ShareExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -688,7 +688,7 @@
"@executable_path/../Frameworks",
"@executable_path/../../../../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 2.0.2;
PRODUCT_BUNDLE_IDENTIFIER = me.grishka.NearDrop.ShareExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -749,7 +749,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 11.0;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
@@ -804,7 +804,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 11.0;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = macosx;
@@ -823,7 +823,7 @@
CODE_SIGN_ENTITLEMENTS = NearDrop/NearDrop.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 7;
CURRENT_PROJECT_VERSION = 8;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
INFOPLIST_KEY_LSUIElement = YES;
@@ -834,8 +834,8 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 2.0.3;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 2.0.4;
PRODUCT_BUNDLE_IDENTIFIER = me.grishka.NearDrop;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
@@ -855,7 +855,7 @@
CODE_SIGN_ENTITLEMENTS = NearDrop/NearDrop.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 7;
CURRENT_PROJECT_VERSION = 8;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
INFOPLIST_KEY_LSUIElement = YES;
@@ -866,8 +866,8 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 2.0.3;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 2.0.4;
PRODUCT_BUNDLE_IDENTIFIER = me.grishka.NearDrop;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
@@ -885,7 +885,7 @@
DYLIB_INSTALL_NAME_BASE = "@executable_path/../Frameworks";
EXECUTABLE_PREFIX = lib;
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
MACOSX_DEPLOYMENT_TARGET = 11.0;
MACOSX_DEPLOYMENT_TARGET = 10.15;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
@@ -901,7 +901,7 @@
DYLIB_INSTALL_NAME_BASE = "@executable_path/../Frameworks";
EXECUTABLE_PREFIX = lib;
LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
MACOSX_DEPLOYMENT_TARGET = 11.0;
MACOSX_DEPLOYMENT_TARGET = 10.15;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;

View File

@@ -34,7 +34,10 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
}
}
nc.delegate=self
let incomingTransfersCategory=NDNotificationCenterHackery.hackedNotificationCategory()
let incomingTransfersCategory=UNNotificationCategory(identifier: "INCOMING_TRANSFERS", actions: [
UNNotificationAction(identifier: "ACCEPT", title: NSLocalizedString("Accept", comment: ""), options: UNNotificationActionOptions.authenticationRequired),
UNNotificationAction(identifier: "DECLINE", title: NSLocalizedString("Decline", comment: ""))
], intentIdentifiers: [])
let errorsCategory=UNNotificationCategory(identifier: "ERRORS", actions: [], intentIdentifiers: [])
nc.setNotificationCategories([incomingTransfersCategory, errorsCategory])
NearbyConnectionManager.shared.mainAppDelegate=self
@@ -79,9 +82,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
}
func obtainUserConsent(for transfer: TransferMetadata, from device: RemoteDeviceInfo) {
let notificationContent=UNMutableNotificationContent()
notificationContent.title="NearDrop"
notificationContent.subtitle=String(format:NSLocalizedString("PinCode", value: "PIN: %@", comment: ""), arguments: [transfer.pinCode!])
let fileStr:String
if let textTitle=transfer.textDescription{
fileStr=textTitle
@@ -90,14 +90,19 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
}else{
fileStr=String.localizedStringWithFormat(NSLocalizedString("NFiles", value: "%d files", comment: ""), transfer.files.count)
}
let notificationContent=UNMutableNotificationContent()
notificationContent.title="NearDrop"
notificationContent.subtitle=String(format:NSLocalizedString("PinCode", value: "PIN: %@", comment: ""), arguments: [transfer.pinCode!])
notificationContent.body=String(format: NSLocalizedString("DeviceSendingFiles", value: "%1$@ is sending you %2$@", comment: ""), arguments: [device.name, fileStr])
notificationContent.sound = .default
notificationContent.categoryIdentifier="INCOMING_TRANSFERS"
notificationContent.userInfo=["transferID": transfer.id]
if #available(macOS 11.0, *){
NDNotificationCenterHackery.removeDefaultAction(notificationContent)
}
let notificationReq=UNNotificationRequest(identifier: "transfer_"+transfer.id, content: notificationContent, trigger: nil)
self.activeIncomingTransfers[transfer.id]=TransferInfo(device: device, transfer: transfer)
UNUserNotificationCenter.current().add(notificationReq)
self.activeIncomingTransfers[transfer.id]=TransferInfo(device: device, transfer: transfer)
}
func incomingTransfer(id: String, didFinishWith error: Error?) {
@@ -107,8 +112,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
notificationContent.title=String(format: NSLocalizedString("TransferError", value: "Failed to receive files from %@", comment: ""), arguments: [transfer.device.name])
if let ne=(error as? NearbyError){
switch ne{
case .inputOutput(let er):
notificationContent.body=er.localizedDescription
case .inputOutput:
notificationContent.body="I/O Error";
case .protocolError(_):
notificationContent.body=NSLocalizedString("Error.Protocol", value: "Communication error", comment: "")
case .requiredFieldMissing:

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21701" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22505" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21701"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22505"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">

View File

@@ -12,7 +12,6 @@ NS_ASSUME_NONNULL_BEGIN
@interface NDNotificationCenterHackery : NSObject
+ (UNNotificationCategory*)hackedNotificationCategory;
+ (void)removeDefaultAction:(UNMutableNotificationContent*) content;
@end

View File

@@ -35,13 +35,6 @@
@implementation NDNotificationCenterHackery
+ (UNNotificationCategory*)hackedNotificationCategory{
UNNotificationAction *accept=[UNNotificationAction actionWithIdentifier:@"ACCEPT" title:NSLocalizedString(@"Accept", nil) options:0];
UNNotificationAction *decline=[UNNotificationAction actionWithIdentifier:@"DECLINE" title:NSLocalizedString(@"Decline", nil) options:0];
UNMutableNotificationCategory *category=[UNMutableNotificationCategory categoryWithIdentifier:@"INCOMING_TRANSFERS" actions:@[accept, decline] intentIdentifiers:@[] hiddenPreviewsBodyPlaceholder:@"" options: UNNotificationCategoryOptionCustomDismissAction];
return category;
}
+ (void)removeDefaultAction:(UNMutableNotificationContent*) content{
content.hasDefaultAction=false;
}

View File

@@ -103,7 +103,7 @@ class InboundNearbyConnection: NearbyConnection{
guard frame.payloadChunk.offset==currentOffset else { throw NearbyError.protocolError("Invalid offset into file \(frame.payloadChunk.offset), expected \(currentOffset)") }
guard currentOffset+Int64(frame.payloadChunk.body.count)<=fileInfo.meta.size else { throw NearbyError.protocolError("Transferred file size exceeds previously specified value") }
if frame.payloadChunk.body.count>0{
try fileInfo.fileHandle?.write(contentsOf: frame.payloadChunk.body)
fileInfo.fileHandle?.write(frame.payloadChunk.body)
transferredFiles[id]!.bytesTransferred+=Int64(frame.payloadChunk.body.count)
fileInfo.progress?.completedUnitCount=transferredFiles[id]!.bytesTransferred
}else if (frame.payloadChunk.flags & 1)==1{

View File

@@ -319,6 +319,31 @@ class NearbyConnection{
return String(format: "%04d", abs(hash))
}
internal static func hkdfExtract(salt:Data, ikm:Data) -> Data{
return HMAC<SHA256>.authenticationCode(for: ikm, using: SymmetricKey(data: salt)).withUnsafeBytes({return Data(bytes: $0.baseAddress!, count: $0.count)})
}
internal static func hkdfExpand(prk:Data, info:Data, length:Int) -> Data{
var okm=Data()
var t=Data()
var i=0
while okm.count<length{
i=i+1
let toDigest=t+info+Data([UInt8(truncatingIfNeeded: i)])
t=HMAC<SHA256>.authenticationCode(for: toDigest, using: SymmetricKey(data: prk)).withUnsafeBytes({return Data(bytes: $0.baseAddress!, count: $0.count)})
okm=okm+t
}
return okm.subdata(in: 0..<length)
}
internal static func hkdf(inputKeyMaterial:SymmetricKey, salt:Data, info:Data, outputByteCount:Int) -> SymmetricKey{
if #available(macOS 11.0, *){
return HKDF<SHA256>.deriveKey(inputKeyMaterial: inputKeyMaterial, salt: salt, info: info, outputByteCount: outputByteCount)
}else{
return SymmetricKey(data: hkdfExpand(prk: hkdfExtract(salt: salt, ikm: inputKeyMaterial.withUnsafeBytes({return Data(bytes: $0.baseAddress!, count: $0.count)})), info: info, length: outputByteCount))
}
}
internal func finalizeKeyExchange(peerKey:Securemessage_GenericPublicKey) throws{
guard peerKey.hasEcP256PublicKey else { throw NearbyError.requiredFieldMissing("peerKey.ecP256PublicKey") }
@@ -341,8 +366,8 @@ class NearbyConnection{
var ukeyInfo=Data()
ukeyInfo.append(ukeyClientInitMsgData!)
ukeyInfo.append(ukeyServerInitMsgData!)
let authString=HKDF<SHA256>.deriveKey(inputKeyMaterial: SymmetricKey(data: derivedSecretKey), salt: "UKEY2 v1 auth".data(using: .utf8)!, info: ukeyInfo, outputByteCount: 32)
let nextSecret=HKDF<SHA256>.deriveKey(inputKeyMaterial: SymmetricKey(data: derivedSecretKey), salt: "UKEY2 v1 next".data(using: .utf8)!, info: ukeyInfo, outputByteCount: 32)
let authString=NearbyConnection.hkdf(inputKeyMaterial: SymmetricKey(data: derivedSecretKey), salt: "UKEY2 v1 auth".data(using: .utf8)!, info: ukeyInfo, outputByteCount: 32)
let nextSecret=NearbyConnection.hkdf(inputKeyMaterial: SymmetricKey(data: derivedSecretKey), salt: "UKEY2 v1 next".data(using: .utf8)!, info: ukeyInfo, outputByteCount: 32)
pinCode=NearbyConnection.pinCodeFromAuthKey(authString)
@@ -350,17 +375,17 @@ class NearbyConnection{
0xEE, 0x8D, 0x39, 0x09, 0xB9, 0x5F, 0x13, 0xFA, 0x7D, 0xEB, 0x1D,
0x4A, 0xB3, 0x83, 0x76, 0xB8, 0x25, 0x6D, 0xA8, 0x55, 0x10])
let d2dClientKey=HKDF<SHA256>.deriveKey(inputKeyMaterial: nextSecret, salt: salt, info: "client".data(using: .utf8)!, outputByteCount: 32)
let d2dServerKey=HKDF<SHA256>.deriveKey(inputKeyMaterial: nextSecret, salt: salt, info: "server".data(using: .utf8)!, outputByteCount: 32)
let d2dClientKey=NearbyConnection.hkdf(inputKeyMaterial: nextSecret, salt: salt, info: "client".data(using: .utf8)!, outputByteCount: 32)
let d2dServerKey=NearbyConnection.hkdf(inputKeyMaterial: nextSecret, salt: salt, info: "server".data(using: .utf8)!, outputByteCount: 32)
sha=SHA256()
sha.update(data: "SecureMessage".data(using: .utf8)!)
let smsgSalt=Data(sha.finalize())
let clientKey=HKDF<SHA256>.deriveKey(inputKeyMaterial: d2dClientKey, salt: smsgSalt, info: "ENC:2".data(using: .utf8)!, outputByteCount: 32).withUnsafeBytes({return [UInt8]($0)})
let clientHmacKey=HKDF<SHA256>.deriveKey(inputKeyMaterial: d2dClientKey, salt: smsgSalt, info: "SIG:1".data(using: .utf8)!, outputByteCount: 32)
let serverKey=HKDF<SHA256>.deriveKey(inputKeyMaterial: d2dServerKey, salt: smsgSalt, info: "ENC:2".data(using: .utf8)!, outputByteCount: 32).withUnsafeBytes({return [UInt8]($0)})
let serverHmacKey=HKDF<SHA256>.deriveKey(inputKeyMaterial: d2dServerKey, salt: smsgSalt, info: "SIG:1".data(using: .utf8)!, outputByteCount: 32)
let clientKey=NearbyConnection.hkdf(inputKeyMaterial: d2dClientKey, salt: smsgSalt, info: "ENC:2".data(using: .utf8)!, outputByteCount: 32).withUnsafeBytes({return [UInt8]($0)})
let clientHmacKey=NearbyConnection.hkdf(inputKeyMaterial: d2dClientKey, salt: smsgSalt, info: "SIG:1".data(using: .utf8)!, outputByteCount: 32)
let serverKey=NearbyConnection.hkdf(inputKeyMaterial: d2dServerKey, salt: smsgSalt, info: "ENC:2".data(using: .utf8)!, outputByteCount: 32).withUnsafeBytes({return [UInt8]($0)})
let serverHmacKey=NearbyConnection.hkdf(inputKeyMaterial: d2dServerKey, salt: smsgSalt, info: "SIG:1".data(using: .utf8)!, outputByteCount: 32)
if isServer(){
decryptKey=clientKey

View File

@@ -53,7 +53,7 @@ public enum NearbyError:Error{
case protocolError(_ message:String)
case requiredFieldMissing(_ message:String)
case ukey2
case inputOutput(cause:Errno)
case inputOutput
case canceled(reason:CancellationReason)
public enum CancellationReason{

View File

@@ -277,10 +277,16 @@ class OutboundNearbyConnection:NearbyConnection{
let typeID=try? url.resourceValues(forKeys: [.typeIdentifierKey]).typeIdentifier
meta.mimeType="application/octet-stream"
if let typeID=typeID{
if #available(macOS 11.0, *){
let type=UTType(typeID)
if let type=type, let mimeType=type.preferredMIMEType{
meta.mimeType=mimeType
}
}else{
if let mimeType=UTTypeCopyPreferredTagWithClass(typeID as CFString, kUTTagClassMIMEType){
meta.mimeType=(mimeType.takeRetainedValue() as NSString) as String
}
}
}
if meta.mimeType.starts(with: "image/"){
meta.type = .image
@@ -358,8 +364,14 @@ class OutboundNearbyConnection:NearbyConnection{
currentTransfer=queue.removeFirst()
}
guard let fileBuffer=try currentTransfer!.handle!.read(upToCount: 512*1024) else{
throw NearbyError.inputOutput(cause: Errno.ioError)
let fileBuffer:Data
if #available(macOS 10.15.4, *) {
guard let _fileBuffer=try currentTransfer!.handle!.read(upToCount: 512*1024) else{
throw NearbyError.inputOutput
}
fileBuffer=_fileBuffer
} else {
fileBuffer=currentTransfer!.handle!.readData(ofLength: 512*1024)
}
var transfer=Location_Nearby_Connections_PayloadTransferFrame()

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21701" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22505" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21701"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22505"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@@ -32,9 +32,6 @@
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="NVE-vN-dkz">
<rect key="frame" x="325" y="3" width="76" height="32"/>
<constraints>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="60" id="cP1-hK-9ZX"/>
</constraints>
<buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="6Up-t3-mwm">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
@@ -42,6 +39,9 @@
Gw
</string>
</buttonCell>
<constraints>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="60" id="cP1-hK-9ZX"/>
</constraints>
<connections>
<action selector="cancel:" target="-2" id="Qav-AK-DGt"/>
</connections>
@@ -57,7 +57,7 @@ Gw
</constraints>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="NearDropIcon" id="q3u-Am-ZIA"/>
</imageView>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="aNc-0i-CWK">
<textField focusRingType="none" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="aNc-0i-CWK">
<rect key="frame" x="19" y="0.0" width="67" height="16"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="NearDrop" allowsEditingTextAttributes="YES" id="0xp-rC-2gr">
<font key="font" metaFont="systemBold"/>
@@ -83,7 +83,7 @@ Gw
</constraints>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="jOq-9r-V1W"/>
</imageView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="OEz-QK-nem">
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="OEz-QK-nem">
<rect key="frame" x="29" y="196" width="367" height="16"/>
<textFieldCell key="cell" lineBreakMode="truncatingMiddle" truncatesLastVisibleLine="YES" id="opy-Bj-x6u">
<font key="font" metaFont="system"/>
@@ -116,10 +116,10 @@ Gw
<rect key="frame" x="0.0" y="0.0" width="521" height="100"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<progressIndicator maxValue="100" indeterminate="YES" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="fCj-wF-rEj">
<progressIndicator wantsLayer="YES" maxValue="100" indeterminate="YES" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="fCj-wF-rEj">
<rect key="frame" x="245" y="68" width="32" height="32"/>
</progressIndicator>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="27P-yf-gUd">
<textField wantsLayer="YES" focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="27P-yf-gUd">
<rect key="frame" x="189" y="42" width="144" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Looking for devices..." id="NaJ-Wx-Pim">
<font key="font" textStyle="headline" name=".SFNS-Bold"/>
@@ -127,7 +127,7 @@ Gw
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="V5W-Rm-YVM">
<textField wantsLayer="YES" focusRingType="none" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="V5W-Rm-YVM">
<rect key="frame" x="-2" y="0.0" width="525" height="32"/>
<textFieldCell key="cell" alignment="center" title="If you don't see your device, open &quot;Google Files&quot; app and tap &quot;Receive&quot; on the Nearby Share tab." id="vla-gF-eJo">
<font key="font" metaFont="system"/>
@@ -185,7 +185,7 @@ Gw
<constraint firstAttribute="bottom" secondItem="84U-lB-SRB" secondAttribute="bottom" id="uh8-T1-Vd8"/>
</constraints>
</customView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dJc-gw-4ux">
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dJc-gw-4ux">
<rect key="frame" x="-2" y="56" width="388" height="16"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" alignment="center" id="QzI-qQ-OBb">
<font key="font" metaFont="system"/>
@@ -199,7 +199,7 @@ Gw
<constraint firstAttribute="width" constant="200" id="bM2-Ih-2UC"/>
</constraints>
</progressIndicator>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="y8I-D3-scQ">
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="y8I-D3-scQ">
<rect key="frame" x="165" y="0.0" width="54" height="16"/>
<textFieldCell key="cell" lineBreakMode="clipping" id="Iin-UY-IE5">
<font key="font" metaFont="system"/>

View File

@@ -44,7 +44,8 @@ class ShareViewController: NSViewController, ShareExtensionDelegate{
for attachment in attachments as NSArray{
let provider=attachment as! NSItemProvider
provider.loadItem(forTypeIdentifier: kUTTypeURL as String) { data, err in
if let url=URL(dataRepresentation: data as! Data, relativeTo: nil, isAbsolute: false){
if let urlData=data as? Data{
if let url=URL(dataRepresentation: urlData, relativeTo: nil, isAbsolute: false){
self.urls.append(url)
if self.urls.count==attachments.count{
DispatchQueue.main.async {
@@ -52,6 +53,14 @@ class ShareViewController: NSViewController, ShareExtensionDelegate{
}
}
}
}else if let url=data as? NSURL{
self.urls.append(url as URL)
if self.urls.count==attachments.count{
DispatchQueue.main.async {
self.urlsReady()
}
}
}
}
}
} else {