mirror of
https://github.com/grishka/NearDrop.git
synced 2025-12-16 03:37:45 +01:00
@@ -15,6 +15,9 @@
|
|||||||
691F53C72AC2594E0089FD92 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 691F53C52AC2594E0089FD92 /* Localizable.strings */; };
|
691F53C72AC2594E0089FD92 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 691F53C52AC2594E0089FD92 /* Localizable.strings */; };
|
||||||
691F53CB2AC2599B0089FD92 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 691F53C92AC2599B0089FD92 /* Localizable.stringsdict */; };
|
691F53CB2AC2599B0089FD92 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 691F53C92AC2599B0089FD92 /* Localizable.stringsdict */; };
|
||||||
693D8DC92E41325300E8E7F4 /* sharing_enums.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693D8DC82E41325300E8E7F4 /* sharing_enums.pb.swift */; };
|
693D8DC92E41325300E8E7F4 /* sharing_enums.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693D8DC82E41325300E8E7F4 /* sharing_enums.pb.swift */; };
|
||||||
|
693D8DCC2E43771D00E8E7F4 /* QRCode in Frameworks */ = {isa = PBXBuildFile; productRef = 693D8DCB2E43771D00E8E7F4 /* QRCode */; };
|
||||||
|
697DDEEC2E43986400B4749C /* SymmetricKey+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 697DDEEB2E43986400B4749C /* SymmetricKey+Extensions.swift */; };
|
||||||
|
697DDF0F2E4422B300B4749C /* QrCodeBackgroundView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 697DDF0E2E4422B300B4749C /* QrCodeBackgroundView.swift */; };
|
||||||
698DFB0329E362140064F247 /* NDNotificationCenterHackery.m in Sources */ = {isa = PBXBuildFile; fileRef = 698DFB0229E362140064F247 /* NDNotificationCenterHackery.m */; };
|
698DFB0329E362140064F247 /* NDNotificationCenterHackery.m in Sources */ = {isa = PBXBuildFile; fileRef = 698DFB0229E362140064F247 /* NDNotificationCenterHackery.m */; };
|
||||||
699B03452AB5FBA300E0D718 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 699B03442AB5FBA300E0D718 /* Assets.xcassets */; };
|
699B03452AB5FBA300E0D718 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 699B03442AB5FBA300E0D718 /* Assets.xcassets */; };
|
||||||
699DEBA62AB0573200115D22 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 699DEBA52AB0573200115D22 /* ShareViewController.swift */; };
|
699DEBA62AB0573200115D22 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 699DEBA52AB0573200115D22 /* ShareViewController.swift */; };
|
||||||
@@ -148,6 +151,8 @@
|
|||||||
693D8DC82E41325300E8E7F4 /* sharing_enums.pb.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = sharing_enums.pb.swift; sourceTree = "<group>"; };
|
693D8DC82E41325300E8E7F4 /* sharing_enums.pb.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = sharing_enums.pb.swift; sourceTree = "<group>"; };
|
||||||
6978D5392BFE97E100A6100C /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = fr; path = fr.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
6978D5392BFE97E100A6100C /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = fr; path = fr.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||||
6978D53A2BFE97E900A6100C /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
|
6978D53A2BFE97E900A6100C /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
|
697DDEEB2E43986400B4749C /* SymmetricKey+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SymmetricKey+Extensions.swift"; sourceTree = "<group>"; };
|
||||||
|
697DDF0E2E4422B300B4749C /* QrCodeBackgroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QrCodeBackgroundView.swift; sourceTree = "<group>"; };
|
||||||
698DFAE529E2F91A0064F247 /* NearbyConnection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearbyConnection.swift; sourceTree = "<group>"; };
|
698DFAE529E2F91A0064F247 /* NearbyConnection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearbyConnection.swift; sourceTree = "<group>"; };
|
||||||
698DFAED29E353220064F247 /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; };
|
698DFAED29E353220064F247 /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; };
|
||||||
698DFAEF29E353220064F247 /* UserNotificationsUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotificationsUI.framework; path = System/Library/Frameworks/UserNotificationsUI.framework; sourceTree = SDKROOT; };
|
698DFAEF29E353220064F247 /* UserNotificationsUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotificationsUI.framework; path = System/Library/Frameworks/UserNotificationsUI.framework; sourceTree = SDKROOT; };
|
||||||
@@ -217,6 +222,7 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
693D8DCC2E43771D00E8E7F4 /* QRCode in Frameworks */,
|
||||||
69DCF49D2AB8C9A500CBE2CC /* libNearbyShare.dylib in Frameworks */,
|
69DCF49D2AB8C9A500CBE2CC /* libNearbyShare.dylib in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
@@ -254,6 +260,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
699DEBA52AB0573200115D22 /* ShareViewController.swift */,
|
699DEBA52AB0573200115D22 /* ShareViewController.swift */,
|
||||||
|
697DDF0E2E4422B300B4749C /* QrCodeBackgroundView.swift */,
|
||||||
691F53B92ABB70840089FD92 /* DeviceListCell.swift */,
|
691F53B92ABB70840089FD92 /* DeviceListCell.swift */,
|
||||||
691F53BA2ABB70840089FD92 /* DeviceListCell.xib */,
|
691F53BA2ABB70840089FD92 /* DeviceListCell.xib */,
|
||||||
699DEBA72AB0573200115D22 /* ShareViewController.xib */,
|
699DEBA72AB0573200115D22 /* ShareViewController.xib */,
|
||||||
@@ -328,6 +335,7 @@
|
|||||||
691F53BD2ABF03820089FD92 /* OutboundNearbyConnection.swift */,
|
691F53BD2ABF03820089FD92 /* OutboundNearbyConnection.swift */,
|
||||||
698DFAE529E2F91A0064F247 /* NearbyConnection.swift */,
|
698DFAE529E2F91A0064F247 /* NearbyConnection.swift */,
|
||||||
69DA9A2029E0CC4E00A442DA /* Data+Extensions.swift */,
|
69DA9A2029E0CC4E00A442DA /* Data+Extensions.swift */,
|
||||||
|
697DDEEB2E43986400B4749C /* SymmetricKey+Extensions.swift */,
|
||||||
);
|
);
|
||||||
path = NearbyShare;
|
path = NearbyShare;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -459,6 +467,7 @@
|
|||||||
packageReferences = (
|
packageReferences = (
|
||||||
69DA9A2429E189EF00A442DA /* XCRemoteSwiftPackageReference "swift-protobuf" */,
|
69DA9A2429E189EF00A442DA /* XCRemoteSwiftPackageReference "swift-protobuf" */,
|
||||||
69DA9A3429E1994C00A442DA /* XCRemoteSwiftPackageReference "SwiftECC" */,
|
69DA9A3429E1994C00A442DA /* XCRemoteSwiftPackageReference "SwiftECC" */,
|
||||||
|
693D8DCA2E43771D00E8E7F4 /* XCRemoteSwiftPackageReference "qrcode" */,
|
||||||
);
|
);
|
||||||
productRefGroup = 69DA9A0F29E0BF5100A442DA /* Products */;
|
productRefGroup = 69DA9A0F29E0BF5100A442DA /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
@@ -505,6 +514,7 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
699DEBA62AB0573200115D22 /* ShareViewController.swift in Sources */,
|
699DEBA62AB0573200115D22 /* ShareViewController.swift in Sources */,
|
||||||
|
697DDF0F2E4422B300B4749C /* QrCodeBackgroundView.swift in Sources */,
|
||||||
691F53BB2ABB70840089FD92 /* DeviceListCell.swift in Sources */,
|
691F53BB2ABB70840089FD92 /* DeviceListCell.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
@@ -533,6 +543,7 @@
|
|||||||
69DCF4902AB70E9700CBE2CC /* InboundNearbyConnection.swift in Sources */,
|
69DCF4902AB70E9700CBE2CC /* InboundNearbyConnection.swift in Sources */,
|
||||||
69DCF48B2AB70E8C00CBE2CC /* ukey.pb.swift in Sources */,
|
69DCF48B2AB70E8C00CBE2CC /* ukey.pb.swift in Sources */,
|
||||||
69DCF48A2AB70E8C00CBE2CC /* wire_format.pb.swift in Sources */,
|
69DCF48A2AB70E8C00CBE2CC /* wire_format.pb.swift in Sources */,
|
||||||
|
697DDEEC2E43986400B4749C /* SymmetricKey+Extensions.swift in Sources */,
|
||||||
69DCF4932AB70E9700CBE2CC /* Data+Extensions.swift in Sources */,
|
69DCF4932AB70E9700CBE2CC /* Data+Extensions.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
@@ -683,7 +694,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 6;
|
CURRENT_PROJECT_VERSION = 7;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = ShareExtension/Info.plist;
|
INFOPLIST_FILE = ShareExtension/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = NearDrop;
|
INFOPLIST_KEY_CFBundleDisplayName = NearDrop;
|
||||||
@@ -694,7 +705,7 @@
|
|||||||
"@executable_path/../../../../Frameworks",
|
"@executable_path/../../../../Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||||
MARKETING_VERSION = 2.0.2;
|
MARKETING_VERSION = 2.2.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = me.grishka.NearDrop.ShareExtension;
|
PRODUCT_BUNDLE_IDENTIFIER = me.grishka.NearDrop.ShareExtension;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
@@ -709,7 +720,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 6;
|
CURRENT_PROJECT_VERSION = 7;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = ShareExtension/Info.plist;
|
INFOPLIST_FILE = ShareExtension/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = NearDrop;
|
INFOPLIST_KEY_CFBundleDisplayName = NearDrop;
|
||||||
@@ -720,7 +731,7 @@
|
|||||||
"@executable_path/../../../../Frameworks",
|
"@executable_path/../../../../Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||||
MARKETING_VERSION = 2.0.2;
|
MARKETING_VERSION = 2.2.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = me.grishka.NearDrop.ShareExtension;
|
PRODUCT_BUNDLE_IDENTIFIER = me.grishka.NearDrop.ShareExtension;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
@@ -852,9 +863,12 @@
|
|||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = NearDrop/NearDrop.entitlements;
|
CODE_SIGN_ENTITLEMENTS = NearDrop/NearDrop.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 9;
|
CURRENT_PROJECT_VERSION = 10;
|
||||||
|
DEVELOPMENT_TEAM = "";
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||||
INFOPLIST_KEY_LSUIElement = YES;
|
INFOPLIST_KEY_LSUIElement = YES;
|
||||||
@@ -866,9 +880,10 @@
|
|||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||||
MARKETING_VERSION = 2.1.0;
|
MARKETING_VERSION = 2.2.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = me.grishka.NearDrop;
|
PRODUCT_BUNDLE_IDENTIFIER = me.grishka.NearDrop;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "NearDrop/NearDrop-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "NearDrop/NearDrop-Bridging-Header.h";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
@@ -884,9 +899,12 @@
|
|||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = NearDrop/NearDrop.entitlements;
|
CODE_SIGN_ENTITLEMENTS = NearDrop/NearDrop.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 9;
|
CURRENT_PROJECT_VERSION = 10;
|
||||||
|
DEVELOPMENT_TEAM = "";
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||||
INFOPLIST_KEY_LSUIElement = YES;
|
INFOPLIST_KEY_LSUIElement = YES;
|
||||||
@@ -898,9 +916,10 @@
|
|||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||||
MARKETING_VERSION = 2.1.0;
|
MARKETING_VERSION = 2.2.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = me.grishka.NearDrop;
|
PRODUCT_BUNDLE_IDENTIFIER = me.grishka.NearDrop;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "NearDrop/NearDrop-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "NearDrop/NearDrop-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
@@ -981,6 +1000,14 @@
|
|||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
|
|
||||||
/* Begin XCRemoteSwiftPackageReference section */
|
/* Begin XCRemoteSwiftPackageReference section */
|
||||||
|
693D8DCA2E43771D00E8E7F4 /* XCRemoteSwiftPackageReference "qrcode" */ = {
|
||||||
|
isa = XCRemoteSwiftPackageReference;
|
||||||
|
repositoryURL = "https://github.com/dagronf/qrcode.git";
|
||||||
|
requirement = {
|
||||||
|
kind = upToNextMajorVersion;
|
||||||
|
minimumVersion = 26.10.0;
|
||||||
|
};
|
||||||
|
};
|
||||||
69DA9A2429E189EF00A442DA /* XCRemoteSwiftPackageReference "swift-protobuf" */ = {
|
69DA9A2429E189EF00A442DA /* XCRemoteSwiftPackageReference "swift-protobuf" */ = {
|
||||||
isa = XCRemoteSwiftPackageReference;
|
isa = XCRemoteSwiftPackageReference;
|
||||||
repositoryURL = "https://github.com/apple/swift-protobuf.git";
|
repositoryURL = "https://github.com/apple/swift-protobuf.git";
|
||||||
@@ -1000,6 +1027,11 @@
|
|||||||
/* End XCRemoteSwiftPackageReference section */
|
/* End XCRemoteSwiftPackageReference section */
|
||||||
|
|
||||||
/* Begin XCSwiftPackageProductDependency section */
|
/* Begin XCSwiftPackageProductDependency section */
|
||||||
|
693D8DCB2E43771D00E8E7F4 /* QRCode */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = 693D8DCA2E43771D00E8E7F4 /* XCRemoteSwiftPackageReference "qrcode" */;
|
||||||
|
productName = QRCode;
|
||||||
|
};
|
||||||
69DCF4992AB8C58500CBE2CC /* SwiftProtobuf */ = {
|
69DCF4992AB8C58500CBE2CC /* SwiftProtobuf */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = 69DA9A2429E189EF00A442DA /* XCRemoteSwiftPackageReference "swift-protobuf" */;
|
package = 69DA9A2429E189EF00A442DA /* XCRemoteSwiftPackageReference "swift-protobuf" */;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"originHash" : "f2a7ac82cfff4c1d8403f173eab86d0110b35f7ef9b3ae22165a6e3b814b176b",
|
||||||
"pins" : [
|
"pins" : [
|
||||||
{
|
{
|
||||||
"identity" : "asn1",
|
"identity" : "asn1",
|
||||||
@@ -18,6 +19,15 @@
|
|||||||
"version" : "1.9.0"
|
"version" : "1.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"identity" : "qrcode",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/dagronf/qrcode.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "177d4091f7fcce1efc22de2a5fcdb671bd103101",
|
||||||
|
"version" : "26.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"identity" : "swift-protobuf",
|
"identity" : "swift-protobuf",
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
@@ -27,6 +37,15 @@
|
|||||||
"version" : "1.21.0"
|
"version" : "1.21.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"identity" : "swift-qrcode-generator",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/dagronf/swift-qrcode-generator",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "2b1980b825f08a81ccc762b0c4d17fcde9d5e953",
|
||||||
|
"version" : "2.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"identity" : "swiftecc",
|
"identity" : "swiftecc",
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
@@ -35,7 +54,16 @@
|
|||||||
"revision" : "55493f0609f07b24bf6cd52b90898ed1cefb268e",
|
"revision" : "55493f0609f07b24bf6cd52b90898ed1cefb268e",
|
||||||
"version" : "3.5.3"
|
"version" : "3.5.3"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "swiftimagereadwrite",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/dagronf/SwiftImageReadWrite",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "42ace2412279f18bc264bc306e96b51c36e12a33",
|
||||||
|
"version" : "1.9.2"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"version" : 2
|
"version" : 3
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,13 @@ extension Data{
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func suffixOfAtMost(numBytes:Int) -> Data{
|
||||||
|
if count<=numBytes{
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
return subdata(in: count-numBytes..<count)
|
||||||
|
}
|
||||||
|
|
||||||
static func randomData(length: Int) -> Data{
|
static func randomData(length: Int) -> Data{
|
||||||
var data=Data(count: length)
|
var data=Data(count: length)
|
||||||
data.withUnsafeMutableBytes {
|
data.withUnsafeMutableBytes {
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ class NearbyConnection{
|
|||||||
private var clientSeq:Int32=0
|
private var clientSeq:Int32=0
|
||||||
|
|
||||||
private(set) var pinCode:String?
|
private(set) var pinCode:String?
|
||||||
|
private(set) var authKey:SymmetricKey?
|
||||||
|
|
||||||
init(connection:NWConnection, id:String) {
|
init(connection:NWConnection, id:String) {
|
||||||
self.connection=connection
|
self.connection=connection
|
||||||
@@ -340,7 +341,7 @@ class NearbyConnection{
|
|||||||
if #available(macOS 11.0, *){
|
if #available(macOS 11.0, *){
|
||||||
return HKDF<SHA256>.deriveKey(inputKeyMaterial: inputKeyMaterial, salt: salt, info: info, outputByteCount: outputByteCount)
|
return HKDF<SHA256>.deriveKey(inputKeyMaterial: inputKeyMaterial, salt: salt, info: info, outputByteCount: outputByteCount)
|
||||||
}else{
|
}else{
|
||||||
return SymmetricKey(data: hkdfExpand(prk: hkdfExtract(salt: salt, ikm: inputKeyMaterial.withUnsafeBytes({return Data(bytes: $0.baseAddress!, count: $0.count)})), info: info, length: outputByteCount))
|
return SymmetricKey(data: hkdfExpand(prk: hkdfExtract(salt: salt, ikm: inputKeyMaterial.data()), info: info, length: outputByteCount))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,6 +370,7 @@ class NearbyConnection{
|
|||||||
let authString=NearbyConnection.hkdf(inputKeyMaterial: SymmetricKey(data: derivedSecretKey), salt: "UKEY2 v1 auth".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)
|
let nextSecret=NearbyConnection.hkdf(inputKeyMaterial: SymmetricKey(data: derivedSecretKey), salt: "UKEY2 v1 next".data(using: .utf8)!, info: ukeyInfo, outputByteCount: 32)
|
||||||
|
|
||||||
|
authKey=authString
|
||||||
pinCode=NearbyConnection.pinCodeFromAuthKey(authString)
|
pinCode=NearbyConnection.pinCodeFromAuthKey(authString)
|
||||||
|
|
||||||
let salt:Data=Data([0x82, 0xAA, 0x55, 0xA0, 0xD3, 0x97, 0xF8, 0x83, 0x46, 0xCA, 0x1C,
|
let salt:Data=Data([0x82, 0xAA, 0x55, 0xA0, 0xD3, 0x97, 0xF8, 0x83, 0x46, 0xCA, 0x1C,
|
||||||
|
|||||||
@@ -8,21 +8,27 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import Network
|
import Network
|
||||||
import System
|
import System
|
||||||
|
import CryptoKit
|
||||||
|
import SwiftECC
|
||||||
|
|
||||||
public struct RemoteDeviceInfo{
|
public struct RemoteDeviceInfo{
|
||||||
public let name:String
|
public let name:String
|
||||||
public let type:DeviceType
|
public let type:DeviceType
|
||||||
|
public let qrCodeData:Data?
|
||||||
public var id:String?
|
public var id:String?
|
||||||
|
|
||||||
init(name: String, type: DeviceType, id: String? = nil) {
|
init(name: String, type: DeviceType, id: String? = nil) {
|
||||||
self.name = name
|
self.name = name
|
||||||
self.type = type
|
self.type = type
|
||||||
self.id = id
|
self.id = id
|
||||||
|
self.qrCodeData = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
init(info:EndpointInfo){
|
init(info:EndpointInfo, id: String? = nil){
|
||||||
self.name=info.name
|
self.name=info.name!
|
||||||
self.type=info.deviceType
|
self.type=info.deviceType
|
||||||
|
self.qrCodeData=info.qrCodeData
|
||||||
|
self.id=id
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum DeviceType:Int32{
|
public enum DeviceType:Int32{
|
||||||
@@ -94,22 +100,50 @@ struct OutgoingTransferInfo{
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct EndpointInfo{
|
struct EndpointInfo{
|
||||||
let name:String
|
var name:String?
|
||||||
let deviceType:RemoteDeviceInfo.DeviceType
|
let deviceType:RemoteDeviceInfo.DeviceType
|
||||||
|
let qrCodeData:Data?
|
||||||
|
|
||||||
init(name: String, deviceType: RemoteDeviceInfo.DeviceType){
|
init(name: String, deviceType: RemoteDeviceInfo.DeviceType){
|
||||||
self.name = name
|
self.name = name
|
||||||
self.deviceType = deviceType
|
self.deviceType = deviceType
|
||||||
|
self.qrCodeData=nil
|
||||||
}
|
}
|
||||||
|
|
||||||
init?(data:Data){
|
init?(data:Data){
|
||||||
guard data.count>17 else {return nil}
|
guard data.count>17 else {return nil}
|
||||||
let deviceNameLength=Int(data[17])
|
let hasName=(data[0] & 0x10)==0
|
||||||
guard data.count>=deviceNameLength+18 else {return nil}
|
let deviceNameLength:Int
|
||||||
guard let deviceName=String(data: data[18..<(18+deviceNameLength)], encoding: .utf8) else {return nil}
|
let deviceName:String?
|
||||||
|
if hasName{
|
||||||
|
deviceNameLength=Int(data[17])
|
||||||
|
guard data.count>=deviceNameLength+18 else {return nil}
|
||||||
|
guard let _deviceName=String(data: data[18..<(18+deviceNameLength)], encoding: .utf8) else {return nil}
|
||||||
|
deviceName=_deviceName
|
||||||
|
}else{
|
||||||
|
deviceNameLength=0
|
||||||
|
deviceName=nil
|
||||||
|
}
|
||||||
let rawDeviceType:Int=Int(data[0] & 7) >> 1
|
let rawDeviceType:Int=Int(data[0] & 7) >> 1
|
||||||
self.name=deviceName
|
self.name=deviceName
|
||||||
self.deviceType=RemoteDeviceInfo.DeviceType.fromRawValue(value: rawDeviceType)
|
self.deviceType=RemoteDeviceInfo.DeviceType.fromRawValue(value: rawDeviceType)
|
||||||
|
var offset=1+16
|
||||||
|
if hasName{
|
||||||
|
offset=offset+1+deviceNameLength
|
||||||
|
}
|
||||||
|
var qrCodeData:Data?=nil
|
||||||
|
while data.count-offset>2{ // read TLV records, if any
|
||||||
|
let type=data[offset]
|
||||||
|
let length=Int(data[offset+1])
|
||||||
|
offset=offset+2
|
||||||
|
if data.count-offset>=length{
|
||||||
|
if type==1{ // QR code data
|
||||||
|
qrCodeData=data.subdata(in: offset..<offset+length)
|
||||||
|
}
|
||||||
|
offset=offset+length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.qrCodeData=qrCodeData
|
||||||
}
|
}
|
||||||
|
|
||||||
func serialize()->Data{
|
func serialize()->Data{
|
||||||
@@ -121,7 +155,7 @@ struct EndpointInfo{
|
|||||||
endpointInfo.append(UInt8.random(in: 0...255))
|
endpointInfo.append(UInt8.random(in: 0...255))
|
||||||
}
|
}
|
||||||
// Device name in UTF-8 prefixed with 1-byte length
|
// Device name in UTF-8 prefixed with 1-byte length
|
||||||
var nameChars=[UInt8](name.utf8)
|
var nameChars=[UInt8](name!.utf8)
|
||||||
if nameChars.count>255{
|
if nameChars.count>255{
|
||||||
nameChars=[UInt8](nameChars[0..<255])
|
nameChars=[UInt8](nameChars[0..<255])
|
||||||
}
|
}
|
||||||
@@ -141,6 +175,7 @@ public protocol MainAppDelegate{
|
|||||||
public protocol ShareExtensionDelegate:AnyObject{
|
public protocol ShareExtensionDelegate:AnyObject{
|
||||||
func addDevice(device:RemoteDeviceInfo)
|
func addDevice(device:RemoteDeviceInfo)
|
||||||
func removeDevice(id:String)
|
func removeDevice(id:String)
|
||||||
|
func startTransferWithQrCode(device:RemoteDeviceInfo)
|
||||||
func connectionWasEstablished(pinCode:String)
|
func connectionWasEstablished(pinCode:String)
|
||||||
func connectionFailed(with error:Error)
|
func connectionFailed(with error:Error)
|
||||||
func transferAccepted()
|
func transferAccepted()
|
||||||
@@ -162,6 +197,12 @@ public class NearbyConnectionManager : NSObject, NetServiceDelegate, InboundNear
|
|||||||
|
|
||||||
private var browser:NWBrowser?
|
private var browser:NWBrowser?
|
||||||
|
|
||||||
|
private var qrCodePublicKey:ECPublicKey?
|
||||||
|
private var qrCodePrivateKey:ECPrivateKey?
|
||||||
|
private var qrCodeAdvertisingToken:Data?
|
||||||
|
private var qrCodeNameEncryptionKey:SymmetricKey?
|
||||||
|
private var qrCodeData:Data?
|
||||||
|
|
||||||
public static let shared=NearbyConnectionManager()
|
public static let shared=NearbyConnectionManager()
|
||||||
|
|
||||||
override init() {
|
override init() {
|
||||||
@@ -314,19 +355,51 @@ public class NearbyConnectionManager : NSObject, NetServiceDelegate, InboundNear
|
|||||||
|
|
||||||
guard case let NWBrowser.Result.Metadata.bonjour(txtRecord)=service.metadata else {return}
|
guard case let NWBrowser.Result.Metadata.bonjour(txtRecord)=service.metadata else {return}
|
||||||
guard let endpointInfoEncoded=txtRecord.dictionary["n"] else {return}
|
guard let endpointInfoEncoded=txtRecord.dictionary["n"] else {return}
|
||||||
guard let endpointInfo=Data.dataFromUrlSafeBase64(endpointInfoEncoded) else {return}
|
guard let endpointInfoSerialized=Data.dataFromUrlSafeBase64(endpointInfoEncoded) else {return}
|
||||||
guard endpointInfo.count>=19 else {return}
|
guard var endpointInfo=EndpointInfo(data: endpointInfoSerialized) else {return}
|
||||||
let deviceType=RemoteDeviceInfo.DeviceType.fromRawValue(value: (Int(endpointInfo[0]) >> 1) & 7)
|
|
||||||
let deviceNameLength=Int(endpointInfo[17])
|
|
||||||
guard endpointInfo.count>=deviceNameLength+17 else {return}
|
|
||||||
guard let deviceName=String(data: endpointInfo.subdata(in: 18..<(18+deviceNameLength)), encoding: .utf8) else {return}
|
|
||||||
|
|
||||||
let deviceInfo=RemoteDeviceInfo(name: deviceName, type: deviceType, id: endpointID)
|
var deviceInfo:RemoteDeviceInfo?
|
||||||
|
if let _=endpointInfo.name{
|
||||||
|
deviceInfo=addFoundDevice(foundService: &foundService, endpointInfo: endpointInfo, endpointID: endpointID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let qrData=endpointInfo.qrCodeData, let _=qrCodeAdvertisingToken{
|
||||||
|
#if DEBUG
|
||||||
|
print("Device has QR data: \(qrData.base64EncodedString()), our advertising token is \(qrCodeAdvertisingToken!.base64EncodedString())")
|
||||||
|
#endif
|
||||||
|
if qrData==qrCodeAdvertisingToken!{
|
||||||
|
if let deviceInfo=deviceInfo{
|
||||||
|
for delegate in shareExtensionDelegates{
|
||||||
|
delegate.startTransferWithQrCode(device: deviceInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else if qrData.count>28{
|
||||||
|
do{
|
||||||
|
let box=try AES.GCM.SealedBox(combined: qrData)
|
||||||
|
let decryptedName=try AES.GCM.open(box, using: qrCodeNameEncryptionKey!, authenticating: qrCodeAdvertisingToken!)
|
||||||
|
guard let name=String.init(data: decryptedName, encoding: .utf8) else {return}
|
||||||
|
endpointInfo.name=name
|
||||||
|
let deviceInfo=addFoundDevice(foundService: &foundService, endpointInfo: endpointInfo, endpointID: endpointID)
|
||||||
|
for delegate in shareExtensionDelegates{
|
||||||
|
delegate.startTransferWithQrCode(device: deviceInfo)
|
||||||
|
}
|
||||||
|
}catch{
|
||||||
|
#if DEBUG
|
||||||
|
print("Error decrypting QR code data of an invisible device: \(error)")
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func addFoundDevice(foundService:inout FoundServiceInfo, endpointInfo:EndpointInfo, endpointID:String) -> RemoteDeviceInfo{
|
||||||
|
let deviceInfo=RemoteDeviceInfo(info: endpointInfo, id: endpointID)
|
||||||
foundService.device=deviceInfo
|
foundService.device=deviceInfo
|
||||||
foundServices[endpointID]=foundService
|
foundServices[endpointID]=foundService
|
||||||
for delegate in shareExtensionDelegates{
|
for delegate in shareExtensionDelegates{
|
||||||
delegate.addDevice(device: deviceInfo)
|
delegate.addDevice(device: deviceInfo)
|
||||||
}
|
}
|
||||||
|
return deviceInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
private func maybeRemoveFoundDevice(service:NWBrowser.Result){
|
private func maybeRemoveFoundDevice(service:NWBrowser.Result){
|
||||||
@@ -337,6 +410,33 @@ public class NearbyConnectionManager : NSObject, NetServiceDelegate, InboundNear
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func generateQrCodeKey() -> String{
|
||||||
|
let domain=Domain.instance(curve: .EC256r1)
|
||||||
|
let (pubKey, privKey)=domain.makeKeyPair()
|
||||||
|
qrCodePublicKey=pubKey
|
||||||
|
qrCodePrivateKey=privKey
|
||||||
|
var keyData=Data()
|
||||||
|
keyData.append(contentsOf: [0, 0, 2])
|
||||||
|
let keyBytes=Data(pubKey.w.x.asSignedBytes())
|
||||||
|
// Sometimes, for some keys, there will be a leading zero byte. Strip that, Android really hates it (it breaks the endpoint info)
|
||||||
|
keyData.append(keyBytes.suffixOfAtMost(numBytes: 32))
|
||||||
|
|
||||||
|
let ikm=SymmetricKey(data: keyData)
|
||||||
|
qrCodeAdvertisingToken=NearbyConnection.hkdf(inputKeyMaterial: ikm, salt: Data(), info: "advertisingContext".data(using: .utf8)!, outputByteCount: 16).data()
|
||||||
|
qrCodeNameEncryptionKey=NearbyConnection.hkdf(inputKeyMaterial: ikm, salt: Data(), info: "encryptionKey".data(using: .utf8)!, outputByteCount: 16)
|
||||||
|
qrCodeData=keyData
|
||||||
|
|
||||||
|
return keyData.urlSafeBase64EncodedString()
|
||||||
|
}
|
||||||
|
|
||||||
|
public func clearQrCodeKey(){
|
||||||
|
qrCodePublicKey=nil
|
||||||
|
qrCodePrivateKey=nil
|
||||||
|
qrCodeAdvertisingToken=nil
|
||||||
|
qrCodeNameEncryptionKey=nil
|
||||||
|
qrCodeData=nil
|
||||||
|
}
|
||||||
|
|
||||||
public func startOutgoingTransfer(deviceID:String, delegate:ShareExtensionDelegate, urls:[URL]){
|
public func startOutgoingTransfer(deviceID:String, delegate:ShareExtensionDelegate, urls:[URL]){
|
||||||
guard let info=foundServices[deviceID] else {return}
|
guard let info=foundServices[deviceID] else {return}
|
||||||
let tcp=NWProtocolTCP.Options.init()
|
let tcp=NWProtocolTCP.Options.init()
|
||||||
@@ -344,6 +444,7 @@ public class NearbyConnectionManager : NSObject, NetServiceDelegate, InboundNear
|
|||||||
let nwconn=NWConnection(to: info.service.endpoint, using: NWParameters(tls: .none, tcp: tcp))
|
let nwconn=NWConnection(to: info.service.endpoint, using: NWParameters(tls: .none, tcp: tcp))
|
||||||
let conn=OutboundNearbyConnection(connection: nwconn, id: deviceID, urlsToSend: urls)
|
let conn=OutboundNearbyConnection(connection: nwconn, id: deviceID, urlsToSend: urls)
|
||||||
conn.delegate=self
|
conn.delegate=self
|
||||||
|
conn.qrCodePrivateKey=qrCodePrivateKey
|
||||||
let transfer=OutgoingTransferInfo(service: info.service, device: info.device!, connection: conn, delegate: delegate)
|
let transfer=OutgoingTransferInfo(service: info.service, device: info.device!, connection: conn, delegate: delegate)
|
||||||
outgoingTransfers[deviceID]=transfer
|
outgoingTransfers[deviceID]=transfer
|
||||||
conn.start()
|
conn.start()
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ class OutboundNearbyConnection:NearbyConnection{
|
|||||||
private var cancelled:Bool=false
|
private var cancelled:Bool=false
|
||||||
private var textPayloadID:Int64=0
|
private var textPayloadID:Int64=0
|
||||||
|
|
||||||
|
public var qrCodePrivateKey:ECPrivateKey?
|
||||||
|
|
||||||
enum State{
|
enum State{
|
||||||
case initial, sentUkeyClientInit, sentUkeyClientFinish, sentPairedKeyEncryption, sentPairedKeyResult, sentIntroduction, sendingFiles
|
case initial, sentUkeyClientInit, sentUkeyClientFinish, sentPairedKeyEncryption, sentPairedKeyResult, sentIntroduction, sendingFiles
|
||||||
}
|
}
|
||||||
@@ -237,6 +239,12 @@ class OutboundNearbyConnection:NearbyConnection{
|
|||||||
pairedEncryption.v1.pairedKeyEncryption=Sharing_Nearby_PairedKeyEncryptionFrame()
|
pairedEncryption.v1.pairedKeyEncryption=Sharing_Nearby_PairedKeyEncryptionFrame()
|
||||||
pairedEncryption.v1.pairedKeyEncryption.secretIDHash=Data.randomData(length: 6)
|
pairedEncryption.v1.pairedKeyEncryption.secretIDHash=Data.randomData(length: 6)
|
||||||
pairedEncryption.v1.pairedKeyEncryption.signedData=Data.randomData(length: 72)
|
pairedEncryption.v1.pairedKeyEncryption.signedData=Data.randomData(length: 72)
|
||||||
|
if let qrKey=qrCodePrivateKey{
|
||||||
|
let signature=qrKey.sign(msg: authKey!.data())
|
||||||
|
var serializedSignature=Data(signature.r)
|
||||||
|
serializedSignature.append(Data(signature.s))
|
||||||
|
pairedEncryption.v1.pairedKeyEncryption.qrCodeHandshakeData=serializedSignature
|
||||||
|
}
|
||||||
try sendTransferSetupFrame(pairedEncryption)
|
try sendTransferSetupFrame(pairedEncryption)
|
||||||
|
|
||||||
currentState = .sentPairedKeyEncryption
|
currentState = .sentPairedKeyEncryption
|
||||||
|
|||||||
15
NearbyShare/SymmetricKey+Extensions.swift
Normal file
15
NearbyShare/SymmetricKey+Extensions.swift
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// SymmetricKey+Extensions.swift
|
||||||
|
// NearbyShare
|
||||||
|
//
|
||||||
|
// Created by Grishka on 06.08.2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import CryptoKit
|
||||||
|
|
||||||
|
extension SymmetricKey{
|
||||||
|
func data() -> Data{
|
||||||
|
return withUnsafeBytes({return Data(bytes: $0.baseAddress!, count: $0.count)})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22505" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="23504" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="macosx"/>
|
<deployment identifier="macosx"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22505"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="23504"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
@@ -22,6 +22,10 @@
|
|||||||
<outlet property="progressProgressBar" destination="J5x-hu-Kn5" id="vYH-DN-03b"/>
|
<outlet property="progressProgressBar" destination="J5x-hu-Kn5" id="vYH-DN-03b"/>
|
||||||
<outlet property="progressState" destination="y8I-D3-scQ" id="Tj3-xa-8VG"/>
|
<outlet property="progressState" destination="y8I-D3-scQ" id="Tj3-xa-8VG"/>
|
||||||
<outlet property="progressView" destination="Q9K-dc-THx" id="LlE-4d-mI5"/>
|
<outlet property="progressView" destination="Q9K-dc-THx" id="LlE-4d-mI5"/>
|
||||||
|
<outlet property="qrCodeButton" destination="ZsR-MN-QVA" id="KaY-NO-F5z"/>
|
||||||
|
<outlet property="qrCodeSheetView" destination="cIc-n7-hIV" id="Ol8-aW-fH0"/>
|
||||||
|
<outlet property="qrCodeView" destination="9Hk-Pa-eYI" id="Weo-3l-5pN"/>
|
||||||
|
<outlet property="qrCodeWrapView" destination="dq7-IV-6Ef" id="V35-5n-nyq"/>
|
||||||
<outlet property="view" destination="1" id="2"/>
|
<outlet property="view" destination="1" id="2"/>
|
||||||
</connections>
|
</connections>
|
||||||
</customObject>
|
</customObject>
|
||||||
@@ -94,12 +98,28 @@ Gw
|
|||||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="ACO-U2-AZj">
|
<customView translatesAutoresizingMaskIntoConstraints="NO" id="ACO-U2-AZj">
|
||||||
<rect key="frame" x="0.0" y="40" width="404" height="146"/>
|
<rect key="frame" x="0.0" y="40" width="404" height="146"/>
|
||||||
</customView>
|
</customView>
|
||||||
|
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ZsR-MN-QVA">
|
||||||
|
<rect key="frame" x="3" y="3" width="125" height="32"/>
|
||||||
|
<buttonCell key="cell" type="push" title="Use QR code..." bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Ll5-lP-3bU">
|
||||||
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
|
<font key="font" metaFont="system"/>
|
||||||
|
</buttonCell>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="100" id="7o5-tK-dlg"/>
|
||||||
|
</constraints>
|
||||||
|
<connections>
|
||||||
|
<action selector="useQrCode:" target="-2" id="BS0-WG-B7q"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
</subviews>
|
</subviews>
|
||||||
<constraints>
|
<constraints>
|
||||||
|
<constraint firstAttribute="bottom" secondItem="ZsR-MN-QVA" secondAttribute="bottom" constant="10" id="76Q-6H-r3I"/>
|
||||||
<constraint firstItem="OEz-QK-nem" firstAttribute="top" secondItem="1xF-vr-5sH" secondAttribute="bottom" constant="10" id="852-oh-vM0"/>
|
<constraint firstItem="OEz-QK-nem" firstAttribute="top" secondItem="1xF-vr-5sH" secondAttribute="bottom" constant="10" id="852-oh-vM0"/>
|
||||||
|
<constraint firstItem="ZsR-MN-QVA" firstAttribute="leading" secondItem="1" secondAttribute="leading" constant="10" id="CHP-wF-HhN"/>
|
||||||
<constraint firstItem="OEz-QK-nem" firstAttribute="leading" secondItem="afM-Om-nLQ" secondAttribute="trailing" constant="5" id="CIj-Dk-Md0"/>
|
<constraint firstItem="OEz-QK-nem" firstAttribute="leading" secondItem="afM-Om-nLQ" secondAttribute="trailing" constant="5" id="CIj-Dk-Md0"/>
|
||||||
<constraint firstAttribute="trailing" secondItem="ACO-U2-AZj" secondAttribute="trailing" id="HIg-sX-IK0"/>
|
<constraint firstAttribute="trailing" secondItem="ACO-U2-AZj" secondAttribute="trailing" id="HIg-sX-IK0"/>
|
||||||
<constraint firstItem="ACO-U2-AZj" firstAttribute="leading" secondItem="1" secondAttribute="leading" id="IGL-2g-wpe"/>
|
<constraint firstItem="ACO-U2-AZj" firstAttribute="leading" secondItem="1" secondAttribute="leading" id="IGL-2g-wpe"/>
|
||||||
|
<constraint firstItem="ZsR-MN-QVA" firstAttribute="top" secondItem="ACO-U2-AZj" secondAttribute="bottom" constant="10" id="K9U-z1-gie"/>
|
||||||
<constraint firstItem="afM-Om-nLQ" firstAttribute="leading" secondItem="1" secondAttribute="leading" constant="10" id="LK2-cg-qcY"/>
|
<constraint firstItem="afM-Om-nLQ" firstAttribute="leading" secondItem="1" secondAttribute="leading" constant="10" id="LK2-cg-qcY"/>
|
||||||
<constraint firstItem="NVE-vN-dkz" firstAttribute="top" secondItem="ACO-U2-AZj" secondAttribute="bottom" constant="10" id="RSD-PX-W0H"/>
|
<constraint firstItem="NVE-vN-dkz" firstAttribute="top" secondItem="ACO-U2-AZj" secondAttribute="bottom" constant="10" id="RSD-PX-W0H"/>
|
||||||
<constraint firstAttribute="bottom" secondItem="NVE-vN-dkz" secondAttribute="bottom" constant="10" id="USG-Gg-of3"/>
|
<constraint firstAttribute="bottom" secondItem="NVE-vN-dkz" secondAttribute="bottom" constant="10" id="USG-Gg-of3"/>
|
||||||
@@ -256,6 +276,82 @@ Gw
|
|||||||
</scroller>
|
</scroller>
|
||||||
<point key="canvasLocation" x="-397.5" y="30"/>
|
<point key="canvasLocation" x="-397.5" y="30"/>
|
||||||
</scrollView>
|
</scrollView>
|
||||||
|
<customView id="cIc-n7-hIV">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="380" height="400"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="oJM-qC-yyW">
|
||||||
|
<rect key="frame" x="8" y="358" width="364" height="32"/>
|
||||||
|
<textFieldCell key="cell" alignment="center" title="Scan this QR code with an Android device. The transfer will begin automatically." id="d3J-ot-h5d">
|
||||||
|
<font key="font" usesAppearanceFont="YES"/>
|
||||||
|
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
</textFieldCell>
|
||||||
|
</textField>
|
||||||
|
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="pLr-Yq-OMn">
|
||||||
|
<rect key="frame" x="301" y="3" width="76" height="32"/>
|
||||||
|
<buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="9EW-Db-fGL">
|
||||||
|
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||||
|
<font key="font" metaFont="system"/>
|
||||||
|
<string key="keyEquivalent" base64-UTF8="YES">
|
||||||
|
Gw
|
||||||
|
</string>
|
||||||
|
<connections>
|
||||||
|
<action selector="dismissQrCodeSheet:" target="-2" id="OX6-j3-Dag"/>
|
||||||
|
</connections>
|
||||||
|
</buttonCell>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="60" id="eRJ-dH-AQv"/>
|
||||||
|
</constraints>
|
||||||
|
</button>
|
||||||
|
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="mP8-S4-SUv">
|
||||||
|
<rect key="frame" x="8" y="40" width="364" height="42"/>
|
||||||
|
<textFieldCell key="cell" alignment="center" id="uuF-4K-rMR">
|
||||||
|
<font key="font" metaFont="smallSystem"/>
|
||||||
|
<string key="title">If this doesn't work, make sure that the device and your Mac are on the same network, and that the router isn't blocking LAN communication.</string>
|
||||||
|
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
</textFieldCell>
|
||||||
|
</textField>
|
||||||
|
<customView translatesAutoresizingMaskIntoConstraints="NO" id="dq7-IV-6Ef">
|
||||||
|
<rect key="frame" x="80" y="113" width="220" height="220"/>
|
||||||
|
<subviews>
|
||||||
|
<customView translatesAutoresizingMaskIntoConstraints="NO" id="lnf-Ci-bVP" customClass="QrCodeBackgroundView" customModule="ShareExtension" customModuleProvider="target">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="220" height="220"/>
|
||||||
|
</customView>
|
||||||
|
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="9Hk-Pa-eYI">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="220" height="220"/>
|
||||||
|
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="J6N-uf-WsV"/>
|
||||||
|
</imageView>
|
||||||
|
</subviews>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstItem="lnf-Ci-bVP" firstAttribute="leading" secondItem="dq7-IV-6Ef" secondAttribute="leading" id="16L-0N-tMO"/>
|
||||||
|
<constraint firstItem="9Hk-Pa-eYI" firstAttribute="top" secondItem="dq7-IV-6Ef" secondAttribute="top" id="22t-Se-FtM"/>
|
||||||
|
<constraint firstAttribute="bottom" secondItem="lnf-Ci-bVP" secondAttribute="bottom" id="9XU-id-5Lj"/>
|
||||||
|
<constraint firstItem="9Hk-Pa-eYI" firstAttribute="leading" secondItem="dq7-IV-6Ef" secondAttribute="leading" id="KWg-eg-4sO"/>
|
||||||
|
<constraint firstAttribute="width" constant="220" id="drn-Gr-Tx6"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="9Hk-Pa-eYI" secondAttribute="trailing" id="fif-Sg-QCc"/>
|
||||||
|
<constraint firstAttribute="bottom" secondItem="9Hk-Pa-eYI" secondAttribute="bottom" id="iVK-yf-1Ev"/>
|
||||||
|
<constraint firstAttribute="height" constant="220" id="l69-dh-xwJ"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="lnf-Ci-bVP" secondAttribute="trailing" id="pva-qe-Ibk"/>
|
||||||
|
<constraint firstItem="lnf-Ci-bVP" firstAttribute="top" secondItem="dq7-IV-6Ef" secondAttribute="top" id="yOu-Bz-qVZ"/>
|
||||||
|
</constraints>
|
||||||
|
</customView>
|
||||||
|
</subviews>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstItem="oJM-qC-yyW" firstAttribute="leading" secondItem="cIc-n7-hIV" secondAttribute="leading" constant="10" id="HaS-Sl-afe"/>
|
||||||
|
<constraint firstItem="dq7-IV-6Ef" firstAttribute="centerX" secondItem="cIc-n7-hIV" secondAttribute="centerX" id="Iip-bT-bl3"/>
|
||||||
|
<constraint firstItem="dq7-IV-6Ef" firstAttribute="top" secondItem="oJM-qC-yyW" secondAttribute="bottom" constant="25" id="YMN-xe-7cI"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="pLr-Yq-OMn" secondAttribute="trailing" constant="10" id="cAr-rb-sXX"/>
|
||||||
|
<constraint firstItem="oJM-qC-yyW" firstAttribute="top" secondItem="cIc-n7-hIV" secondAttribute="top" constant="10" id="gts-uR-3Ej"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="oJM-qC-yyW" secondAttribute="trailing" constant="10" id="hwy-vE-lHk"/>
|
||||||
|
<constraint firstAttribute="bottom" secondItem="pLr-Yq-OMn" secondAttribute="bottom" constant="10" id="jpn-he-6Ju"/>
|
||||||
|
<constraint firstItem="pLr-Yq-OMn" firstAttribute="top" secondItem="mP8-S4-SUv" secondAttribute="bottom" constant="10" id="sbP-BO-Te7"/>
|
||||||
|
<constraint firstItem="mP8-S4-SUv" firstAttribute="leading" secondItem="cIc-n7-hIV" secondAttribute="leading" constant="10" id="vUz-rq-dbN"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="mP8-S4-SUv" secondAttribute="trailing" constant="10" id="way-Az-buy"/>
|
||||||
|
</constraints>
|
||||||
|
<point key="canvasLocation" x="-13" y="400"/>
|
||||||
|
</customView>
|
||||||
</objects>
|
</objects>
|
||||||
<resources>
|
<resources>
|
||||||
<image name="NSCaution" width="32" height="32"/>
|
<image name="NSCaution" width="32" height="32"/>
|
||||||
|
|||||||
46
ShareExtension/QrCodeBackgroundView.swift
Normal file
46
ShareExtension/QrCodeBackgroundView.swift
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
//
|
||||||
|
// QrCodeBackgroundView.swift
|
||||||
|
// ShareExtension
|
||||||
|
//
|
||||||
|
// Created by Grishka on 07.08.2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Metal
|
||||||
|
import MetalKit
|
||||||
|
|
||||||
|
class QrCodeBackgroundView:MTKView{
|
||||||
|
private var commandQueue:MTLCommandQueue?
|
||||||
|
private var commandBuffer:MTLCommandBuffer?
|
||||||
|
|
||||||
|
override func awakeFromNib() {
|
||||||
|
super.awakeFromNib()
|
||||||
|
isPaused=true
|
||||||
|
enableSetNeedsDisplay=false
|
||||||
|
device=MTLCreateSystemDefaultDevice()
|
||||||
|
let brightness=1.5
|
||||||
|
clearColor=MTLClearColor(red: brightness, green: brightness, blue: brightness, alpha: 1)
|
||||||
|
|
||||||
|
let mtlLayer:CAMetalLayer=(layer as? CAMetalLayer)!
|
||||||
|
mtlLayer.wantsExtendedDynamicRangeContent=true
|
||||||
|
mtlLayer.cornerRadius=20
|
||||||
|
mtlLayer.masksToBounds=true
|
||||||
|
colorspace=CGColorSpace(name: CGColorSpace.extendedSRGB)
|
||||||
|
colorPixelFormat = .rgba16Float
|
||||||
|
|
||||||
|
commandQueue=device!.makeCommandQueue()
|
||||||
|
commandBuffer=commandQueue!.makeCommandBuffer()
|
||||||
|
draw()
|
||||||
|
}
|
||||||
|
|
||||||
|
override func draw(_ dirtyRect: NSRect) {
|
||||||
|
guard let commandBuffer=commandBuffer else {return}
|
||||||
|
if let descriptor=currentRenderPassDescriptor, let encoder=commandBuffer.makeRenderCommandEncoder(descriptor: descriptor){
|
||||||
|
encoder.endEncoding()
|
||||||
|
if let currentDrawable=currentDrawable{
|
||||||
|
commandBuffer.present(currentDrawable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
commandBuffer.commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import Cocoa
|
import Cocoa
|
||||||
import NearbyShare
|
import NearbyShare
|
||||||
|
import QRCode
|
||||||
|
|
||||||
class ShareViewController: NSViewController, ShareExtensionDelegate{
|
class ShareViewController: NSViewController, ShareExtensionDelegate{
|
||||||
|
|
||||||
@@ -15,6 +16,7 @@ class ShareViewController: NSViewController, ShareExtensionDelegate{
|
|||||||
private var foundDevices:[RemoteDeviceInfo]=[]
|
private var foundDevices:[RemoteDeviceInfo]=[]
|
||||||
private var chosenDevice:RemoteDeviceInfo?
|
private var chosenDevice:RemoteDeviceInfo?
|
||||||
private var lastError:Error?
|
private var lastError:Error?
|
||||||
|
private var sheetWindow:NSWindow?
|
||||||
|
|
||||||
@IBOutlet var filesIcon:NSImageView?
|
@IBOutlet var filesIcon:NSImageView?
|
||||||
@IBOutlet var filesLabel:NSTextField?
|
@IBOutlet var filesLabel:NSTextField?
|
||||||
@@ -30,6 +32,11 @@ class ShareViewController: NSViewController, ShareExtensionDelegate{
|
|||||||
@IBOutlet var progressState:NSTextField?
|
@IBOutlet var progressState:NSTextField?
|
||||||
@IBOutlet var progressDeviceIconWrap:NSView?
|
@IBOutlet var progressDeviceIconWrap:NSView?
|
||||||
@IBOutlet var progressDeviceSecondaryIcon:NSImageView?
|
@IBOutlet var progressDeviceSecondaryIcon:NSImageView?
|
||||||
|
@IBOutlet var qrCodeButton:NSButton?
|
||||||
|
|
||||||
|
@IBOutlet var qrCodeSheetView:NSView?
|
||||||
|
@IBOutlet var qrCodeView:NSImageView?
|
||||||
|
@IBOutlet var qrCodeWrapView:NSView?
|
||||||
|
|
||||||
override var nibName: NSNib.Name? {
|
override var nibName: NSNib.Name? {
|
||||||
return NSNib.Name("ShareViewController")
|
return NSNib.Name("ShareViewController")
|
||||||
@@ -38,7 +45,6 @@ class ShareViewController: NSViewController, ShareExtensionDelegate{
|
|||||||
override func loadView() {
|
override func loadView() {
|
||||||
super.loadView()
|
super.loadView()
|
||||||
|
|
||||||
// Insert code here to customize the view
|
|
||||||
let item = self.extensionContext!.inputItems[0] as! NSExtensionItem
|
let item = self.extensionContext!.inputItems[0] as! NSExtensionItem
|
||||||
if let attachments = item.attachments {
|
if let attachments = item.attachments {
|
||||||
for attachment in attachments as NSArray{
|
for attachment in attachments as NSArray{
|
||||||
@@ -99,6 +105,13 @@ class ShareViewController: NSViewController, ShareExtensionDelegate{
|
|||||||
|
|
||||||
progressDeviceIconWrap!.wantsLayer=true
|
progressDeviceIconWrap!.wantsLayer=true
|
||||||
progressDeviceIconWrap!.layer!.masksToBounds=false
|
progressDeviceIconWrap!.layer!.masksToBounds=false
|
||||||
|
|
||||||
|
qrCodeWrapView!.wantsLayer=true
|
||||||
|
qrCodeWrapView!.layer!.masksToBounds=false
|
||||||
|
qrCodeWrapView!.layer!.shadowColor = .black
|
||||||
|
qrCodeWrapView!.layer!.shadowOpacity=0.3
|
||||||
|
qrCodeWrapView!.layer!.shadowRadius=12
|
||||||
|
qrCodeWrapView!.layer!.shadowOffset=CGSizeMake(0, -5)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewDidLoad(){
|
override func viewDidLoad(){
|
||||||
@@ -122,6 +135,39 @@ class ShareViewController: NSViewController, ShareExtensionDelegate{
|
|||||||
self.extensionContext!.cancelRequest(withError: cancelError)
|
self.extensionContext!.cancelRequest(withError: cancelError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@IBAction func useQrCode(_ sender: AnyObject?) {
|
||||||
|
let window=contentWrap!.window!
|
||||||
|
let sheetWindow=NSWindow()
|
||||||
|
sheetWindow.contentView=qrCodeSheetView!
|
||||||
|
let size=NSSize(width: 380, height: 400)
|
||||||
|
sheetWindow.contentMaxSize=size
|
||||||
|
sheetWindow.contentMinSize=size
|
||||||
|
sheetWindow.setContentSize(size)
|
||||||
|
|
||||||
|
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(.roundedPointing())
|
||||||
|
.errorCorrection(.low)
|
||||||
|
.generate.image(dimension: Int(qrCodeView!.frame.width)*2)
|
||||||
|
qrCodeView!.image=NSImage(cgImage: qrCodeImage, size: qrCodeImage.size)
|
||||||
|
|
||||||
|
self.sheetWindow=sheetWindow
|
||||||
|
window.beginSheet(sheetWindow) { response in
|
||||||
|
self.sheetWindow=nil
|
||||||
|
NearbyConnectionManager.shared.clearQrCodeKey()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@IBAction func dismissQrCodeSheet(_ sender: AnyObject?){
|
||||||
|
contentWrap!.window!.endSheet(sheetWindow!)
|
||||||
|
sheetWindow=nil
|
||||||
|
NearbyConnectionManager.shared.clearQrCodeKey()
|
||||||
|
}
|
||||||
|
|
||||||
private func urlsReady(){
|
private func urlsReady(){
|
||||||
for url in urls{
|
for url in urls{
|
||||||
if url.isFileURL{
|
if url.isFileURL{
|
||||||
@@ -172,6 +218,11 @@ class ShareViewController: NSViewController, ShareExtensionDelegate{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func startTransferWithQrCode(device: RemoteDeviceInfo){
|
||||||
|
dismissQrCodeSheet(nil)
|
||||||
|
selectDevice(device: device)
|
||||||
|
}
|
||||||
|
|
||||||
func connectionWasEstablished(pinCode: String) {
|
func connectionWasEstablished(pinCode: String) {
|
||||||
progressState?.stringValue=String(format:NSLocalizedString("PinCode", value: "PIN: %@", comment: ""), arguments: [pinCode])
|
progressState?.stringValue=String(format:NSLocalizedString("PinCode", value: "PIN: %@", comment: ""), arguments: [pinCode])
|
||||||
progressProgressBar?.isIndeterminate=false
|
progressProgressBar?.isIndeterminate=false
|
||||||
@@ -224,6 +275,7 @@ class ShareViewController: NSViewController, ShareExtensionDelegate{
|
|||||||
NearbyConnectionManager.shared.stopDeviceDiscovery()
|
NearbyConnectionManager.shared.stopDeviceDiscovery()
|
||||||
listViewWrapper?.animator().isHidden=true
|
listViewWrapper?.animator().isHidden=true
|
||||||
progressView?.animator().isHidden=false
|
progressView?.animator().isHidden=false
|
||||||
|
qrCodeButton?.animator().isHidden=true
|
||||||
progressDeviceName?.stringValue=device.name
|
progressDeviceName?.stringValue=device.name
|
||||||
progressDeviceIcon?.image=imageForDeviceType(type: device.type)
|
progressDeviceIcon?.image=imageForDeviceType(type: device.type)
|
||||||
progressProgressBar?.startAnimation(nil)
|
progressProgressBar?.startAnimation(nil)
|
||||||
|
|||||||
@@ -5,8 +5,20 @@
|
|||||||
/* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "6Up-t3-mwm"; */
|
/* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "6Up-t3-mwm"; */
|
||||||
"6Up-t3-mwm.title" = "Отменить";
|
"6Up-t3-mwm.title" = "Отменить";
|
||||||
|
|
||||||
|
/* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "9EW-Db-fGL"; */
|
||||||
|
"9EW-Db-fGL.title" = "Отменить";
|
||||||
|
|
||||||
|
/* Class = "NSButtonCell"; title = "Use QR code..."; ObjectID = "Ll5-lP-3bU"; */
|
||||||
|
"Ll5-lP-3bU.title" = "Использовать QR-код...";
|
||||||
|
|
||||||
/* Class = "NSTextFieldCell"; title = "Looking for devices..."; ObjectID = "NaJ-Wx-Pim"; */
|
/* Class = "NSTextFieldCell"; title = "Looking for devices..."; ObjectID = "NaJ-Wx-Pim"; */
|
||||||
"NaJ-Wx-Pim.title" = "Ищу устройства...";
|
"NaJ-Wx-Pim.title" = "Ищу устройства...";
|
||||||
|
|
||||||
|
/* Class = "NSTextFieldCell"; title = "Scan this QR code with an Android device. The transfer will begin automatically."; ObjectID = "d3J-ot-h5d"; */
|
||||||
|
"d3J-ot-h5d.title" = "Отсканируйте этот QR-код на Android-устройстве. Передача начнётся автоматически.";
|
||||||
|
|
||||||
|
/* Class = "NSTextFieldCell"; title = "If this doesn't work, make sure that the device and your Mac are on the same network, and that the router isn't blocking LAN communication."; ObjectID = "uuF-4K-rMR"; */
|
||||||
|
"uuF-4K-rMR.title" = "Если соединиться не удаётся, убедитесь, что устройство и Mac находятся в одной сети, и что роутер не блокирует передачу данных по локальной сети.";
|
||||||
|
|
||||||
/* Class = "NSTextFieldCell"; title = "If you don't see your device, open \"Files by Google\" app and tap \"Receive\" on the Nearby Share tab."; ObjectID = "vla-gF-eJo"; */
|
/* Class = "NSTextFieldCell"; title = "If you don't see your device, open \"Files by Google\" app and tap \"Receive\" on the Nearby Share tab."; ObjectID = "vla-gF-eJo"; */
|
||||||
"vla-gF-eJo.title" = "Если Вы не видите своё устройство, откройте приложение \"Google Files\" и нажмите \"Получить\" на вкладке Обмен.";
|
"vla-gF-eJo.title" = "Если Вы не видите своё устройство, откройте приложение \"Google Files\" и нажмите \"Получить\" на вкладке Обмен.";
|
||||||
|
|||||||
Reference in New Issue
Block a user