mirror of
https://github.com/leonboe1/QuickDrop.git
synced 2026-11-11 19:11:10 +00:00
UI Improvements
This commit is contained in:
1 parent
98da599302
commit
90e3e23905
31 files changed
+458
-277
No files matched your search
@@ -44,13 +44,13 @@
|
||||
EB7CD1452D6FB0C300CB0CB5 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB7CD1442D6FB0C100CB0CB5 /* Logger.swift */; };
|
||||
EB7CD1462D6FB0E800CB0CB5 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB7CD1442D6FB0C100CB0CB5 /* Logger.swift */; };
|
||||
EB7CD1472D6FB0E800CB0CB5 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB7CD1442D6FB0C100CB0CB5 /* Logger.swift */; };
|
||||
EB7F54102D78E6DF00989564 /* Sidebar.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB7F540F2D78E6DD00989564 /* Sidebar.swift */; };
|
||||
EB7F54122D78E96000989564 /* TutorialView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB7F54112D78E95C00989564 /* TutorialView.swift */; };
|
||||
EB7F54142D78E9E700989564 /* LicenseWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB7F54132D78E9E400989564 /* LicenseWindow.swift */; };
|
||||
EB91F0EB2DEDC741006C1867 /* CableConnectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB91F0EA2DEDC73D006C1867 /* CableConnectionView.swift */; };
|
||||
EB9237C42D7CDF8B00CA3A42 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 69D2C32B29E77F2200EC7E30 /* Localizable.strings */; };
|
||||
EB9237C52D7CDF9000CA3A42 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 69D2C33629E78DF400EC7E30 /* Localizable.stringsdict */; };
|
||||
EB96ED8B2D7F7CF7004B3FF1 /* QrCodeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB96ED8A2D7F7CF4004B3FF1 /* QrCodeView.swift */; };
|
||||
EB96ED8C2D7F7E7B004B3FF1 /* QrCodeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB96ED8A2D7F7CF4004B3FF1 /* QrCodeView.swift */; };
|
||||
EB96ED8B2D7F7CF7004B3FF1 /* SmallSheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB96ED8A2D7F7CF4004B3FF1 /* SmallSheetView.swift */; };
|
||||
EB96ED8C2D7F7E7B004B3FF1 /* SmallSheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB96ED8A2D7F7CF4004B3FF1 /* SmallSheetView.swift */; };
|
||||
EB96ED8D2D7F7EA3004B3FF1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 69DA9A1329E0BF5200A442DA /* Assets.xcassets */; };
|
||||
EB96ED8F2D7F8105004B3FF1 /* Localized.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB96ED8E2D7F8103004B3FF1 /* Localized.swift */; };
|
||||
EB96ED902D7F8114004B3FF1 /* Localized.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB96ED8E2D7F8103004B3FF1 /* Localized.swift */; };
|
||||
@@ -211,9 +211,9 @@
|
||||
EB6E743D2DD5C76F00331466 /* ConnectionFailureTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionFailureTracker.swift; sourceTree = "<group>"; };
|
||||
EB6F62D62D91F4AC00534EC2 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
|
||||
EB7CD1442D6FB0C100CB0CB5 /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
|
||||
EB7F540F2D78E6DD00989564 /* Sidebar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sidebar.swift; sourceTree = "<group>"; };
|
||||
EB7F54112D78E95C00989564 /* TutorialView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TutorialView.swift; sourceTree = "<group>"; };
|
||||
EB7F54132D78E9E400989564 /* LicenseWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LicenseWindow.swift; sourceTree = "<group>"; };
|
||||
EB91F0EA2DEDC73D006C1867 /* CableConnectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CableConnectionView.swift; sourceTree = "<group>"; };
|
||||
EB9237B52D7CDCE700CA3A42 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/ShareViewController.strings; sourceTree = "<group>"; };
|
||||
EB9237B72D7CDD7200CA3A42 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/ShareViewController.strings; sourceTree = "<group>"; };
|
||||
EB9237B92D7CDE3B00CA3A42 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/ShareViewController.strings; sourceTree = "<group>"; };
|
||||
@@ -222,7 +222,7 @@
|
||||
EB9237BF2D7CDE3E00CA3A42 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/ShareViewController.strings"; sourceTree = "<group>"; };
|
||||
EB9237C12D7CDE4000CA3A42 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/ShareViewController.strings; sourceTree = "<group>"; };
|
||||
EB9237C32D7CDE4100CA3A42 /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/ShareViewController.strings; sourceTree = "<group>"; };
|
||||
EB96ED8A2D7F7CF4004B3FF1 /* QrCodeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QrCodeView.swift; sourceTree = "<group>"; };
|
||||
EB96ED8A2D7F7CF4004B3FF1 /* SmallSheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmallSheetView.swift; sourceTree = "<group>"; };
|
||||
EB96ED8E2D7F8103004B3FF1 /* Localized.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Localized.swift; sourceTree = "<group>"; };
|
||||
EBCC27F82D80C9F70079C478 /* Zip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Zip.swift; sourceTree = "<group>"; };
|
||||
EBD2A2162D2860BE00BCB8E2 /* WelcomeScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeScreen.swift; sourceTree = "<group>"; };
|
||||
@@ -232,7 +232,7 @@
|
||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||
EB1A7E422DD4D8BD00A6D5A3 /* SelfTest */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = SelfTest; sourceTree = "<group>"; };
|
||||
EB6E743F2DD5CBFB00331466 /* IssueViews */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = IssueViews; sourceTree = "<group>"; };
|
||||
EB7CD13B2D6F8B6500CB0CB5 /* IAP */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = IAP; sourceTree = "<group>"; };
|
||||
EB7CD13B2D6F8B6500CB0CB5 /* Plus */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Plus; sourceTree = "<group>"; };
|
||||
/* End PBXFileSystemSynchronizedRootGroup section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -279,7 +279,7 @@
|
||||
children = (
|
||||
699DEBA52AB0573200115D22 /* ShareViewController.swift */,
|
||||
EBCC27F82D80C9F70079C478 /* Zip.swift */,
|
||||
EB96ED8A2D7F7CF4004B3FF1 /* QrCodeView.swift */,
|
||||
EB96ED8A2D7F7CF4004B3FF1 /* SmallSheetView.swift */,
|
||||
691F53B92ABB70840089FD92 /* DeviceListCell.swift */,
|
||||
691F53BA2ABB70840089FD92 /* DeviceListCell.xib */,
|
||||
699DEBA72AB0573200115D22 /* ShareViewController.xib */,
|
||||
@@ -321,12 +321,12 @@
|
||||
EB7F54112D78E95C00989564 /* TutorialView.swift */,
|
||||
EB1A7E422DD4D8BD00A6D5A3 /* SelfTest */,
|
||||
EB7F54132D78E9E400989564 /* LicenseWindow.swift */,
|
||||
EB91F0EA2DEDC73D006C1867 /* CableConnectionView.swift */,
|
||||
EB6F62D62D91F4AC00534EC2 /* SettingsView.swift */,
|
||||
EB36435F2D73A29F009CDFF8 /* AudioManager.swift */,
|
||||
EB6E743F2DD5CBFB00331466 /* IssueViews */,
|
||||
EB96ED8E2D7F8103004B3FF1 /* Localized.swift */,
|
||||
EB7F540F2D78E6DD00989564 /* Sidebar.swift */,
|
||||
EB7CD13B2D6F8B6500CB0CB5 /* IAP */,
|
||||
EB7CD13B2D6F8B6500CB0CB5 /* Plus */,
|
||||
69DA9A1329E0BF5200A442DA /* Assets.xcassets */,
|
||||
69D2C33629E78DF400EC7E30 /* Localizable.stringsdict */,
|
||||
69D2C32B29E77F2200EC7E30 /* Localizable.strings */,
|
||||
@@ -431,7 +431,7 @@
|
||||
fileSystemSynchronizedGroups = (
|
||||
EB1A7E422DD4D8BD00A6D5A3 /* SelfTest */,
|
||||
EB6E743F2DD5CBFB00331466 /* IssueViews */,
|
||||
EB7CD13B2D6F8B6500CB0CB5 /* IAP */,
|
||||
EB7CD13B2D6F8B6500CB0CB5 /* Plus */,
|
||||
);
|
||||
name = QuickDrop;
|
||||
packageProductDependencies = (
|
||||
@@ -559,7 +559,7 @@
|
||||
files = (
|
||||
EB96ED902D7F8114004B3FF1 /* Localized.swift in Sources */,
|
||||
699DEBA62AB0573200115D22 /* ShareViewController.swift in Sources */,
|
||||
EB96ED8B2D7F7CF7004B3FF1 /* QrCodeView.swift in Sources */,
|
||||
EB96ED8B2D7F7CF7004B3FF1 /* SmallSheetView.swift in Sources */,
|
||||
EBCC27F92D80C9F90079C478 /* Zip.swift in Sources */,
|
||||
EB7CD1462D6FB0E800CB0CB5 /* Logger.swift in Sources */,
|
||||
691F53BB2ABB70840089FD92 /* DeviceListCell.swift in Sources */,
|
||||
@@ -572,10 +572,10 @@
|
||||
files = (
|
||||
EBD2A2172D2860C100BCB8E2 /* WelcomeScreen.swift in Sources */,
|
||||
EB3643602D73A2A2009CDFF8 /* AudioManager.swift in Sources */,
|
||||
EB96ED8C2D7F7E7B004B3FF1 /* QrCodeView.swift in Sources */,
|
||||
EB91F0EB2DEDC741006C1867 /* CableConnectionView.swift in Sources */,
|
||||
EB96ED8C2D7F7E7B004B3FF1 /* SmallSheetView.swift in Sources */,
|
||||
EB7F54142D78E9E700989564 /* LicenseWindow.swift in Sources */,
|
||||
69DA9A1229E0BF5100A442DA /* AppDelegate.swift in Sources */,
|
||||
EB7F54102D78E6DF00989564 /* Sidebar.swift in Sources */,
|
||||
EB6F62D72D91F4AF00534EC2 /* SettingsView.swift in Sources */,
|
||||
EB7F54122D78E96000989564 /* TutorialView.swift in Sources */,
|
||||
EB96ED8F2D7F8105004B3FF1 /* Localized.swift in Sources */,
|
||||
@@ -825,8 +825,8 @@
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
SHARED_BUILD = 41;
|
||||
SHARED_VERSION = 1.9.2;
|
||||
SHARED_BUILD = 42;
|
||||
SHARED_VERSION = 1.9.3;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
@@ -884,8 +884,8 @@
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = macosx;
|
||||
SHARED_BUILD = 41;
|
||||
SHARED_VERSION = 1.9.2;
|
||||
SHARED_BUILD = 42;
|
||||
SHARED_VERSION = 1.9.3;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
};
|
||||
|
||||
+128
-104
@@ -23,7 +23,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
var welcomeWindow: NSWindow?
|
||||
var plusWindow: NSWindow?
|
||||
|
||||
private var qrCodeSheetView: NSPanel? = nil
|
||||
private var sheetView: NSPanel? = nil
|
||||
private var sheetAttachedWindow: NSWindow? = nil
|
||||
|
||||
var firewallAlertWindow: NSWindow?
|
||||
@@ -35,6 +35,9 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
var visibleItem: NSMenuItem? = nil
|
||||
let hasConnectionMonitor = NWPathMonitor()
|
||||
|
||||
|
||||
// MARK: NSApplicationDelegate functions
|
||||
|
||||
func applicationDidFinishLaunching(_: Notification) {
|
||||
let menu = NSMenu()
|
||||
|
||||
@@ -113,20 +116,35 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
let queue2 = DispatchQueue(label: "NetworkConnectionMonitor")
|
||||
hasConnectionMonitor.start(queue: queue2)
|
||||
}
|
||||
|
||||
|
||||
func applicationShouldHandleReopen(_: NSApplication, hasVisibleWindows _: Bool) -> Bool {
|
||||
openWelcomeScreen()
|
||||
statusItem?.isVisible = true
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
func performDeviceToDeviceCheck() {
|
||||
let scanner = DeviceToDeviceHeuristicScanner()
|
||||
scanner.scan { allowed in
|
||||
if allowed {
|
||||
log("✅ Device-to-device likely allowed (peer responded on LAN).")
|
||||
self.apIsolationAlertWindow?.close()
|
||||
} else {
|
||||
log("❌ Device-to-device check failed. Informing user...")
|
||||
self.openAlert(type: .ApIsolation)
|
||||
}
|
||||
}
|
||||
public func userNotificationCenter(_: UNUserNotificationCenter,
|
||||
willPresent _: UNNotification,
|
||||
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
||||
completionHandler([.sound, .banner])
|
||||
}
|
||||
|
||||
|
||||
func applicationWillTerminate(_: Notification) {
|
||||
UNUserNotificationCenter.current().removeAllDeliveredNotifications()
|
||||
iapManager?.stopObserving()
|
||||
}
|
||||
|
||||
|
||||
func applicationSupportsSecureRestorableState(_: NSApplication) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Button Actions
|
||||
|
||||
@objc func sendClipboard() {
|
||||
|
||||
let pasteboard = NSPasteboard.general
|
||||
@@ -136,11 +154,14 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
sharingService?.perform(withItems: [clipboardString])
|
||||
}
|
||||
|
||||
|
||||
@objc func openWelcomeScreen() {
|
||||
// Create the welcome screen SwiftUI view
|
||||
let welcomeView = WelcomeScreen(openPlusScreen: openPlusScreen, openAppAdvertisementView: openQrCodeView, checkForNetworkIssues: performDeviceToDeviceCheck)
|
||||
let welcomeView = WelcomeScreen(openPlusScreen: openPlusScreen,
|
||||
openAppAdvertisementView: { self.openSheetView(type: .downloadAndroidApp) },
|
||||
openCableTransmissionView: { self.openSheetView(type: .downloadCableConnectionApp) },
|
||||
checkForNetworkIssues: performDeviceToDeviceCheck)
|
||||
|
||||
// Create an NSWindow to host the SwiftUI view
|
||||
|
||||
welcomeWindow = NSWindow(
|
||||
contentRect: NSRect(x: 0, y: 0, width: 400, height: 280),
|
||||
styleMask: [.titled, .closable],
|
||||
@@ -162,43 +183,11 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
welcomeWindow?.makeKeyAndOrderFront(nil)
|
||||
welcomeWindow?.level = .normal
|
||||
}
|
||||
|
||||
|
||||
private func openQrCodeView() {
|
||||
if qrCodeSheetView == nil {
|
||||
let contentView = QrCodeView(advertisesApp: true) {
|
||||
self.closeQrCodeView()
|
||||
}
|
||||
|
||||
let hostingView = NSHostingView(rootView: contentView)
|
||||
|
||||
let panel = NSPanel(contentRect: NSRect(x: 0, y: 0, width: qrCodeViewSize.width, height: qrCodeViewSize.height),
|
||||
styleMask: [.titled, .closable, .utilityWindow],
|
||||
backing: .buffered,
|
||||
defer: false)
|
||||
|
||||
panel.contentView = hostingView
|
||||
|
||||
qrCodeSheetView = panel
|
||||
|
||||
if let mainWindow = NSApp.mainWindow {
|
||||
sheetAttachedWindow = mainWindow
|
||||
mainWindow.beginSheet(panel) { _ in }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func closeQrCodeView() {
|
||||
if let mainWindow = sheetAttachedWindow, let qrCodeView = qrCodeSheetView {
|
||||
mainWindow.endSheet(qrCodeView)
|
||||
|
||||
qrCodeSheetView = nil
|
||||
sheetAttachedWindow = nil
|
||||
}
|
||||
}
|
||||
|
||||
@objc func openPlusScreen() {
|
||||
// Create the welcome screen SwiftUI view
|
||||
let plusView = GetPlusView(closeView: {
|
||||
let plusView = PlusView(closeView: {
|
||||
log("Closing plus screen")
|
||||
self.plusWindow?.close()
|
||||
})
|
||||
@@ -225,12 +214,51 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
plusWindow?.makeKeyAndOrderFront(nil)
|
||||
plusWindow?.level = .normal
|
||||
}
|
||||
|
||||
|
||||
private func openSheetView(type: SheetViewType) {
|
||||
if sheetView == nil {
|
||||
let contentView = SmallSheetView(type: type) {
|
||||
self.closeSheetView()
|
||||
}
|
||||
|
||||
let hostingView = NSHostingView(rootView: contentView)
|
||||
|
||||
let panel = NSPanel(contentRect: NSRect(x: 0, y: 0, width: smallSheetViewSize.width, height: smallSheetViewSize.height),
|
||||
styleMask: [.titled, .closable, .utilityWindow],
|
||||
backing: .buffered,
|
||||
defer: false)
|
||||
|
||||
panel.contentView = hostingView
|
||||
|
||||
sheetView = panel
|
||||
|
||||
if let mainWindow = NSApp.mainWindow {
|
||||
sheetAttachedWindow = mainWindow
|
||||
mainWindow.beginSheet(panel) { _ in }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func closeSheetView() {
|
||||
if let mainWindow = sheetAttachedWindow, let sheetView = sheetView {
|
||||
mainWindow.endSheet(sheetView)
|
||||
|
||||
self.sheetView = nil
|
||||
self.sheetAttachedWindow = nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Alerts and Notifications
|
||||
|
||||
enum AlertType: String {
|
||||
case ApIsolation
|
||||
case NetworkFilter
|
||||
case Firewall
|
||||
}
|
||||
|
||||
|
||||
func openAlert(type: AlertType) {
|
||||
log("Opening Alert for \(type)")
|
||||
@@ -266,36 +294,42 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
alertWindow.level = .normal
|
||||
}
|
||||
}
|
||||
|
||||
// Action for "Recommended Apps" menu item
|
||||
@objc func openRecommendedApps() {
|
||||
if let url = URL(string: "https://apps.apple.com/de/developer/leon-boettger/id1537384790") {
|
||||
NSWorkspace.shared.open(url)
|
||||
|
||||
|
||||
func showFirewallAlert() {
|
||||
openAlert(type: .Firewall)
|
||||
}
|
||||
|
||||
|
||||
func showCopiedToClipboardAlert() {
|
||||
DispatchQueue.main.async {
|
||||
BezelNotification.show(messageText: "InsertedIntoClipboard".localized(), icon: .clipboard)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func showUnsupportedFileAlert(for device: RemoteDeviceInfo?) {
|
||||
|
||||
DispatchQueue.main.async {
|
||||
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
|
||||
let alert = NSAlert()
|
||||
alert.alertStyle = .critical
|
||||
|
||||
alert.messageText = String(format: NSLocalizedString("TransferError", value: "Failed to receive files from %@", comment: ""), arguments: [device?.name ?? "??"])
|
||||
alert.informativeText = "UnsupportedFileType".localized()
|
||||
|
||||
alert.addButton(withTitle: "InformDeveloper".localized())
|
||||
alert.addButton(withTitle: "CloseAlert".localized())
|
||||
|
||||
let _ = alert.runModal()
|
||||
}
|
||||
}
|
||||
|
||||
func applicationShouldHandleReopen(_: NSApplication, hasVisibleWindows _: Bool) -> Bool {
|
||||
openWelcomeScreen()
|
||||
statusItem?.isVisible = true
|
||||
return true
|
||||
}
|
||||
|
||||
public func userNotificationCenter(_: UNUserNotificationCenter,
|
||||
willPresent _: UNNotification,
|
||||
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
|
||||
{
|
||||
completionHandler([.sound, .banner])
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_: Notification) {
|
||||
UNUserNotificationCenter.current().removeAllDeliveredNotifications()
|
||||
iapManager?.stopObserving()
|
||||
}
|
||||
|
||||
func applicationSupportsSecureRestorableState(_: NSApplication) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Transfer Handling
|
||||
|
||||
public func continueTransmission(accept: Bool, transferID: String, storeInTemp: Bool = false) {
|
||||
NearbyConnectionManager.shared.submitUserConsent(transferID: transferID, accept: accept, storeInTemp: storeInTemp)
|
||||
|
||||
@@ -303,6 +337,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
activeIncomingTransfers.removeValue(forKey: transferID)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func obtainUserConsent(for transfer: TransferMetadata, from device: RemoteDeviceInfo) {
|
||||
|
||||
@@ -382,6 +417,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func pressAcceptButton(transferID: String) {
|
||||
if isFileTransferRestricted() {
|
||||
continueTransmission(accept: true, transferID: transferID, storeInTemp: true)
|
||||
@@ -392,35 +428,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
continueTransmission(accept: true, transferID: transferID)
|
||||
}
|
||||
}
|
||||
|
||||
func showFirewallAlert() {
|
||||
openAlert(type: .Firewall)
|
||||
}
|
||||
|
||||
func showCopiedToClipboardAlert() {
|
||||
DispatchQueue.main.async {
|
||||
BezelNotification.show(messageText: "InsertedIntoClipboard".localized(), icon: .clipboard)
|
||||
}
|
||||
}
|
||||
|
||||
func showUnsupportedFileAlert(for device: RemoteDeviceInfo?) {
|
||||
|
||||
DispatchQueue.main.async {
|
||||
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
|
||||
let alert = NSAlert()
|
||||
alert.alertStyle = .critical
|
||||
|
||||
alert.messageText = String(format: NSLocalizedString("TransferError", value: "Failed to receive files from %@", comment: ""), arguments: [device?.name ?? "??"])
|
||||
alert.informativeText = "UnsupportedFileType".localized()
|
||||
|
||||
alert.addButton(withTitle: "InformDeveloper".localized())
|
||||
alert.addButton(withTitle: "CloseAlert".localized())
|
||||
|
||||
let _ = alert.runModal()
|
||||
}
|
||||
}
|
||||
|
||||
func incomingTransfer(id: String, didFinishWith error: Error?) {
|
||||
|
||||
@@ -490,6 +498,22 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
|
||||
|
||||
activeIncomingTransfers.removeValue(forKey: id)
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Helper Functions
|
||||
|
||||
private func performDeviceToDeviceCheck() {
|
||||
let scanner = DeviceToDeviceHeuristicScanner()
|
||||
scanner.scan { allowed in
|
||||
if allowed {
|
||||
log("✅ Device-to-device likely allowed (peer responded on LAN).")
|
||||
self.apIsolationAlertWindow?.close()
|
||||
} else {
|
||||
log("❌ Device-to-device check failed. Informing user...")
|
||||
self.openAlert(type: .ApIsolation)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TransferInfo {
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "FileTransfer Kopie-1024.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 647 KiB |
@@ -196,3 +196,7 @@ Once this is done, your phone will be able to connect to your Mac.";
|
||||
Your Mac may have a faulty packet filter enabled, which might be installed by your antivirus program (e.g., ESET). Open System Preferences > Network > VPN & Filter and disable the content filter.
|
||||
|
||||
Once this is done, you should be able to transfer files successfully.";
|
||||
|
||||
"TransmitUsingCable" = "Transfer With Cable";
|
||||
"DownloadCableConnectionApp" = "Download iDroid";
|
||||
"DownloadCableConnectionAppDescription" = "If you want to transfer files and browse the storage of your Android device via USB, you can now do so with the new iDroid app.\n\niDroid supports downloading and uploading files and whole folders using Drag & Drop. iDroid is free for a limited time!";
|
||||
@@ -0,0 +1,110 @@
|
||||
//
|
||||
// CableConnectionView.swift
|
||||
// QuickDrop
|
||||
//
|
||||
// Created by Leon Böttger on 02.06.25.
|
||||
//
|
||||
|
||||
//import SwiftUI
|
||||
//
|
||||
//struct CableConnectionView: View {
|
||||
// let closeView: () -> Void
|
||||
//
|
||||
// @Environment(\.colorScheme) var colorScheme
|
||||
//
|
||||
// var body: some View {
|
||||
//
|
||||
// VStack {
|
||||
//
|
||||
// HStack {
|
||||
//
|
||||
// HStack(spacing: 5) {
|
||||
//
|
||||
// let imageSize: CGFloat = advertisesApp ? 20 : 25
|
||||
//
|
||||
// Image(.quickDropIcon)
|
||||
// .resizable()
|
||||
// .aspectRatio(contentMode: .fit)
|
||||
// .frame(width: imageSize, height: imageSize)
|
||||
//
|
||||
// if advertisesApp {
|
||||
// Text("QuickDrop")
|
||||
// }
|
||||
// }
|
||||
// .padding(.leading, 18)
|
||||
//
|
||||
// if !advertisesApp {
|
||||
// Spacer()
|
||||
//
|
||||
// HStack {
|
||||
// Text("ConnectWithQuickDropApp")
|
||||
// .padding(5)
|
||||
// .padding(.horizontal, 4)
|
||||
// .background(Capsule().fill(colorScheme == .light ? .white : .white.opacity(0.15)).opacity(connectWithApp ? 1 : 0))
|
||||
//
|
||||
// Text("ConnectWithoutApp")
|
||||
// .padding(5)
|
||||
// .padding(.horizontal, 4)
|
||||
// .background(Capsule().fill(colorScheme == .light ? .white : .white.opacity(0.15)).opacity(connectWithApp ? 0 : 1))
|
||||
// }
|
||||
// .padding(.horizontal, 1)
|
||||
// .padding(4)
|
||||
// .background(Capsule().fill(Color.gray.opacity(colorScheme == .light ? 0.2 : 0.15)))
|
||||
// .onTapGesture {
|
||||
// withAnimation {
|
||||
// connectWithApp.toggle()
|
||||
// }
|
||||
// }
|
||||
// .animation(.smooth, value:connectWithApp)
|
||||
// }
|
||||
//
|
||||
// Spacer()
|
||||
//
|
||||
// Button(action: {
|
||||
// closeView()
|
||||
// }, label: {
|
||||
// Image(systemName: "xmark")
|
||||
// .font(.system(size: 20))
|
||||
// .foregroundColor(.gray)
|
||||
// })
|
||||
// .buttonStyle(PlainButtonStyle())
|
||||
// }
|
||||
// .padding(.trailing, 15)
|
||||
// .padding(.leading, 10)
|
||||
// .padding(.top, 15)
|
||||
// .padding(.bottom, advertisesApp ? -10 : 0)
|
||||
//
|
||||
// Spacer()
|
||||
//
|
||||
// HStack {
|
||||
// Spacer()
|
||||
//
|
||||
// Image(connectWithApp ? .qrApp : .QR)
|
||||
// .resizable()
|
||||
// .aspectRatio(1, contentMode: .fit)
|
||||
// .frame(height: 160)
|
||||
//
|
||||
// Spacer()
|
||||
//
|
||||
//
|
||||
// Text(getDescription().localized())
|
||||
// .padding(.top, 5)
|
||||
// .padding(.horizontal)
|
||||
// .fixedSize(horizontal: false, vertical: true)
|
||||
// .multilineTextAlignment(.center)
|
||||
//
|
||||
// Spacer()
|
||||
// }
|
||||
// .padding(.horizontal)
|
||||
// .padding(.bottom)
|
||||
//
|
||||
// Spacer()
|
||||
//
|
||||
// }
|
||||
// .frame(width: qrCodeViewSize.width, height: qrCodeViewSize.height)
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//#Preview {
|
||||
// QrCodeView(advertisesApp: false, closeView: {})
|
||||
//}
|
||||
File renamed without changes.
File renamed without changes.
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// GetPlusView.swift
|
||||
// PlusView.swift
|
||||
// QuickDrop
|
||||
//
|
||||
// Created by Leon Böttger on 23.02.25.
|
||||
@@ -12,7 +12,7 @@ import NearbyShare
|
||||
let plusViewWidth: CGFloat = 440
|
||||
let plusViewHeight: CGFloat = 200
|
||||
|
||||
struct GetPlusView: View {
|
||||
struct PlusView: View {
|
||||
|
||||
@AppStorage(UserDefaultsKeys.plusVersion.rawValue) var isPlusVersion = false
|
||||
@ObservedObject private var iaphelper = IAPManager.sharedInstance
|
||||
@@ -253,5 +253,5 @@ extension SKProduct {
|
||||
|
||||
|
||||
#Preview {
|
||||
GetPlusView(closeView: {})
|
||||
PlusView(closeView: {})
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
//
|
||||
// Sidebar.swift
|
||||
// QuickDrop
|
||||
//
|
||||
// Created by Leon Böttger on 05.03.25.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct SidebarView: View {
|
||||
@State private var selection: String? = "Receive Files"
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
List(selection: $selection) {
|
||||
Label("Receive Files", systemImage: "tray.and.arrow.down.fill")
|
||||
.tag("Receive Files")
|
||||
Label("Send Files", systemImage: "tray.and.arrow.up.fill")
|
||||
.tag("Send Files")
|
||||
Label("Troubleshooting", systemImage: "exclamationmark.triangle.fill")
|
||||
.tag("Troubleshooting")
|
||||
}
|
||||
.frame(minWidth: 200, idealWidth: 250, maxWidth: 300)
|
||||
.listStyle(SidebarListStyle())
|
||||
|
||||
Divider()
|
||||
|
||||
if let selection = selection {
|
||||
DetailView(selection: selection)
|
||||
} else {
|
||||
Text("Select an option").frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct DetailView: View {
|
||||
let selection: String
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
Text(selection)
|
||||
.font(.largeTitle)
|
||||
.bold()
|
||||
Spacer()
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#Preview {
|
||||
SidebarView()
|
||||
}
|
||||
@@ -15,7 +15,7 @@ struct TutorialView: View {
|
||||
let showsLicense: Bool
|
||||
var showsBetaJoinButton: Bool = false
|
||||
|
||||
let openIAP: () -> Void
|
||||
let openPlus: () -> Void
|
||||
|
||||
@State private var licenseWindow: NSWindow?
|
||||
@State var taps = 0
|
||||
@@ -62,7 +62,7 @@ struct TutorialView: View {
|
||||
|
||||
if !isPlusVersion {
|
||||
Button {
|
||||
openIAP()
|
||||
openPlus()
|
||||
} label: {
|
||||
Text("SupportQuickDrop")
|
||||
.underline()
|
||||
@@ -165,5 +165,5 @@ func copyToClipboard(_ text: String) {
|
||||
|
||||
|
||||
#Preview {
|
||||
WelcomeScreen(openPlusScreen: {}, openAppAdvertisementView: {}, checkForNetworkIssues: {})
|
||||
WelcomeScreen(openPlusScreen: {}, openAppAdvertisementView: {}, openCableTransmissionView: {}, checkForNetworkIssues: {})
|
||||
}
|
||||
@@ -15,6 +15,7 @@ struct WelcomeScreen: View {
|
||||
|
||||
let openPlusScreen: () -> Void
|
||||
let openAppAdvertisementView: () -> Void
|
||||
let openCableTransmissionView: () -> Void
|
||||
let checkForNetworkIssues: () -> Void
|
||||
|
||||
@State private var selection: Tabs? = Tabs.receive
|
||||
@@ -23,78 +24,37 @@ struct WelcomeScreen: View {
|
||||
|
||||
HStack(spacing: 0) {
|
||||
List(selection: $selection) {
|
||||
ForEach(Tabs.allCases.filter({$0 != .settings && $0 != .app }), id: \.self) { tab in
|
||||
ForEach(Tabs.allCases.filter({$0 != .settings }), id: \.self) { tab in
|
||||
Label(tab.title, systemImage: tab.systemImage)
|
||||
// .font(.system(size: 13))
|
||||
.tag(tab)
|
||||
.frame(height: 30)
|
||||
}
|
||||
|
||||
Divider()
|
||||
|
||||
Button {
|
||||
ExternalLinkLabel(label: "GetSupport", icon: "questionmark.circle") {
|
||||
getSupport()
|
||||
} label: {
|
||||
HStack {
|
||||
Label("GetSupport", systemImage: "questionmark.circle")
|
||||
|
||||
Spacer()
|
||||
|
||||
Image(systemName: "arrow.up.right")
|
||||
.opacity(0.3)
|
||||
}
|
||||
.frame(height: 32)
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
|
||||
|
||||
Button {
|
||||
ExternalLinkLabel(label: "PrivacyPolicy", icon: "hand.raised") {
|
||||
openPrivacyPolicy()
|
||||
|
||||
} label: {
|
||||
|
||||
HStack {
|
||||
Label("PrivacyPolicy", systemImage: "hand.raised")
|
||||
|
||||
Spacer()
|
||||
|
||||
Image(systemName: "arrow.up.right")
|
||||
.opacity(0.3)
|
||||
}
|
||||
.frame(height: 32)
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
|
||||
|
||||
Button {
|
||||
ExternalLinkLabel(label: "AndroidApp", icon: "smartphone") {
|
||||
openAppAdvertisementView()
|
||||
} label: {
|
||||
|
||||
HStack {
|
||||
Label(Tabs.app.title, systemImage: Tabs.app.systemImage)
|
||||
|
||||
Spacer()
|
||||
|
||||
Image(systemName: "arrow.up.right")
|
||||
.opacity(0.3)
|
||||
}
|
||||
.frame(height: 32)
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
|
||||
ExternalLinkLabel(label: "TransmitUsingCable", icon: "cable.connector") {
|
||||
openCableTransmissionView()
|
||||
}
|
||||
|
||||
Divider()
|
||||
|
||||
Label(Tabs.settings.title, systemImage: Tabs.settings.systemImage)
|
||||
.tag(Tabs.settings)
|
||||
.frame(height: 30)
|
||||
|
||||
// Label(Tabs.app.title, systemImage: Tabs.app.systemImage)
|
||||
// .tag(Tabs.app)
|
||||
// .frame(height: 30)
|
||||
}
|
||||
.minimumScaleFactor(0.5)
|
||||
.frame(width: 220)
|
||||
.listStyle(SidebarListStyle())
|
||||
|
||||
@@ -107,20 +67,16 @@ struct WelcomeScreen: View {
|
||||
|
||||
switch selection {
|
||||
case .receive:
|
||||
TutorialView(title: "WelcomeToQuickDrop", text: "UserManualDescription", showsLicense: true, openIAP: openPlusScreen)
|
||||
TutorialView(title: "WelcomeToQuickDrop", text: "UserManualDescription", showsLicense: true, openPlus: openPlusScreen)
|
||||
|
||||
case .send:
|
||||
TutorialView(title: "SendFiles", text: "SendFilesDescription", showsLicense: false, openIAP: openPlusScreen)
|
||||
TutorialView(title: "SendFiles", text: "SendFilesDescription", showsLicense: false, openPlus: openPlusScreen)
|
||||
|
||||
case .troubleshooting:
|
||||
TutorialView(title: "Troubleshooting", text: "TroubleshootingDescription", showsLicense: false, openIAP: openPlusScreen)
|
||||
TutorialView(title: "Troubleshooting", text: "TroubleshootingDescription", showsLicense: false, openPlus: openPlusScreen)
|
||||
.onAppear {
|
||||
checkForNetworkIssues()
|
||||
}
|
||||
|
||||
// case .app:
|
||||
// TutorialView(title: "AndroidApp", text: "AndroidAppDescription", showsLicense: false, showsBetaJoinButton: true, openIAP: openPlusScreen)
|
||||
|
||||
default:
|
||||
SettingsView()
|
||||
}
|
||||
@@ -143,11 +99,36 @@ struct WelcomeScreen: View {
|
||||
}
|
||||
|
||||
|
||||
struct ExternalLinkLabel: View {
|
||||
|
||||
let label: String
|
||||
let icon: String
|
||||
let action: () -> Void
|
||||
|
||||
var body: some View {
|
||||
Button {
|
||||
action()
|
||||
} label: {
|
||||
HStack {
|
||||
Label(label.localized(), systemImage: icon)
|
||||
|
||||
Spacer()
|
||||
|
||||
Image(systemName: "arrow.up.right")
|
||||
.opacity(0.3)
|
||||
}
|
||||
.frame(height: 32)
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum Tabs: CaseIterable {
|
||||
case receive
|
||||
case send
|
||||
case troubleshooting
|
||||
case app
|
||||
case settings
|
||||
|
||||
var title: String {
|
||||
@@ -158,8 +139,6 @@ enum Tabs: CaseIterable {
|
||||
return "SendFiles".localized()
|
||||
case .troubleshooting:
|
||||
return "DeviceNotShown".localized()
|
||||
case .app:
|
||||
return "AndroidApp".localized()
|
||||
case .settings:
|
||||
return "Settings".localized()
|
||||
}
|
||||
@@ -175,13 +154,11 @@ enum Tabs: CaseIterable {
|
||||
return "exclamationmark.triangle"
|
||||
case .settings:
|
||||
return "gear"
|
||||
case .app:
|
||||
return "smartphone"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#Preview {
|
||||
WelcomeScreen(openPlusScreen: {}, openAppAdvertisementView: {}, checkForNetworkIssues: {})
|
||||
WelcomeScreen(openPlusScreen: {}, openAppAdvertisementView: {}, openCableTransmissionView: {}, checkForNetworkIssues: {})
|
||||
}
|
||||
@@ -185,3 +185,7 @@ QuickDrop لنظام Android في المرحلة التجريبية حاليًا
|
||||
قد يكون هناك مرشح حزم معيب مفعل على جهاز Mac، ربما تم تثبيته بواسطة برنامج مكافحة الفيروسات (مثل ESET). افتح تفضيلات النظام > الشبكة > VPN والتصفية، ثم قم بإيقاف تشغيل مرشح المحتوى.
|
||||
|
||||
بمجرد الانتهاء من ذلك، يجب أن تتمكن من نقل الملفات بنجاح.";
|
||||
|
||||
"TransmitUsingCable" = "النقل باستخدام الكابل";
|
||||
"DownloadCableConnectionApp" = "تحميل iDroid";
|
||||
"DownloadCableConnectionAppDescription" = "إذا كنت تريد نقل الملفات واستعراض تخزين جهاز Android الخاص بك عبر USB، يمكنك الآن القيام بذلك باستخدام تطبيق iDroid الجديد.\n\niDroid يدعم تنزيل وتحميل الملفات والمجلدات الكاملة باستخدام السحب والإفلات. iDroid مجاني لفترة محدودة!";
|
||||
@@ -189,3 +189,7 @@ Sobald dies erledigt ist, kann sich dein Telefon mit deinem Mac verbinden.";
|
||||
Möglicherweise ist auf deinem Mac ein fehlerhafter Paketfilter aktiviert, der z. B. von einem Antivirenprogramm (z. B. ESET) stammt. Öffne Systemeinstellungen > Netzwerk > VPN & Filter und deaktiviere den Inhaltsfilter.
|
||||
|
||||
Danach solltest du Dateien erfolgreich übertragen können.";
|
||||
|
||||
"TransmitUsingCable" = "Mit Kabel übertragen";
|
||||
"DownloadCableConnectionApp" = "iDroid herunterladen";
|
||||
"DownloadCableConnectionAppDescription" = "Wenn du Dateien übertragen und den Speicher deines Android-Geräts per USB durchsuchen willst, kannst du das jetzt mit der neuen iDroid-App tun.\n\niDroid unterstützt das Herunterladen und Hochladen von Dateien und ganzen Ordnern per Drag & Drop. iDroid ist für begrenzte Zeit kostenlos!";
|
||||
@@ -188,3 +188,6 @@ Es posible que tu Mac tenga habilitado un filtro de paquetes defectuoso, instala
|
||||
|
||||
Una vez hecho esto, deberías poder transferir archivos correctamente.";
|
||||
|
||||
"TransmitUsingCable" = "Transferir con Cable";
|
||||
"DownloadCableConnectionApp" = "Descargar iDroid";
|
||||
"DownloadCableConnectionAppDescription" = "Si deseas transferir archivos y explorar el almacenamiento de tu dispositivo Android mediante USB, ahora puedes hacerlo con la nueva aplicación iDroid.\n\niDroid admite la descarga y carga de archivos y carpetas completas mediante arrastrar y soltar. ¡iDroid es gratuita por tiempo limitado!";
|
||||
@@ -187,3 +187,7 @@ Une fois cela fait, votre téléphone pourra se connecter à votre Mac.";
|
||||
Votre Mac pourrait avoir un filtre de paquets défectueux activé, installé par exemple par un antivirus (comme ESET). Ouvrez Réglages Système > Réseau > VPN et Filtrage, puis désactivez le filtre de contenu.
|
||||
|
||||
Une fois cela fait, vous devriez pouvoir transférer des fichiers sans problème.";
|
||||
|
||||
"TransmitUsingCable" = "Transférer avec Câble";
|
||||
"DownloadCableConnectionApp" = "Télécharger iDroid";
|
||||
"DownloadCableConnectionAppDescription" = "Si vous souhaitez transférer des fichiers et explorer le stockage de votre appareil Android via USB, vous pouvez maintenant le faire avec la nouvelle application iDroid.\n\niDroid prend en charge le téléchargement et l'envoi de fichiers et dossiers entiers avec le glisser-déposer. iDroid est gratuit pour une durée limitée !";
|
||||
@@ -188,3 +188,7 @@ Ezek után a telefonja csatlakozni tud majd a Mac-hez.";
|
||||
Lehet, hogy a Mac gépén egy hibás csomagszűrő van engedélyezve, amelyet egy antivírus program (pl. ESET) telepített. Nyissa meg a Rendszerbeállítások > Hálózat > VPN és Szűrés menüpontot, és kapcsolja ki a tartalomszűrőt.
|
||||
|
||||
Ezután a fájlátvitelnek sikeresnek kell lennie.";
|
||||
|
||||
"TransmitUsingCable" = "Átvitel kábellel";
|
||||
"DownloadCableConnectionApp" = "iDroid letöltése";
|
||||
"DownloadCableConnectionAppDescription" = "Ha fájlokat szeretnél áthelyezni és böngészni Android-eszközöd tárhelyét USB-n keresztül, most megteheted az új iDroid alkalmazással.\n\niDroid támogatja a fájlok és teljes mappák letöltését és feltöltését húzással és ejtéssel. Az iDroid korlátozott ideig ingyenes!";
|
||||
@@ -187,3 +187,7 @@ Una volta fatto ciò, il tuo telefono sarà in grado di connettersi al tuo Mac."
|
||||
È possibile che sul tuo Mac sia attivo un filtro di pacchetti difettoso, installato ad esempio da un antivirus (es. ESET). Apri Preferenze di Sistema > Rete > VPN e Filtro e disattiva il filtro dei contenuti.
|
||||
|
||||
Una volta fatto, dovresti essere in grado di trasferire i file correttamente.";
|
||||
|
||||
"TransmitUsingCable" = "Trasferisci con Cavo";
|
||||
"DownloadCableConnectionApp" = "Scarica iDroid";
|
||||
"DownloadCableConnectionAppDescription" = "Se desideri trasferire file e navigare nella memoria del tuo dispositivo Android tramite USB, ora puoi farlo con la nuova app iDroid.\n\niDroid supporta il download e il caricamento di file e cartelle intere tramite Drag & Drop. iDroid è gratuita per un periodo limitato!";
|
||||
@@ -187,3 +187,7 @@ AndroidデバイスからMacにファイルを送信するには、スマート
|
||||
Mac で不具合のあるパケットフィルターが有効になっている可能性があり、これは ESET などのウイルス対策ソフトによってインストールされている場合があります。システム設定 > ネットワーク > VPNとフィルター を開き、コンテンツフィルターを無効にしてください。
|
||||
|
||||
これで、ファイルを正常に転送できるはずです。";
|
||||
|
||||
"TransmitUsingCable" = "ケーブルで転送";
|
||||
"DownloadCableConnectionApp" = "iDroidをダウンロード";
|
||||
"DownloadCableConnectionAppDescription" = "USB経由でAndroidデバイスのファイルを転送し、ストレージを閲覧したい場合は、新しいiDroidアプリを使って実現できます。\n\niDroidはドラッグ&ドロップによるファイルやフォルダのダウンロードとアップロードをサポートしています。iDroidは期間限定で無料です!";
|
||||
@@ -187,3 +187,7 @@ Mac에서 바이러스 백신 프로그램을 사용하고 있을 가능성이
|
||||
Mac에 문제가 있는 패킷 필터가 활성화되어 있을 수 있으며, 이는 ESET과 같은 백신 프로그램이 설치했을 수 있습니다. 시스템 설정 > 네트워크 > VPN 및 필터로 이동하여 콘텐츠 필터를 비활성화하세요.
|
||||
|
||||
이 작업이 완료되면 파일 전송이 정상적으로 이루어질 것입니다.";
|
||||
|
||||
"TransmitUsingCable" = "케이블로 전송";
|
||||
"DownloadCableConnectionApp" = "iDroid 다운로드";
|
||||
"DownloadCableConnectionAppDescription" = "USB를 통해 Android 기기의 파일을 전송하고 저장소를 탐색하려면, 이제 새롭게 출시된 iDroid 앱을 사용해보세요.\n\niDroid는 드래그 앤 드롭으로 전체 폴더 및 파일의 다운로드와 업로드를 지원합니다. iDroid는 한정된 시간 동안 무료입니다!";
|
||||
@@ -187,3 +187,7 @@ Zodra dit is gedaan, kan je telefoon verbinding maken met je Mac.";
|
||||
Je Mac heeft mogelijk een defect pakketfilter ingeschakeld, mogelijk geïnstalleerd door antivirussoftware (zoals ESET). Ga naar Systeeminstellingen > Netwerk > VPN en Filter en schakel het inhoudsfilter uit.
|
||||
|
||||
Daarna zou je bestanden succesvol moeten kunnen overdragen.";
|
||||
|
||||
"TransmitUsingCable" = "Overdragen met Kabel";
|
||||
"DownloadCableConnectionApp" = "Download iDroid";
|
||||
"DownloadCableConnectionAppDescription" = "Als je bestanden wilt overzetten en de opslag van je Android-apparaat via USB wilt verkennen, kan dat nu met de nieuwe iDroid-app.\n\niDroid ondersteunt het downloaden en uploaden van bestanden en volledige mappen via slepen en neerzetten. iDroid is tijdelijk gratis!";
|
||||
@@ -188,3 +188,6 @@ Pode haver um filtro de pacotes com defeito ativado no seu Mac, possivelmente in
|
||||
|
||||
Depois disso, você deve conseguir transferir arquivos com sucesso.";
|
||||
|
||||
"TransmitUsingCable" = "Transferir com Cabo";
|
||||
"DownloadCableConnectionApp" = "Baixar iDroid";
|
||||
"DownloadCableConnectionAppDescription" = "Se você deseja transferir arquivos e navegar no armazenamento do seu dispositivo Android via USB, agora pode fazer isso com o novo app iDroid.\n\niDroid suporta download e upload de arquivos e pastas inteiras usando Arrastar e Soltar. iDroid é gratuito por tempo limitado!";
|
||||
@@ -187,3 +187,7 @@ Depois de feito isto, o seu telefone poderá conectar-se ao seu Mac.";
|
||||
Pode ter um filtro de pacotes com defeito ativado no seu Mac, possivelmente instalado por um antivírus (por exemplo, ESET). Abra Preferências do Sistema > Rede > VPN e Filtro e desative o filtro de conteúdo.
|
||||
|
||||
Depois disso, deverá conseguir transferir ficheiros com sucesso.";
|
||||
|
||||
"TransmitUsingCable" = "Transferir com Cabo";
|
||||
"DownloadCableConnectionApp" = "Descarregar iDroid";
|
||||
"DownloadCableConnectionAppDescription" = "Se pretendes transferir ficheiros e explorar o armazenamento do teu dispositivo Android via USB, agora podes fazê-lo com a nova aplicação iDroid.\n\niDroid suporta transferência e envio de ficheiros e pastas inteiras através de arrastar e largar. O iDroid é gratuito por tempo limitado!";
|
||||
@@ -186,3 +186,7 @@ După ce faceți acest lucru, telefonul dvs. va putea să se conecteze la Mac.";
|
||||
Este posibil ca Mac-ul tău să aibă activat un filtru de pachete defect, instalat de un program antivirus (de exemplu, ESET). Deschide Preferințe Sistem > Rețea > VPN și Filtru și dezactivează filtrul de conținut.
|
||||
|
||||
După ce faci acest lucru, ar trebui să poți transfera fișiere cu succes.";
|
||||
|
||||
"TransmitUsingCable" = "Transferă cu Cablu";
|
||||
"DownloadCableConnectionApp" = "Descarcă iDroid";
|
||||
"DownloadCableConnectionAppDescription" = "Dacă dorești să transferi fișiere și să explorezi stocarea dispozitivului tău Android prin USB, acum poți face acest lucru cu noua aplicație iDroid.\n\niDroid permite descărcarea și încărcarea fișierelor și folderelor întregi prin tragere și plasare. iDroid este gratuit pentru o perioadă limitată!";
|
||||
@@ -190,3 +190,6 @@ QuickDrop для Android сейчас находится в стадии бет
|
||||
|
||||
После этого передача файлов должна пройти успешно.";
|
||||
|
||||
"TransmitUsingCable" = "Передача через кабель";
|
||||
"DownloadCableConnectionApp" = "Скачать iDroid";
|
||||
"DownloadCableConnectionAppDescription" = "Если вы хотите передавать файлы и просматривать хранилище вашего Android-устройства через USB, теперь вы можете сделать это с помощью нового приложения iDroid.\n\niDroid поддерживает загрузку и передачу файлов и целых папок с помощью перетаскивания. iDroid бесплатно в течение ограниченного времени!";
|
||||
@@ -187,3 +187,7 @@ QuickDrop สำหรับ Android อยู่ในช่วงเบต้
|
||||
Mac ของคุณอาจเปิดใช้งานตัวกรองแพ็กเก็ตที่มีปัญหา ซึ่งอาจติดตั้งโดยโปรแกรมป้องกันไวรัส (เช่น ESET) ให้เปิดการตั้งค่าระบบ > เครือข่าย > VPN และตัวกรอง แล้วปิดตัวกรองเนื้อหา
|
||||
|
||||
เมื่อทำเสร็จแล้ว คุณควรสามารถถ่ายโอนไฟล์ได้สำเร็จ";
|
||||
|
||||
"TransmitUsingCable" = "ถ่ายโอนด้วยสายเคเบิล";
|
||||
"DownloadCableConnectionApp" = "ดาวน์โหลด iDroid";
|
||||
"DownloadCableConnectionAppDescription" = "หากคุณต้องการถ่ายโอนไฟล์และเรียกดูที่เก็บข้อมูลของอุปกรณ์ Android ผ่าน USB ตอนนี้คุณสามารถทำได้ด้วยแอป iDroid ใหม่\n\niDroid รองรับการดาวน์โหลดและอัปโหลดไฟล์และโฟลเดอร์ทั้งหมดด้วยการลากและวาง iDroid ฟรีในช่วงเวลาจำกัด!";
|
||||
@@ -187,3 +187,7 @@ QuickDrop для Android наразі знаходиться в бета-вер
|
||||
На вашому Mac може бути активований несправний фільтр пакетів, встановлений антивірусною програмою (наприклад, ESET). Відкрийте Системні налаштування > Мережа > VPN і Фільтр та вимкніть фільтр вмісту.
|
||||
|
||||
Після цього передача файлів має працювати коректно.";
|
||||
|
||||
"TransmitUsingCable" = "Передача через кабель";
|
||||
"DownloadCableConnectionApp" = "Завантажити iDroid";
|
||||
"DownloadCableConnectionAppDescription" = "Якщо ви хочете передавати файли та переглядати сховище вашого Android-пристрою через USB, тепер це можливо з новим додатком iDroid.\n\niDroid підтримує завантаження та надсилання файлів і цілих папок через перетягування. iDroid безкоштовний протягом обмеженого часу!";
|
||||
@@ -187,3 +187,7 @@ QuickDrop for Android 当前处于测试阶段。要注册测试版,请发送
|
||||
您的 Mac 上可能启用了有问题的数据包过滤器,该过滤器可能由杀毒软件(如 ESET)安装。请打开系统设置 > 网络 > VPN 与过滤器,并关闭内容过滤器。
|
||||
|
||||
完成这些操作后,您应该可以成功传输文件。";
|
||||
|
||||
"TransmitUsingCable" = "通过数据线传输";
|
||||
"DownloadCableConnectionApp" = "下载 iDroid";
|
||||
"DownloadCableConnectionAppDescription" = "如果您想通过 USB 传输文件并浏览 Android 设备的存储空间,现在可以使用全新的 iDroid 应用程序。\n\niDroid 支持通过拖放下载和上传文件及整个文件夹。iDroid 限时免费!";
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="23504" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="23727" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="23504"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="23727"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
|
||||
@@ -147,13 +147,13 @@ class ShareViewController: NSViewController, ShareExtensionDelegate {
|
||||
|
||||
private func openQrCodeView() {
|
||||
if qrCodeSheetView == nil {
|
||||
let contentView = QrCodeView {
|
||||
let contentView = SmallSheetView(type: .sendToDeviceQrCode) {
|
||||
self.closeQrCodeView()
|
||||
}
|
||||
|
||||
let hostingView = NSHostingView(rootView: contentView)
|
||||
|
||||
let panel = NSPanel(contentRect: NSRect(x: 0, y: 0, width: qrCodeViewSize.width, height: qrCodeViewSize.height),
|
||||
let panel = NSPanel(contentRect: NSRect(x: 0, y: 0, width: smallSheetViewSize.width, height: smallSheetViewSize.height),
|
||||
styleMask: [.titled, .closable, .utilityWindow],
|
||||
backing: .buffered,
|
||||
defer: false)
|
||||
|
||||
@@ -7,11 +7,12 @@
|
||||
|
||||
import SwiftUI
|
||||
|
||||
let qrCodeViewSize = CGSize(width: 530.0, height: 270.0)
|
||||
let smallSheetViewSize = CGSize(width: 530.0, height: 270.0)
|
||||
|
||||
struct QrCodeView: View {
|
||||
struct SmallSheetView: View {
|
||||
@State private var qrCode: String = ""
|
||||
var advertisesApp = false
|
||||
|
||||
let type: SheetViewType
|
||||
let closeView: () -> Void
|
||||
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
@@ -23,7 +24,22 @@ struct QrCodeView: View {
|
||||
|
||||
HStack {
|
||||
|
||||
if !advertisesApp {
|
||||
HStack(spacing: 5) {
|
||||
|
||||
let imageSize: CGFloat = type == .sendToDeviceQrCode ? 25 : 20
|
||||
|
||||
Image(.quickDropIcon)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: imageSize, height: imageSize)
|
||||
|
||||
if type != .sendToDeviceQrCode {
|
||||
Text("QuickDrop")
|
||||
}
|
||||
}
|
||||
.padding(.leading, 18)
|
||||
|
||||
if type == .sendToDeviceQrCode {
|
||||
Spacer()
|
||||
|
||||
HStack {
|
||||
@@ -45,18 +61,7 @@ struct QrCodeView: View {
|
||||
connectWithApp.toggle()
|
||||
}
|
||||
}
|
||||
.animation(.smooth, value:connectWithApp)
|
||||
}
|
||||
else {
|
||||
HStack(spacing: 5) {
|
||||
Image(.quickDropIcon)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 20, height: 20)
|
||||
|
||||
Text("QuickDrop")
|
||||
}
|
||||
.padding(.leading, 18)
|
||||
.animation(.smooth, value: connectWithApp)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
@@ -73,26 +78,39 @@ struct QrCodeView: View {
|
||||
.padding(.trailing, 15)
|
||||
.padding(.leading, 10)
|
||||
.padding(.top, 15)
|
||||
.padding(.bottom, advertisesApp ? -10 : 0)
|
||||
.padding(.bottom, type == .sendToDeviceQrCode ? 0 : -10)
|
||||
|
||||
Spacer()
|
||||
|
||||
HStack {
|
||||
Spacer()
|
||||
|
||||
Image(connectWithApp ? .qrApp : .QR)
|
||||
getImage()
|
||||
.resizable()
|
||||
.aspectRatio(1, contentMode: .fit)
|
||||
.frame(height: 160)
|
||||
|
||||
Spacer()
|
||||
|
||||
|
||||
Text(getDescription().localized())
|
||||
.padding(.top, 5)
|
||||
.padding(.horizontal)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.multilineTextAlignment(.center)
|
||||
VStack {
|
||||
Text(getDescription().localized())
|
||||
.padding(.top, 5)
|
||||
.padding(.horizontal)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.multilineTextAlignment(.center)
|
||||
|
||||
if type == .downloadCableConnectionApp {
|
||||
Button {
|
||||
if let url = URL(string: "https://apps.apple.com/de/app/idroid-phone-file-manager/id6746444380") {
|
||||
NSWorkspace.shared.open(url)
|
||||
}
|
||||
} label: {
|
||||
Text("DownloadCableConnectionApp")
|
||||
}
|
||||
.keyboardShortcut(.defaultAction)
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
@@ -102,19 +120,39 @@ struct QrCodeView: View {
|
||||
Spacer()
|
||||
|
||||
}
|
||||
.frame(width: qrCodeViewSize.width, height: qrCodeViewSize.height)
|
||||
.frame(width: smallSheetViewSize.width, height: smallSheetViewSize.height)
|
||||
}
|
||||
|
||||
func getDescription() -> String {
|
||||
|
||||
if advertisesApp {
|
||||
switch type {
|
||||
case .sendToDeviceQrCode:
|
||||
return connectWithApp ? "QrCodeInstructionsApp" : "QrCodeInstructions"
|
||||
case .downloadAndroidApp:
|
||||
return "QuickDropAndroidAppAdvertisement"
|
||||
case .downloadCableConnectionApp:
|
||||
return "DownloadCableConnectionAppDescription"
|
||||
}
|
||||
}
|
||||
|
||||
func getImage() -> Image {
|
||||
switch type {
|
||||
case .sendToDeviceQrCode:
|
||||
return connectWithApp ? Image(.qrApp) : Image(.QR)
|
||||
case .downloadAndroidApp:
|
||||
return Image(.qrApp)
|
||||
case .downloadCableConnectionApp:
|
||||
return Image(.iDroid)
|
||||
}
|
||||
|
||||
return connectWithApp ? "QrCodeInstructionsApp" : "QrCodeInstructions"
|
||||
}
|
||||
}
|
||||
|
||||
enum SheetViewType {
|
||||
case sendToDeviceQrCode
|
||||
case downloadAndroidApp
|
||||
case downloadCableConnectionApp
|
||||
}
|
||||
|
||||
#Preview {
|
||||
QrCodeView(closeView: {})
|
||||
SmallSheetView(type: .downloadCableConnectionApp, closeView: {})
|
||||
}
|
||||
Reference in new issue
Block a user