From 6f9309d74e40b99454a99eb3fe9cc815d56358bf Mon Sep 17 00:00:00 2001 From: Marco Moschettini Date: Mon, 29 Jan 2024 00:10:30 +0100 Subject: [PATCH] fix: fix parent identifier with no prefix --- CubbitDS3Sync.xcodeproj/project.pbxproj | 16 ++++++++-------- CubbitDS3Sync/CubbitDS3SyncApp.swift | 13 +++++++------ .../Views/Login/ViewModels/LoginViewModel.swift | 1 + CubbitDS3Sync/Views/Login/Views/LoginView.swift | 13 ++++++++++++- CubbitDS3Sync/Views/Login/Views/MFAView.swift | 14 ++++++++++++++ .../Views/SyncRecapNameSelectionView.swift | 10 +++++++++- .../Tray/ViewModels/DS3DriveViewModel.swift | 2 -- .../Views/Tray/Views/TrayMenuView.swift | 9 ++++----- Provider/S3Enumerator.swift | 1 - Provider/S3Item.swift | 10 +++++++--- Provider/S3Lib.swift | 4 +++- 11 files changed, 65 insertions(+), 28 deletions(-) diff --git a/CubbitDS3Sync.xcodeproj/project.pbxproj b/CubbitDS3Sync.xcodeproj/project.pbxproj index 4bc8071..1457811 100644 --- a/CubbitDS3Sync.xcodeproj/project.pbxproj +++ b/CubbitDS3Sync.xcodeproj/project.pbxproj @@ -730,8 +730,8 @@ D5A221EC2B571FED00F1413B /* SyncRecap */ = { isa = PBXGroup; children = ( - D5A221ED2B571FED00F1413B /* ViewModels */, D5A221EF2B571FED00F1413B /* Views */, + D5A221ED2B571FED00F1413B /* ViewModels */, ); path = SyncRecap; sourceTree = ""; @@ -767,9 +767,9 @@ D5A221F72B571FED00F1413B /* Login */ = { isa = PBXGroup; children = ( - D5A221F82B571FED00F1413B /* ViewModels */, D5A221FA2B571FED00F1413B /* Models */, D5A221FC2B571FED00F1413B /* Views */, + D5A221F82B571FED00F1413B /* ViewModels */, ); path = Login; sourceTree = ""; @@ -1333,7 +1333,7 @@ CODE_SIGN_ENTITLEMENTS = CubbitDS3Sync/CubbitDS3Sync.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_ASSET_PATHS = "\"CubbitDS3Sync/Preview Content\""; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=macosx*]" = X889956QSM; @@ -1382,7 +1382,7 @@ CODE_SIGN_ENTITLEMENTS = CubbitDS3Sync/CubbitDS3Sync.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_ASSET_PATHS = "\"CubbitDS3Sync/Preview Content\""; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=macosx*]" = X889956QSM; @@ -1428,7 +1428,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = X889956QSM; DYLIB_COMPATIBILITY_VERSION = 1; @@ -1465,7 +1465,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = X889956QSM; DYLIB_COMPATIBILITY_VERSION = 1; @@ -1501,7 +1501,7 @@ CODE_SIGN_ENTITLEMENTS = Provider/Provider.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=macosx*]" = X889956QSM; ENABLE_HARDENED_RUNTIME = YES; @@ -1534,7 +1534,7 @@ CODE_SIGN_ENTITLEMENTS = Provider/Provider.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=macosx*]" = X889956QSM; ENABLE_HARDENED_RUNTIME = YES; diff --git a/CubbitDS3Sync/CubbitDS3SyncApp.swift b/CubbitDS3Sync/CubbitDS3SyncApp.swift index b738395..4b54908 100644 --- a/CubbitDS3Sync/CubbitDS3SyncApp.swift +++ b/CubbitDS3Sync/CubbitDS3SyncApp.swift @@ -3,16 +3,17 @@ import os.log @main struct ds3syncApp: App { + private let logger: Logger = Logger(subsystem: "io.cubbit.CubbitDS3Sync", category: "MainApp") + @AppStorage(DefaultSettings.UserDefaultsKeys.tutorial) var tutorialShown: Bool = DefaultSettings.tutorialShown @AppStorage(DefaultSettings.UserDefaultsKeys.loginItemSet) var loginItemSet: Bool = DefaultSettings.loginItemSet - private let logger: Logger = Logger(subsystem: "io.cubbit.CubbitDS3Sync", category: "MainApp") - - @State var showTrayIcon: Bool = true @State var ds3Authentication: DS3Authentication = DS3Authentication.loadFromPersistenceOrCreateNew() + @State var appStatusManager: AppStatusManager = AppStatusManager.default() + @State var ds3DriveManager: DS3DriveManager = DS3DriveManager(appStatusManager: AppStatusManager.default()) - var appStatusManager: AppStatusManager = AppStatusManager.default() - var ds3DriveManager: DS3DriveManager = DS3DriveManager(appStatusManager: AppStatusManager.default()) + // TODO: Hide tray menu when not logged in + @State var trayMenuVisible: Bool = true var body: some Scene { // MARK: - Main view @@ -79,7 +80,7 @@ struct ds3syncApp: App { #if os(macOS) // MARK: - Tray Menu - MenuBarExtra(isInserted: $showTrayIcon) { + MenuBarExtra(isInserted: $trayMenuVisible) { TrayMenuView() .environment(ds3Authentication) .environment(ds3DriveManager) diff --git a/CubbitDS3Sync/Views/Login/ViewModels/LoginViewModel.swift b/CubbitDS3Sync/Views/Login/ViewModels/LoginViewModel.swift index 04e0c6e..b986988 100644 --- a/CubbitDS3Sync/Views/Login/ViewModels/LoginViewModel.swift +++ b/CubbitDS3Sync/Views/Login/ViewModels/LoginViewModel.swift @@ -7,6 +7,7 @@ import os.log var loginError: Error? var need2FA: Bool = false + var tfaError: Error? var isLoading: Bool = false /// Logs in the account with the provided credentials diff --git a/CubbitDS3Sync/Views/Login/Views/LoginView.swift b/CubbitDS3Sync/Views/Login/Views/LoginView.swift index 2d3ee97..7e201e9 100644 --- a/CubbitDS3Sync/Views/Login/Views/LoginView.swift +++ b/CubbitDS3Sync/Views/Login/Views/LoginView.swift @@ -1,10 +1,14 @@ import SwiftUI struct LoginView: View { + enum FocusedField { + case email, password + } @Environment(DS3Authentication.self) var ds3Authentication: DS3Authentication @State var email: String = "" @State var password: String = "" + @FocusState private var focusedField: FocusedField? var loginViewModel: LoginViewModel = LoginViewModel() @@ -16,7 +20,8 @@ struct LoginView: View { .environment(ds3Authentication) } else { ZStack { - Color(.background).ignoresSafeArea() + Color(.background) + .ignoresSafeArea() VStack(alignment: .center) { Image(.cubbitLogo) @@ -35,6 +40,12 @@ struct LoginView: View { error: loginViewModel.loginError, text: $email ) + .focused(self.$focusedField, equals: .email) + .onAppear { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.75) { + self.focusedField = .email + } + } IconTextField( iconName: .passwordIcon, diff --git a/CubbitDS3Sync/Views/Login/Views/MFAView.swift b/CubbitDS3Sync/Views/Login/Views/MFAView.swift index 9fe10e7..763da33 100644 --- a/CubbitDS3Sync/Views/Login/Views/MFAView.swift +++ b/CubbitDS3Sync/Views/Login/Views/MFAView.swift @@ -8,6 +8,7 @@ struct MFAView: View { var password: String @State var tfaCode: String = "" + @FocusState var focused: Bool? var body: some View { ZStack { @@ -40,6 +41,12 @@ struct MFAView: View { placeholder: "2FA 6-digit code", text: $tfaCode ) + .focused($focused, equals: true) + .onAppear { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.75) { + self.focused = true + } + } .onSubmit { self.loginWithMFA() } @@ -53,6 +60,13 @@ struct MFAView: View { .onSubmit { self.loginWithMFA() } + + if let loginError = loginViewModel.loginError { + Text(loginError.localizedDescription) + .font(.custom("Nunito", size: 14)) + .foregroundStyle(Color.red) + .multilineTextAlignment(.center) + } } } } diff --git a/CubbitDS3Sync/Views/Sync/SyncRecap/Views/SyncRecapNameSelectionView.swift b/CubbitDS3Sync/Views/Sync/SyncRecap/Views/SyncRecapNameSelectionView.swift index 6f40713..67dd892 100644 --- a/CubbitDS3Sync/Views/Sync/SyncRecap/Views/SyncRecapNameSelectionView.swift +++ b/CubbitDS3Sync/Views/Sync/SyncRecap/Views/SyncRecapNameSelectionView.swift @@ -2,6 +2,7 @@ import SwiftUI struct SyncRecapNameSelectionView: View { @Environment(SyncRecapViewModel.self) var syncRecapViewModel: SyncRecapViewModel + @FocusState var focused: Bool? var onComplete: (() -> Void)? @@ -19,11 +20,18 @@ struct SyncRecapNameSelectionView: View { } set: { syncRecapViewModel.setDS3DriveName($0) } - ).onSubmit { + ) + .focused($focused, equals: true) + .onSubmit { if let ds3DriveName = syncRecapViewModel.ds3DriveName, ds3DriveName.count > 0 { onComplete?() } } + .onAppear { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.75) { + self.focused = true + } + } } .padding(.vertical, 5) diff --git a/CubbitDS3Sync/Views/Tray/ViewModels/DS3DriveViewModel.swift b/CubbitDS3Sync/Views/Tray/ViewModels/DS3DriveViewModel.swift index 0c073e9..6682250 100644 --- a/CubbitDS3Sync/Views/Tray/ViewModels/DS3DriveViewModel.swift +++ b/CubbitDS3Sync/Views/Tray/ViewModels/DS3DriveViewModel.swift @@ -79,8 +79,6 @@ import os.log updateDriveStatusNotification.driveId == self.drive.id // Only update if the notification is for this drive else { return } - self.logger.debug("Updating drive status to \(updateDriveStatusNotification.status.rawValue) for drive \(self.drive.name)") - self.driveStatus = updateDriveStatusNotification.status } diff --git a/CubbitDS3Sync/Views/Tray/Views/TrayMenuView.swift b/CubbitDS3Sync/Views/Tray/Views/TrayMenuView.swift index aab16ef..f2fd8ae 100644 --- a/CubbitDS3Sync/Views/Tray/Views/TrayMenuView.swift +++ b/CubbitDS3Sync/Views/Tray/Views/TrayMenuView.swift @@ -60,10 +60,10 @@ struct TrayMenuView: View { NSApplication.shared.terminate(self) } - Divider() - Spacer() + Divider() + TrayMenuFooterView( status: appStatusManager.status.toString(), version: DefaultSettings.appVersion @@ -71,9 +71,8 @@ struct TrayMenuView: View { } } .frame( - minWidth: 280, - maxWidth: 280, - maxHeight: .infinity + minWidth: 310, + maxWidth: 310 ) .fixedSize(horizontal: true, vertical: false) diff --git a/Provider/S3Enumerator.swift b/Provider/S3Enumerator.swift index 6b72119..860b859 100644 --- a/Provider/S3Enumerator.swift +++ b/Provider/S3Enumerator.swift @@ -90,7 +90,6 @@ class S3Enumerator: NSObject, NSFileProviderEnumerator { var page: NSFileProviderPage? = nil if continuationToken != nil { - self.logger.debug("Continuation token found \(continuationToken!). Creating new page for enumeration") page = NSFileProviderPage(continuationToken!) } diff --git a/Provider/S3Item.swift b/Provider/S3Item.swift index c4fc53e..ccbee9d 100644 --- a/Provider/S3Item.swift +++ b/Provider/S3Item.swift @@ -20,7 +20,6 @@ class S3Item: NSObject, NSFileProviderItem { drive: DS3Drive, objectMetadata: S3Item.Metadata ) { - self.metadata = objectMetadata self.drive = drive @@ -31,7 +30,10 @@ class S3Item: NSObject, NSFileProviderItem { } } - init(from item: NSFileProviderItem, drive: DS3Drive) { + init( + from item: NSFileProviderItem, + drive: DS3Drive + ) { self.identifier = item.itemIdentifier self.drive = drive self.metadata = S3Item.Metadata( @@ -47,7 +49,9 @@ class S3Item: NSObject, NSFileProviderItem { var parentItemIdentifier: NSFileProviderItemIdentifier { var pathSegments = self.identifier.rawValue.split(separator: self.separator) - if pathSegments.count == 2 { + let prefixSegmentsCount = (self.drive.syncAnchor.prefix?.split(separator: self.separator) ?? []).count + + if pathSegments.count == prefixSegmentsCount + 1 { // NOTE: e.g. parent of prefix/folder/ is prefix/ (remember prefix == .rootContainer) return .rootContainer } diff --git a/Provider/S3Lib.swift b/Provider/S3Lib.swift index 1c7f82a..61c1102 100644 --- a/Provider/S3Lib.swift +++ b/Provider/S3Lib.swift @@ -85,7 +85,7 @@ class S3Lib { // NOTE: Skipping the prefix itself as we don't want the folder root to be listed continue } - + let s3Item = S3Item( identifier: NSFileProviderItemIdentifier(key), drive: drive, @@ -110,6 +110,8 @@ class S3Lib { } } + self.logger.debug("Listed \(items.count) items") + guard let isTruncated = response.isTruncated else { throw EnumeratorError.missingParameters }