UI Improvements

This commit is contained in:
Leon Böttger committed 2025-06-02 14:31:38 +02:00
1 parent 98da599302
commit 90e3e23905
31 files changed
+458 -277

No files matched your search

+17 -17
View File
@@ -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
View File
@@ -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 {
+21
View File
@@ -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

+4
View File
@@ -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!";
+110
View File
@@ -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: {})
}
-54
View File
@@ -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()
}
+3 -3
View File
@@ -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: {})
}
+40 -63
View File
@@ -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: {})
}
+4
View File
@@ -185,3 +185,7 @@ QuickDrop لنظام Android في المرحلة التجريبية حاليًا
قد يكون هناك مرشح حزم معيب مفعل على جهاز Mac، ربما تم تثبيته بواسطة برنامج مكافحة الفيروسات (مثل ESET). افتح تفضيلات النظام > الشبكة > VPN والتصفية، ثم قم بإيقاف تشغيل مرشح المحتوى.
بمجرد الانتهاء من ذلك، يجب أن تتمكن من نقل الملفات بنجاح.";
"TransmitUsingCable" = "النقل باستخدام الكابل";
"DownloadCableConnectionApp" = "تحميل iDroid";
"DownloadCableConnectionAppDescription" = "إذا كنت تريد نقل الملفات واستعراض تخزين جهاز Android الخاص بك عبر USB، يمكنك الآن القيام بذلك باستخدام تطبيق iDroid الجديد.\n\niDroid يدعم تنزيل وتحميل الملفات والمجلدات الكاملة باستخدام السحب والإفلات. iDroid مجاني لفترة محدودة!";
+4
View File
@@ -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!";
+3
View File
@@ -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!";
+4
View File
@@ -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 !";
+4
View File
@@ -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!";
+4
View File
@@ -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!";
+4
View File
@@ -187,3 +187,7 @@ AndroidデバイスからMacにファイルを送信するには、スマート
Mac で不具合のあるパケットフィルターが有効になっている可能性があり、これは ESET などのウイルス対策ソフトによってインストールされている場合があります。システム設定 > ネットワーク > VPNとフィルター を開き、コンテンツフィルターを無効にしてください。
これで、ファイルを正常に転送できるはずです。";
"TransmitUsingCable" = "ケーブルで転送";
"DownloadCableConnectionApp" = "iDroidをダウンロード";
"DownloadCableConnectionAppDescription" = "USB経由でAndroidデバイスのファイルを転送し、ストレージを閲覧したい場合は、新しいiDroidアプリを使って実現できます。\n\niDroidはドラッグ&ドロップによるファイルやフォルダのダウンロードとアップロードをサポートしています。iDroidは期間限定で無料です!";
+4
View File
@@ -187,3 +187,7 @@ Mac에서 바이러스 백신 프로그램을 사용하고 있을 가능성이
Mac에 문제가 있는 패킷 필터가 활성화되어 있을 수 있으며, 이는 ESET과 같은 백신 프로그램이 설치했을 수 있습니다. 시스템 설정 > 네트워크 > VPN 및 필터로 이동하여 콘텐츠 필터를 비활성화하세요.
이 작업이 완료되면 파일 전송이 정상적으로 이루어질 것입니다.";
"TransmitUsingCable" = "케이블로 전송";
"DownloadCableConnectionApp" = "iDroid 다운로드";
"DownloadCableConnectionAppDescription" = "USB를 통해 Android 기기의 파일을 전송하고 저장소를 탐색하려면, 이제 새롭게 출시된 iDroid 앱을 사용해보세요.\n\niDroid는 드래그 앤 드롭으로 전체 폴더 및 파일의 다운로드와 업로드를 지원합니다. iDroid는 한정된 시간 동안 무료입니다!";
+4
View File
@@ -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!";
+4
View File
@@ -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ă!";
+3
View File
@@ -190,3 +190,6 @@ QuickDrop для Android сейчас находится в стадии бет
После этого передача файлов должна пройти успешно.";
"TransmitUsingCable" = "Передача через кабель";
"DownloadCableConnectionApp" = "Скачать iDroid";
"DownloadCableConnectionAppDescription" = "Если вы хотите передавать файлы и просматривать хранилище вашего Android-устройства через USB, теперь вы можете сделать это с помощью нового приложения iDroid.\n\niDroid поддерживает загрузку и передачу файлов и целых папок с помощью перетаскивания. iDroid бесплатно в течение ограниченного времени!";
+4
View File
@@ -187,3 +187,7 @@ QuickDrop สำหรับ Android อยู่ในช่วงเบต้
Mac ของคุณอาจเปิดใช้งานตัวกรองแพ็กเก็ตที่มีปัญหา ซึ่งอาจติดตั้งโดยโปรแกรมป้องกันไวรัส (เช่น ESET) ให้เปิดการตั้งค่าระบบ > เครือข่าย > VPN และตัวกรอง แล้วปิดตัวกรองเนื้อหา
เมื่อทำเสร็จแล้ว คุณควรสามารถถ่ายโอนไฟล์ได้สำเร็จ";
"TransmitUsingCable" = "ถ่ายโอนด้วยสายเคเบิล";
"DownloadCableConnectionApp" = "ดาวน์โหลด iDroid";
"DownloadCableConnectionAppDescription" = "หากคุณต้องการถ่ายโอนไฟล์และเรียกดูที่เก็บข้อมูลของอุปกรณ์ Android ผ่าน USB ตอนนี้คุณสามารถทำได้ด้วยแอป iDroid ใหม่\n\niDroid รองรับการดาวน์โหลดและอัปโหลดไฟล์และโฟลเดอร์ทั้งหมดด้วยการลากและวาง iDroid ฟรีในช่วงเวลาจำกัด!";
+4
View File
@@ -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>
+2 -2
View File
@@ -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: {})
}