├── .crowdin.yml ├── .github ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug.yml │ ├── config.yml │ └── feature.yml ├── SECURITY.md ├── SUPPORT.md └── workflows │ ├── build.yml │ ├── no-response.yml │ └── stale.yml ├── .gitignore ├── .periphery.yml ├── .swiftformat ├── .swiftlint.yml ├── Cryptomator.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ ├── WorkspaceSettings.xcsettings │ │ └── swiftpm │ │ └── Package.resolved └── xcshareddata │ └── xcschemes │ ├── AllTests.xcscheme │ ├── Cryptomator.xcscheme │ ├── CryptomatorFileProvider.xcscheme │ ├── CryptomatorIntents.xcscheme │ ├── FileProviderExtension.xcscheme │ ├── FileProviderExtensionUI.xcscheme │ └── Snapshots.xcscheme ├── Cryptomator ├── AddVault │ ├── AddVaultCoordinator.swift │ ├── AddVaultSuccesing.swift │ ├── AddVaultSuccessCoordinator.swift │ ├── AddVaultSuccessViewController.swift │ ├── AddVaultSuccessViewModel.swift │ ├── AddVaultViewController.swift │ ├── ChooseCloudViewController.swift │ ├── ChooseCloudViewModel.swift │ ├── CloudCell.swift │ ├── CloudChoosing.swift │ ├── CreateNewVault │ │ ├── CreateNewVaultChooseFolderViewController.swift │ │ ├── CreateNewVaultChooseFolderViewModel.swift │ │ ├── CreateNewVaultCoordinator.swift │ │ ├── CreateNewVaultPasswordViewController.swift │ │ ├── CreateNewVaultPasswordViewModel.swift │ │ ├── DetectedVaultFailureView.swift │ │ ├── DetectedVaultFailureViewController.swift │ │ ├── LocalVault │ │ │ ├── CreateNewLocalVaultCoordinator.swift │ │ │ └── CreateNewLocalVaultViewModel.swift │ │ ├── SetVaultNameViewController.swift │ │ ├── SetVaultNameViewModel.swift │ │ └── VaultNaming.swift │ ├── Hub │ │ └── HubAddVaultCoordinator.swift │ ├── LocalVault │ │ ├── AddLocalVaultViewController.swift │ │ ├── LocalFileSystemAuthenticating.swift │ │ ├── LocalFileSystemAuthenticationViewController.swift │ │ ├── LocalFileSystemAuthenticationViewModel.swift │ │ └── LocalVaultAdding.swift │ ├── OpenExistingVault │ │ ├── LocalVault │ │ │ ├── OpenExistingLocalVaultCoordinator.swift │ │ │ └── OpenExistingLocalVaultViewModel.swift │ │ ├── OpenExistingLegacyVaultPasswordViewModel.swift │ │ ├── OpenExistingVaultChooseFolderViewController.swift │ │ ├── OpenExistingVaultCoordinator.swift │ │ ├── OpenExistingVaultPasswordViewController.swift │ │ └── OpenExistingVaultPasswordViewModel.swift │ ├── VaultCoordinatorError.swift │ ├── VaultInstallationCoordinator.swift │ └── VaultInstalling.swift ├── AppDelegate.swift ├── Base.lproj │ └── LaunchScreen.storyboard ├── Common │ ├── ActionButton.swift │ ├── AutoHidingLabel.swift │ ├── BaseNavigationController.swift │ ├── BaseUITableViewController.swift │ ├── Bindable.swift │ ├── Cells │ │ ├── BindableTableViewCellViewModel.swift │ │ ├── ButtonCellViewModel.swift │ │ ├── CheckMarkCell.swift │ │ ├── LoadingButtonCell.swift │ │ ├── LoadingButtonCellViewModel.swift │ │ ├── LoadingCell.swift │ │ ├── LoadingWithLabelCell.swift │ │ ├── LoadingWithLabelCellViewModel.swift │ │ ├── PasswordFieldCell.swift │ │ ├── ReturnButtonSupport.swift │ │ ├── SwitchCell.swift │ │ ├── SwitchCellViewModel.swift │ │ ├── SystemSymbolButtonCell.swift │ │ ├── SystemSymbolButtonCellViewModel.swift │ │ ├── TableViewCell.swift │ │ ├── TextFieldCell.swift │ │ ├── TextFieldCellViewModel.swift │ │ ├── URLFieldCell.swift │ │ └── UsernameFieldCell.swift │ ├── ChildCoordinator.swift │ ├── ChooseFolder │ │ ├── ChooseFolderViewController.swift │ │ ├── ChooseFolderViewModel.swift │ │ ├── CloudItemCell.swift │ │ ├── CreateNewFolderViewController.swift │ │ ├── CreateNewFolderViewModel.swift │ │ ├── FileCell.swift │ │ ├── FolderCell.swift │ │ ├── FolderChoosing.swift │ │ └── FolderCreating.swift │ ├── CloudAccountList │ │ ├── AccountCell.swift │ │ ├── AccountCellContent.swift │ │ ├── AccountInfo.swift │ │ ├── AccountListPosition.swift │ │ ├── AccountListViewController.swift │ │ ├── AccountListViewModel.swift │ │ └── AccountListing.swift │ ├── CloudAuthenticator.swift │ ├── CloudProviderType+Localization.swift │ ├── Combine │ │ ├── Publisher+OptionalAssign.swift │ │ ├── UIControl+Publisher.swift │ │ └── UISwitch+Publisher.swift │ ├── DatabaseManager.swift │ ├── DefaultShowEditAccountBehavior.swift │ ├── EditableDataSource.swift │ ├── EditableTableViewHeader.swift │ ├── EmptyListMessage.swift │ ├── FilesAppUtil.swift │ ├── HeaderFooter │ │ ├── AttributedTextHeaderFooterView.swift │ │ ├── AttributedTextHeaderFooterViewModel.swift │ │ ├── BaseHeaderFooterView.swift │ │ ├── BindableAttributedTextHeaderFooterViewModel.swift │ │ └── HeaderFooterViewModel.swift │ ├── ListViewController.swift │ ├── ListViewModel.swift │ ├── LocalWeb │ │ ├── LocalWebViewController.swift │ │ └── LocalWebViewModel.swift │ ├── MaintenanceModeError+Localization.swift │ ├── NSAttributedString+Extension.swift │ ├── PoppingCloseCoordinator.swift │ ├── Previews │ │ ├── UIView+Preview.swift │ │ └── UIViewController+Preview.swift │ ├── SingleSectionTableViewController.swift │ ├── StaticUITableViewController.swift │ ├── TableViewModel.swift │ ├── UIImage+CloudProviderType.swift │ ├── UIViewController+ProgressHUDError.swift │ ├── URL+Zip.swift │ ├── VaultDetailItem.swift │ └── VaultDetector.swift ├── Cryptomator.entitlements ├── Info.plist ├── MainCoordinator.swift ├── MicrosoftGraph │ ├── EnterSharePointURLViewController.swift │ ├── EnterSharePointURLViewModel.swift │ ├── MicrosoftGraphAuthenticatorError+Localization.swift │ ├── OneDriveAuthenticator.swift │ ├── SharePointAuthenticating.swift │ ├── SharePointAuthenticationCoordinator.swift │ ├── SharePointAuthenticator.swift │ ├── SharePointCredential.swift │ ├── SharePointDriveListViewController.swift │ ├── SharePointDriveListViewModel.swift │ └── SharePointURLValidationError+Localization.swift ├── Onboarding │ ├── OnboardingCoordinator.swift │ ├── OnboardingNavigationController.swift │ ├── OnboardingViewController.swift │ └── OnboardingViewModel.swift ├── Purchase │ ├── Cells │ │ ├── DisclosureCell.swift │ │ ├── IAPCell.swift │ │ ├── PurchaseCell.swift │ │ └── TrialCell.swift │ ├── IAPHeaderView.swift │ ├── IAPViewController.swift │ ├── PremiumManager.swift │ ├── PurchaseAlert.swift │ ├── PurchaseCoordinator.swift │ ├── PurchaseFooterView.swift │ ├── PurchaseViewController.swift │ ├── PurchaseViewModel.swift │ ├── SKProduct+LocalizedPrice.swift │ ├── SalePromo.swift │ ├── StoreManager.swift │ ├── StoreObserver.swift │ ├── TrialExpiredCoordinator.swift │ ├── TrialExpiredNavigationController.swift │ └── UpgradeViewModel.swift ├── Resources │ ├── about.html │ ├── jquery-3.6.0.slim.min.js │ └── style.css ├── S3 │ ├── S3Authenticating.swift │ ├── S3AuthenticationView.swift │ ├── S3AuthenticationViewController.swift │ ├── S3AuthenticationViewModel.swift │ ├── S3Authenticator+VC.swift │ └── S3CredentialVerifier.swift ├── Settings │ ├── About │ │ ├── AboutCoordinator.swift │ │ └── AboutViewModel.swift │ ├── SettingsCoordinator.swift │ ├── SettingsViewController.swift │ └── SettingsViewModel.swift ├── Snapshots │ ├── SnapshotCoordinator.swift │ └── SnapshotVaultListViewModel.swift ├── VaultDetail │ ├── ChangePassword │ │ ├── ChangePasswordViewController.swift │ │ ├── ChangePasswordViewModel.swift │ │ └── VaultPasswordChanging.swift │ ├── KeepUnlocked │ │ ├── KeepUnlockedSectionFooterViewModel.swift │ │ ├── VaultKeepUnlockedViewController.swift │ │ └── VaultKeepUnlockedViewModel.swift │ ├── MoveVault │ │ ├── MoveVaultCoordinator.swift │ │ ├── MoveVaultViewController.swift │ │ └── MoveVaultViewModel.swift │ ├── RenameVault │ │ ├── RenameVaultViewController.swift │ │ └── RenameVaultViewModel.swift │ ├── UnlockSectionFooterViewModel.swift │ ├── VaultDetailCoordinator.swift │ ├── VaultDetailInfoFooterViewModel.swift │ ├── VaultDetailUnlockCoordinator.swift │ ├── VaultDetailUnlockVaultViewController.swift │ ├── VaultDetailUnlockVaultViewModel.swift │ ├── VaultDetailViewController.swift │ ├── VaultDetailViewModel.swift │ └── VaultPasswordVerifying.swift ├── VaultList │ ├── VaultCell.swift │ ├── VaultCellViewModel.swift │ ├── VaultInfo.swift │ ├── VaultListPosition.swift │ ├── VaultListViewController.swift │ └── VaultListViewModel.swift └── WebDAV │ ├── TLSCertificateValidationHelper.swift │ ├── WebDAVAuthenticating.swift │ ├── WebDAVAuthentication.swift │ ├── WebDAVAuthenticationCoordinator.swift │ ├── WebDAVAuthenticationViewController.swift │ ├── WebDAVAuthenticationViewModel.swift │ ├── WebDAVAuthenticator+VC.swift │ └── WebDAVCredentialCoordinator.swift ├── CryptomatorCommon ├── .swiftpm │ └── xcode │ │ ├── package.xcworkspace │ │ └── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── xcschemes │ │ ├── CryptomatorCommon.xcscheme │ │ └── CryptomatorCommonCore.xcscheme ├── Package.swift ├── Sources │ ├── CryptomatorCommon │ │ └── CryptomatorHubAuthenticator+HubAuthenticating.swift │ └── CryptomatorCommonCore │ │ ├── Box │ │ └── BoxTokenStorage.swift │ │ ├── CloudPath+Contains.swift │ │ ├── Coordinator.swift │ │ ├── CryptoBotHeaderFooterView.swift │ │ ├── CryptomatorConstants.swift │ │ ├── CryptomatorDatabase.swift │ │ ├── CryptomatorErrorView.swift │ │ ├── CryptomatorKeychain.swift │ │ ├── CryptomatorSimpleButtonView.swift │ │ ├── CryptomatorUserDefaults.swift │ │ ├── FileProviderXPC │ │ ├── CacheManaging.swift │ │ ├── FileImporting.swift │ │ ├── FileProviderConnector.swift │ │ ├── LogLevelUpdating.swift │ │ ├── MaintenanceModeHelper.swift │ │ ├── UploadRetrying.swift │ │ ├── VaultLocking.swift │ │ ├── VaultUnlocking.swift │ │ └── XPCErrorHelper.swift │ │ ├── FullVersionChecker.swift │ │ ├── Hub │ │ ├── CryptomatorHubAuthenticator.swift │ │ ├── CryptomatorHubKeyProvider.swift │ │ ├── HubAuthenticating.swift │ │ ├── HubAuthenticationCoordinator.swift │ │ ├── HubAuthenticationFlowDelegate.swift │ │ ├── HubAuthenticationView.swift │ │ ├── HubAuthenticationViewController.swift │ │ ├── HubAuthenticationViewModel.swift │ │ ├── HubDeviceRegisteringService.swift │ │ ├── HubDeviceRegistrationView.swift │ │ ├── HubErrorWithRefreshView.swift │ │ ├── HubKeyService.swift │ │ ├── HubRepository.swift │ │ ├── HubSubscriptionState.swift │ │ ├── HubUserAuthenticator.swift │ │ ├── HubUserLogin.swift │ │ ├── HubXPCLoginCoordinator.swift │ │ └── UnlockHandler │ │ │ ├── AddHubVaultUnlockHandler.swift │ │ │ ├── HubVaultUnlockHandler.swift │ │ │ └── HubXPCVaultUnlockHandler.swift │ │ ├── ItemNameValidator.swift │ │ ├── JWEHelper.swift │ │ ├── KeepUnlockedDuration.swift │ │ ├── LargeHeaderFooterView.swift │ │ ├── LocalAuthentication+Localization.swift │ │ ├── LocalFileSystem │ │ └── LocalFileSystemBookmarkManager.swift │ │ ├── LocalizedCloudProviderDecorator.swift │ │ ├── LocalizedCloudProviderError.swift │ │ ├── LocalizedString.swift │ │ ├── LoggerSetup.swift │ │ ├── Manager │ │ ├── CloudProviderAccountDBManager.swift │ │ ├── CloudProviderDBManager.swift │ │ ├── CloudProviderType.swift │ │ ├── ExistingHubVault.swift │ │ ├── MasterkeyCacheManager.swift │ │ ├── VaultAccountDBManager.swift │ │ ├── VaultDBCache.swift │ │ ├── VaultDBManager.swift │ │ ├── VaultKeepUnlockedManager.swift │ │ └── VaultPasswordManager.swift │ │ ├── MicrosoftGraph │ │ └── MicrosoftGraphAccountDBManager.swift │ │ ├── Mocks │ │ ├── CacheManagingMock.swift │ │ ├── CloudProviderMock.swift │ │ ├── CloudProviderUpdatingMock.swift │ │ ├── CryptomatorKeychainMock.swift │ │ ├── CryptomatorSettingsMock.swift │ │ ├── FileProviderConnectorMock.swift │ │ ├── FullVersionCheckerMock.swift │ │ ├── HubRepositoryMock.swift │ │ ├── MaintenanceModeHelperMock.swift │ │ ├── MasterkeyCacheHelperMock.swift │ │ ├── MasterkeyCacheManagerMock.swift │ │ ├── S3CredentialManagerMock.swift │ │ ├── UpgradeCheckerMock.swift │ │ ├── VaultCacheMock.swift │ │ ├── VaultKeepUnlockedHelperMock.swift │ │ ├── VaultKeepUnlockedSettingsMock.swift │ │ ├── VaultManagerMock.swift │ │ ├── VaultPasswordManagerMock.swift │ │ └── WebDAVCredentialManagerMock.swift │ │ ├── NSLayoutConstraint+Extensions.swift │ │ ├── PCloud │ │ └── PCloudCredential+Keychain.swift │ │ ├── ProgressHUD.swift │ │ ├── Promise+AllIgnoringResult.swift │ │ ├── Promise+StructuredConcurrency.swift │ │ ├── S3 │ │ ├── CryptomatorKeychain+S3.swift │ │ └── S3CredentialManager.swift │ │ ├── SwiftUI │ │ ├── SwiftUI+CustomKeyboard.swift │ │ ├── SwiftUI+Focus.swift │ │ └── SwiftUI+ListBackground.swift │ │ ├── UIColor+CryptomatorColors.swift │ │ ├── UIView+Shaking.swift │ │ ├── URLSessionError+Localization.swift │ │ ├── UpgradeChecker.swift │ │ ├── VaultAccountManagerError+Localization.swift │ │ ├── VaultItem.swift │ │ ├── VaultProviderFactory+Localization.swift │ │ └── WebDAV │ │ ├── WebDAVAuthenticator+Keychain.swift │ │ └── WebDAVAuthenticatorError+Localization.swift └── Tests │ └── CryptomatorCommonCoreTests │ ├── FullVersionCheckerTests.swift │ ├── Hub │ ├── AddHubVaultUnlockHandlerTests.swift │ ├── HubAuthenticationViewModelTests.swift │ ├── HubDBRepositoryTests.swift │ ├── HubVaultUnlockHandlerDelegateMock.swift │ └── JWEHelperTests.swift │ ├── ItemNameValidatorTests.swift │ ├── Manager │ ├── CloudProviderAccountManagerTests.swift │ ├── CloudProviderManagerTests.swift │ ├── MasterkeyCacheKeychainManagerTests.swift │ ├── S3CredentialManagerTests.swift │ ├── VaultDBCacheTests.swift │ ├── VaultKeepUnlockedManagerTests.swift │ └── VaultManagerTests.swift │ ├── Promise+AllIgnoringResultsTests.swift │ └── XCTestCase+Promises.swift ├── CryptomatorCommonHostedTests ├── Info.plist └── Keychain │ ├── PCloudKeychainTests.swift │ ├── VaultPasswordKeychainManagerTests.swift │ └── WebDAVKeychainTests.swift ├── CryptomatorFileProvider ├── Actions │ └── FileProviderAction.swift ├── CachedFileManagerFactory.swift ├── CloudPath+GetParent.swift ├── CloudPath+NameCollision.swift ├── CloudTask │ ├── CloudTask.swift │ ├── DeletionTask.swift │ ├── DownloadTask.swift │ ├── FolderCreationTask.swift │ ├── ItemEnumerationTask.swift │ ├── ReparentTask.swift │ └── UploadTask.swift ├── CryptomatorFileProvider.h ├── DB │ ├── CachedFileDBManager.swift │ ├── DBManagerError.swift │ ├── DatabaseHelper.swift │ ├── DeletionTaskDBManager.swift │ ├── DeletionTaskRecord.swift │ ├── DownloadTaskDBManager.swift │ ├── DownloadTaskRecord.swift │ ├── ItemEnumerationTaskDBManager.swift │ ├── ItemEnumerationTaskRecord.swift │ ├── ItemMetadata.swift │ ├── ItemMetadataDBManager.swift │ ├── LocalCachedFileInfo.swift │ ├── MaintenanceDBManager.swift │ ├── ReparentTaskDBManager.swift │ ├── ReparentTaskRecord.swift │ ├── TaskError.swift │ ├── UploadTaskDBManager.swift │ ├── UploadTaskRecord.swift │ └── WorkingSetObserver.swift ├── DatabaseURLProvider.swift ├── DeleteItemHelper.swift ├── DocumentStorageURLProvider.swift ├── ErrorWrapper.swift ├── FileProviderAdapter.swift ├── FileProviderAdapterError.swift ├── FileProviderAdapterManager.swift ├── FileProviderEnumerator.swift ├── FileProviderItem.swift ├── FileProviderItemList.swift ├── FileProviderNotificator.swift ├── FileProviderNotificatorManager.swift ├── ItemStatus.swift ├── LocalURLProviderType.swift ├── Locks │ ├── FileSystemLock.swift │ ├── LockManager.swift │ ├── LockNode.swift │ └── RWLock.swift ├── Middleware │ ├── ErrorMapper.swift │ ├── OnlineItemNameCollisionHandler.swift │ ├── TaskExecutor │ │ ├── DeletionTaskExecutor.swift │ │ ├── DownloadTaskExecutor.swift │ │ ├── FolderCreationTaskExecutor.swift │ │ ├── ItemEnumerationTaskExecutor.swift │ │ ├── ReparentTaskExecutor.swift │ │ └── UploadTaskExecutor.swift │ └── WorkflowMiddleware.swift ├── NSFileProviderDomainProvider.swift ├── NSFileProviderItemIdentifier+Database.swift ├── PermissionProvider.swift ├── ProgressManager.swift ├── RootFileProviderItem.swift ├── ServiceSource │ ├── CacheManagingServiceSource.swift │ ├── FileImportingServiceSource.swift │ ├── LogLevelUpdatingServiceSource.swift │ ├── MaintenanceModeHelperServiceSource.swift │ ├── ServiceSource.swift │ ├── UploadRetryingServiceSource.swift │ ├── VaultLockingServiceSource.swift │ └── VaultUnlockingServiceSource.swift ├── SessionTaskRegistrator.swift ├── URL+NameCollisionExtension.swift ├── UnlockMonitor.swift ├── VaultUnlockingServiceSource.swift └── Workflow │ ├── Workflow.swift │ ├── WorkflowConstraint.swift │ ├── WorkflowDependencyFactory.swift │ ├── WorkflowDependencyMiddleware.swift │ ├── WorkflowDependencyTaskCollection.swift │ ├── WorkflowFactory.swift │ ├── WorkflowFactoryLocking.swift │ └── WorkflowScheduler.swift ├── CryptomatorFileProviderTests ├── CloudPath+NameCollision.swift ├── DB │ ├── CachedFileManagerTests.swift │ ├── DeletionTaskManagerTests.swift │ ├── DownloadTaskManagerTests.swift │ ├── ItemEnumerationTaskManagerTests.swift │ ├── MaintenanceManagerTests.swift │ ├── MetadataManagerTests.swift │ ├── ReparentTaskManagerTests.swift │ └── UploadTaskManagerTests.swift ├── FileImportingServiceSourceTests.swift ├── FileProviderAdapter │ ├── FileProviderAdapterCreateDirectoryTests.swift │ ├── FileProviderAdapterDeleteItemTests.swift │ ├── FileProviderAdapterEnumerateItemTests.swift │ ├── FileProviderAdapterGetItemIdentifierTests.swift │ ├── FileProviderAdapterGetItemTests.swift │ ├── FileProviderAdapterImportDirectoryTests.swift │ ├── FileProviderAdapterImportDocumentTests.swift │ ├── FileProviderAdapterMoveItemTests.swift │ ├── FileProviderAdapterSetFavoriteRankTests.swift │ ├── FileProviderAdapterSetTagDataTests.swift │ ├── FileProviderAdapterStartProvidingItemRestrictedVersionTests.swift │ ├── FileProviderAdapterStartProvidingItemTests.swift │ └── FileProviderAdapterTestCase.swift ├── FileProviderAdapterManagerTests.swift ├── FileProviderEnumeratorTests.swift ├── FileProviderItemTests.swift ├── FileProviderNotificatorTests.swift ├── InMemoryProgressManagerTests.swift ├── Info.plist ├── LocalURLProviderTests.swift ├── Middleware │ ├── ErrorMapperTests.swift │ ├── OnlineItemNameCollisionHandlerTests.swift │ ├── TaskExecutor │ │ ├── CloudTaskExecutorTestCase.swift │ │ ├── DeletionTaskExecutorTests.swift │ │ ├── DownloadTaskExecutorTests.swift │ │ ├── FolderCreationTaskExecutorTests.swift │ │ ├── ItemEnumerationTaskTests.swift │ │ ├── ReparentTaskExecutorTests.swift │ │ └── UploadTaskExecutorTests.swift │ └── WorkflowMiddlewareMock.swift ├── Mocks │ ├── CacheManagerMock.swift │ ├── CachedFileManagerFactoryMock.swift │ ├── CloudProviderPaginationMock.swift │ ├── CustomCloudProviderMock.swift │ ├── CustomCloudProviderMockTests.swift │ ├── DocumentStorageURLProviderMock.swift │ ├── EnumerationSignalingMock.swift │ ├── FileProviderAdapterCacheTypeMock.swift │ ├── FileProviderAdapterProvidingMock.swift │ ├── FileProviderAdapterTypeMock.swift │ ├── FileProviderItemUpdateDelegateMock.swift │ ├── FileProviderNotificatorManagerMock.swift │ ├── FileProviderNotificatorMock.swift │ ├── LocalURLProviderMock.swift │ ├── MaintenanceManagerMock.swift │ ├── NSFileProviderChangeObserverMock.swift │ ├── NSFileProviderDomainProviderMock.swift │ ├── NSFileProviderEnumerationObserverMock.swift │ ├── PermissionProviderMock.swift │ ├── ProgressManagerMock.swift │ ├── SessionTaskRegistratorMock.swift │ ├── UnlockMonitorTaskExecutorMock.swift │ ├── UploadTaskManagerMock.swift │ ├── WorkflowDependencyTasksCollectionMock.swift │ └── WorkingSetObservingMock.swift ├── PermissionProviderImplTests.swift ├── ServiceSource │ ├── CacheManagingServiceSourceTests.swift │ ├── LogLevelUpdatingServiceSourceTests.swift │ └── UploadRetryingServiceSourceTests.swift ├── URL+NameCollisionExtensionTests.swift ├── UnlockMonitorTests.swift ├── WorkflowDependencyFactoryTests.swift ├── WorkingSetEnumerationTests.swift ├── WorkingSetObserverTests.swift └── XCTestCase+Promises.swift ├── CryptomatorIntents ├── Base.lproj │ └── Intents.intentdefinition ├── Common │ └── VaultOptionsProvider.swift ├── CryptomatorIntents.entitlements ├── GetFolderIntentHandler.swift ├── GetFolderIntentHandlerError.swift ├── Info.plist ├── IntentHandler.swift ├── IsVaultUnlockedIntentHandler.swift ├── LockVaultIntentHandler.swift ├── OpenVaultIntentHandler.swift ├── SaveFileIntentHandler.swift ├── af.lproj │ └── Intents.strings ├── ar.lproj │ └── Intents.strings ├── ba.lproj │ └── Intents.strings ├── be.lproj │ └── Intents.strings ├── bg.lproj │ └── Intents.strings ├── bn.lproj │ └── Intents.strings ├── bs.lproj │ └── Intents.strings ├── ca.lproj │ └── Intents.strings ├── cs.lproj │ └── Intents.strings ├── da.lproj │ └── Intents.strings ├── de.lproj │ └── Intents.strings ├── el.lproj │ └── Intents.strings ├── en.lproj │ └── Intents.strings ├── es.lproj │ └── Intents.strings ├── fa.lproj │ └── Intents.strings ├── fi.lproj │ └── Intents.strings ├── fil.lproj │ └── Intents.strings ├── fr.lproj │ └── Intents.strings ├── gl.lproj │ └── Intents.strings ├── he.lproj │ └── Intents.strings ├── hi.lproj │ └── Intents.strings ├── hr.lproj │ └── Intents.strings ├── hu.lproj │ └── Intents.strings ├── id.lproj │ └── Intents.strings ├── it.lproj │ └── Intents.strings ├── ja.lproj │ └── Intents.strings ├── ko.lproj │ └── Intents.strings ├── lv.lproj │ └── Intents.strings ├── mk.lproj │ └── Intents.strings ├── mr.lproj │ └── Intents.strings ├── nb.lproj │ └── Intents.strings ├── nl.lproj │ └── Intents.strings ├── nn-NO.lproj │ └── Intents.strings ├── no.lproj │ └── Intents.strings ├── pa.lproj │ └── Intents.strings ├── pl.lproj │ └── Intents.strings ├── pt-BR.lproj │ └── Intents.strings ├── pt.lproj │ └── Intents.strings ├── ro.lproj │ └── Intents.strings ├── ru.lproj │ └── Intents.strings ├── si.lproj │ └── Intents.strings ├── sk.lproj │ └── Intents.strings ├── sl.lproj │ └── Intents.strings ├── sr-Latn.lproj │ └── Intents.strings ├── sr.lproj │ └── Intents.strings ├── sv.lproj │ └── Intents.strings ├── sw-TZ.lproj │ └── Intents.strings ├── ta.lproj │ └── Intents.strings ├── te.lproj │ └── Intents.strings ├── th.lproj │ └── Intents.strings ├── tr.lproj │ └── Intents.strings ├── ug.lproj │ └── Intents.strings ├── uk.lproj │ └── Intents.strings ├── ur.lproj │ └── Intents.strings ├── vi.lproj │ └── Intents.strings ├── zh-HK.lproj │ └── Intents.strings ├── zh-Hans.lproj │ └── Intents.strings └── zh-Hant.lproj │ └── Intents.strings ├── CryptomatorTests ├── AccountListViewModelTests.swift ├── AddLocalVault │ ├── AddLocalVaultViewModelTestCase.swift │ ├── CreateNewLocalVaultViewModelTests.swift │ └── OpenExistingLocalVaultViewModelTests.swift ├── ChangePasswordViewModelTests.swift ├── CreateNewFolderViewModelTests.swift ├── CreateNewVaultPasswordViewModelTests.swift ├── DatabaseManagerTests.swift ├── FileProviderConnectorMock.swift ├── Info.plist ├── MockError.swift ├── Mocks │ ├── IAPManagerMock.swift │ ├── IAPStoreMock.swift │ ├── PremiumManagerMock.swift │ ├── S3CredentialVerifierMock.swift │ └── TLSCertificateValidationHelperMock.swift ├── MoveVaultViewModelTests.swift ├── Purchase │ ├── IAPViewModelTestCase.swift │ ├── PurchaseViewModelTests.swift │ ├── StoreObserverTests.swift │ └── UpgradeViewModelTests.swift ├── RenameVaultViewModelTests.swift ├── S3AuthenticationViewModelTests.swift ├── SetVaultNameViewModelTests.swift ├── SettingsViewModelTests.swift ├── VaultKeepUnlockedViewModelTests.swift ├── VaultListViewModelTests.swift ├── WebDAVAuthenticationViewModelTests.swift ├── XCTest+Async.swift ├── XCTest+Combine.swift └── XCTestCase+Promises.swift ├── FileProviderExtension ├── FileProvider+Actions.swift ├── FileProviderExtension-Bridging-Header.h ├── FileProviderExtension.entitlements ├── FileProviderExtension.swift ├── FileProviderValidationServiceSource.h ├── FileProviderValidationServiceSource.m ├── Info.plist └── Snapshots │ ├── FileProviderEnumeratorSnapshotMock.swift │ └── VaultUnlockingServiceSourceSnapshotMock.swift ├── FileProviderExtensionUI ├── FileProviderCoordinator.swift ├── FileProviderCoordinatorError.swift ├── FileProviderExtensionUI.entitlements ├── Info.plist ├── OnboardingViewController.swift ├── RootViewController.swift ├── Snapshots │ └── FileProviderCoordinatorSnapshotMock.swift ├── UnauthorizedErrorViewController.swift ├── UnlockVaultViewController.swift ├── UnlockVaultViewModel.swift └── UploadProgressAlertController.swift ├── Gemfile ├── Gemfile.lock ├── LICENSE.txt ├── README.md ├── Scripts ├── git-format-staged.py └── process.sh ├── SharedResources ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── DarkIcon.png │ │ ├── LightIcon.png │ │ └── TintedIcon.png │ ├── Contents.json │ ├── bot-vault.imageset │ │ ├── Contents.json │ │ ├── bot-vault.png │ │ ├── bot-vault@2x.png │ │ └── bot-vault@3x.png │ ├── bot.imageset │ │ ├── Contents.json │ │ ├── bot.png │ │ ├── bot@2x.png │ │ └── bot@3x.png │ ├── box-vault-selected.imageset │ │ ├── Contents.json │ │ ├── box-vault-selected.png │ │ ├── box-vault-selected@2x.png │ │ └── box-vault-selected@3x.png │ ├── box-vault.imageset │ │ ├── Contents.json │ │ ├── box-vault.png │ │ ├── box-vault@2x.png │ │ └── box-vault@3x.png │ ├── box.imageset │ │ ├── Contents.json │ │ ├── box.png │ │ ├── box@2.png │ │ └── box@3.png │ ├── dropbox-vault-selected.imageset │ │ ├── Contents.json │ │ ├── dropbox-vault-selected.png │ │ ├── dropbox-vault-selected@2x.png │ │ └── dropbox-vault-selected@3x.png │ ├── dropbox-vault.imageset │ │ ├── Contents.json │ │ ├── dropbox-vault.png │ │ ├── dropbox-vault@2x.png │ │ └── dropbox-vault@3x.png │ ├── dropbox.imageset │ │ ├── Contents.json │ │ ├── dropbox.png │ │ ├── dropbox@2x.png │ │ └── dropbox@3x.png │ ├── file-provider-vault-selected.imageset │ │ ├── Contents.json │ │ ├── file-provider-vault-selected.png │ │ ├── file-provider-vault-selected@2x.png │ │ └── file-provider-vault-selected@3x.png │ ├── file-provider-vault.imageset │ │ ├── Contents.json │ │ ├── file-provider-vault.png │ │ ├── file-provider-vault@2x.png │ │ └── file-provider-vault@3x.png │ ├── file-provider.imageset │ │ ├── Contents.json │ │ ├── file-provider.png │ │ ├── file-provider@2x.png │ │ └── file-provider@3x.png │ ├── google-drive-vault-selected.imageset │ │ ├── Contents.json │ │ ├── google-drive-vault-selected.png │ │ ├── google-drive-vault-selected@2x.png │ │ └── google-drive-vault-selected@3x.png │ ├── google-drive-vault.imageset │ │ ├── Contents.json │ │ ├── google-drive-vault.png │ │ ├── google-drive-vault@2x.png │ │ └── google-drive-vault@3x.png │ ├── google-drive.imageset │ │ ├── Contents.json │ │ ├── google-drive.png │ │ ├── google-drive@2x.png │ │ └── google-drive@3x.png │ ├── icloud-drive-vault-selected.imageset │ │ ├── Contents.json │ │ ├── icloud-drive-vault-selected.png │ │ ├── icloud-drive-vault-selected@2x.png │ │ └── icloud-drive-vault-selected@3x.png │ ├── icloud-drive-vault.imageset │ │ ├── Contents.json │ │ ├── icloud-drive-vault.png │ │ ├── icloud-drive-vault@2x.png │ │ └── icloud-drive-vault@3x.png │ ├── icloud-drive.imageset │ │ ├── Contents.json │ │ ├── icloud-drive.png │ │ ├── icloud-drive@2x.png │ │ └── icloud-drive@3x.png │ ├── onedrive-vault-selected.imageset │ │ ├── Contents.json │ │ ├── onedrive-vault-selected.png │ │ ├── onedrive-vault-selected@2x.png │ │ └── onedrive-vault-selected@3x.png │ ├── onedrive-vault.imageset │ │ ├── Contents.json │ │ ├── onedrive-vault.png │ │ ├── onedrive-vault@2x.png │ │ └── onedrive-vault@3x.png │ ├── onedrive.imageset │ │ ├── Contents.json │ │ ├── onedrive.png │ │ ├── onedrive@2x.png │ │ └── onedrive@3x.png │ ├── pcloud-vault-selected.imageset │ │ ├── Contents.json │ │ ├── pcloud-vault-selected.png │ │ ├── pcloud-vault-selected@2x.png │ │ └── pcloud-vault-selected@3x.png │ ├── pcloud-vault.imageset │ │ ├── Contents.json │ │ ├── pcloud-vault.png │ │ ├── pcloud-vault@2x.png │ │ └── pcloud-vault@3x.png │ ├── pcloud.imageset │ │ ├── Contents.json │ │ ├── pcloud.png │ │ ├── pcloud@2x.png │ │ └── pcloud@3x.png │ ├── s3-vault-selected.imageset │ │ ├── Contents.json │ │ ├── s3-vault-selected.png │ │ ├── s3-vault-selected@2x.png │ │ └── s3-vault-selected@3x.png │ ├── s3-vault.imageset │ │ ├── Contents.json │ │ ├── s3-vault.png │ │ ├── s3-vault@2x.png │ │ └── s3-vault@3x.png │ ├── s3.imageset │ │ ├── Contents.json │ │ ├── s3.png │ │ ├── s3@2x.png │ │ └── s3@3x.png │ ├── sharepoint-selected.imageset │ │ ├── Contents.json │ │ ├── sharepoint-vault-selected.png │ │ ├── sharepoint-vault-selected@2x.png │ │ └── sharepoint-vault-selected@3x.png │ ├── sharepoint-vault.imageset │ │ ├── Contents.json │ │ ├── sharepoint-vault.png │ │ ├── sharepoint-vault@2x.png │ │ └── sharepoint-vault@3x.png │ ├── sharepoint.imageset │ │ ├── Contents.json │ │ ├── sharepoint.png │ │ ├── sharepoint@2x.png │ │ └── sharepoint@3x.png │ ├── webdav-vault-selected.imageset │ │ ├── Contents.json │ │ ├── webdav-vault-selected.png │ │ ├── webdav-vault-selected@2x.png │ │ └── webdav-vault-selected@3x.png │ ├── webdav-vault.imageset │ │ ├── Contents.json │ │ ├── webdav-vault.png │ │ ├── webdav-vault@2x.png │ │ └── webdav-vault@3x.png │ └── webdav.imageset │ │ ├── Contents.json │ │ ├── webdav.png │ │ ├── webdav@2x.png │ │ └── webdav@3x.png ├── Colors.xcassets │ ├── Contents.json │ ├── background.colorset │ │ └── Contents.json │ ├── primary.colorset │ │ └── Contents.json │ └── yellow.colorset │ │ └── Contents.json ├── PrivacyInfo.xcprivacy ├── af.lproj │ └── Localizable.strings ├── ar.lproj │ └── Localizable.strings ├── ba.lproj │ └── Localizable.strings ├── be.lproj │ └── Localizable.strings ├── bg.lproj │ └── Localizable.strings ├── bn.lproj │ └── Localizable.strings ├── bs.lproj │ └── Localizable.strings ├── ca.lproj │ └── Localizable.strings ├── cs.lproj │ └── Localizable.strings ├── da.lproj │ └── Localizable.strings ├── de.lproj │ └── Localizable.strings ├── el.lproj │ └── Localizable.strings ├── en.lproj │ └── Localizable.strings ├── es.lproj │ └── Localizable.strings ├── fa.lproj │ └── Localizable.strings ├── fi.lproj │ └── Localizable.strings ├── fil.lproj │ └── Localizable.strings ├── fr.lproj │ └── Localizable.strings ├── gl.lproj │ └── Localizable.strings ├── he.lproj │ └── Localizable.strings ├── hi.lproj │ └── Localizable.strings ├── hr.lproj │ └── Localizable.strings ├── hu.lproj │ └── Localizable.strings ├── id.lproj │ └── Localizable.strings ├── it.lproj │ └── Localizable.strings ├── ja.lproj │ └── Localizable.strings ├── ko.lproj │ └── Localizable.strings ├── lv.lproj │ └── Localizable.strings ├── mk.lproj │ └── Localizable.strings ├── mr.lproj │ └── Localizable.strings ├── nb.lproj │ └── Localizable.strings ├── nl.lproj │ └── Localizable.strings ├── nn-NO.lproj │ └── Localizable.strings ├── no.lproj │ └── Localizable.strings ├── pa.lproj │ └── Localizable.strings ├── pl.lproj │ └── Localizable.strings ├── pt-BR.lproj │ └── Localizable.strings ├── pt.lproj │ └── Localizable.strings ├── ro.lproj │ └── Localizable.strings ├── ru.lproj │ └── Localizable.strings ├── si.lproj │ └── Localizable.strings ├── sk.lproj │ └── Localizable.strings ├── sl.lproj │ └── Localizable.strings ├── sr-CS.lproj │ └── Localizable.strings ├── sr-Latn.lproj │ └── Localizable.strings ├── sr.lproj │ └── Localizable.strings ├── sv.lproj │ └── Localizable.strings ├── sw-TZ.lproj │ └── Localizable.strings ├── ta.lproj │ └── Localizable.strings ├── te.lproj │ └── Localizable.strings ├── th.lproj │ └── Localizable.strings ├── tr.lproj │ └── Localizable.strings ├── ug.lproj │ └── Localizable.strings ├── uk.lproj │ └── Localizable.strings ├── ur.lproj │ └── Localizable.strings ├── vi.lproj │ └── Localizable.strings ├── zh-HK.lproj │ └── Localizable.strings ├── zh-Hans.lproj │ └── Localizable.strings └── zh-Hant.lproj │ └── Localizable.strings ├── Snapshots ├── SnapshotBiometrics.h ├── SnapshotBiometrics.m ├── SnapshotHelper.swift ├── Snapshots-Bridging-Header.h └── Snapshots.swift ├── StoreKitTestConfiguration ├── Configuration.storekit └── StoreKitTestCertificate.cer └── fastlane ├── .env.freemium ├── .env.premium ├── Appfile ├── Deliverfile ├── Fastfile ├── Gymfile ├── Matchfile ├── README.md ├── Scanfile ├── Snapfile ├── beta_app_description.txt ├── changelog.txt ├── config ├── freemium │ ├── DarkIcon.png │ ├── LightIcon.png │ ├── TintedIcon.png │ └── metadata │ │ ├── copyright.txt │ │ ├── de-DE │ │ ├── description.txt │ │ ├── marketing_url.txt │ │ ├── privacy_url.txt │ │ ├── release_notes.txt │ │ ├── subtitle.txt │ │ └── support_url.txt │ │ ├── default │ │ ├── keywords.txt │ │ └── name.txt │ │ ├── en-US │ │ ├── description.txt │ │ ├── marketing_url.txt │ │ ├── privacy_url.txt │ │ ├── release_notes.txt │ │ ├── subtitle.txt │ │ └── support_url.txt │ │ ├── primary_category.txt │ │ └── secondary_category.txt └── premium │ ├── DarkIcon.png │ ├── LightIcon.png │ ├── TintedIcon.png │ └── metadata │ ├── copyright.txt │ ├── de-DE │ ├── description.txt │ ├── marketing_url.txt │ ├── name.txt │ ├── privacy_url.txt │ ├── release_notes.txt │ ├── subtitle.txt │ └── support_url.txt │ ├── default │ └── keywords.txt │ ├── en-US │ ├── description.txt │ ├── marketing_url.txt │ ├── name.txt │ ├── privacy_url.txt │ ├── release_notes.txt │ ├── subtitle.txt │ └── support_url.txt │ ├── primary_category.txt │ └── secondary_category.txt └── scripts ├── create-app-constants.sh ├── create-app-icon.sh └── create-cloud-access-secrets.sh /.crowdin.yml: -------------------------------------------------------------------------------- 1 | commit_message: '[ci skip]' 2 | files: 3 | - source: /SharedResources/en.lproj/Localizable.strings 4 | translation: /SharedResources/%osx_code%/%original_file_name% 5 | skip_untranslated_strings: false 6 | skip_untranslated_files: true 7 | - source: /CryptomatorIntents/en.lproj/Intents.strings 8 | translation: /CryptomatorIntents/%osx_code%/%original_file_name% 9 | skip_untranslated_strings: false 10 | skip_untranslated_files: true 11 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [cryptomator] 2 | custom: https://cryptomator.org/sponsors/ 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Help & Support 4 | url: https://community.cryptomator.org/ 5 | about: You will find answers in our community forum 6 | - name: User Manual 7 | url: https://docs.cryptomator.org/ 8 | about: Read the Cryptomator documentation here 9 | -------------------------------------------------------------------------------- /.github/SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Support for Cryptomator 2 | 3 | For development-related topics, GitHub is the right place. 4 | 5 | For _everything else_, please visit our official [Cryptomator Community](https://community.cryptomator.org) (we are there, too :wink:). Amongst others, you will find: 6 | 7 | - [Docs](https://docs.cryptomator.org/) and [Knowledge Base](https://community.cryptomator.org/c/kb) 8 | - Installation manuals 9 | - Usage guides 10 | - FAQ 11 | - [Help with problems](https://community.cryptomator.org/c/help) 12 | - Assistance with the setup 13 | - Known issues and workarounds 14 | - Discussions about the apps 15 | - [Development discussions](https://community.cryptomator.org/c/development) 16 | - General questions 17 | - Discussions regarding our design decisions 18 | - Our roadmap 19 | -------------------------------------------------------------------------------- /.github/workflows/no-response.yml: -------------------------------------------------------------------------------- 1 | # Configuration for close-stale-issues - https://github.com/marketplace/actions/close-stale-issues 2 | 3 | name: 'Close awaiting response issues' 4 | on: 5 | schedule: 6 | - cron: '00 09 * * *' 7 | 8 | jobs: 9 | no-response: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | issues: write 13 | pull-requests: write 14 | steps: 15 | - uses: actions/stale@v8 16 | with: 17 | days-before-stale: 14 18 | days-before-close: 0 19 | days-before-pr-close: -1 20 | stale-issue-label: 'state:stale' 21 | close-issue-message: "This issue has been automatically closed because there has been no response to our request for more information from the original author. With only the information that is currently in the issue, we don't have enough information to take action. Please reach out if you have or find the answers we need so that we can investigate further." 22 | only-labels: 'state:awaiting-response' 23 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | # Configuration for close-stale-issues - https://github.com/marketplace/actions/close-stale-issues 2 | 3 | name: 'Close stale issues' 4 | on: 5 | schedule: 6 | - cron: '00 09 * * *' 7 | 8 | jobs: 9 | stale: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | issues: write 13 | pull-requests: write 14 | steps: 15 | - uses: actions/stale@v8 16 | with: 17 | days-before-stale: 365 18 | days-before-close: 90 19 | exempt-issue-labels: 'type:security-issue,type:feature-request,type:enhancement,type:upstream-bug,state:awaiting-response,state:blocked,state:confirmed' 20 | exempt-all-milestones: true 21 | stale-issue-label: 'state:stale' 22 | stale-pr-label: 'state:stale' 23 | stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.' 24 | stale-pr-message: 'This PR has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.' 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Secrets 2 | .cloud-access-secrets.sh 3 | CryptomatorCommon/Sources/CryptomatorCommonCore/CloudAccessSecrets.swift 4 | 5 | # macOS 6 | .DS_Store 7 | 8 | # Xcode 9 | 10 | ## User settings 11 | xcuserdata/ 12 | 13 | ## Obj-C/Swift specific 14 | *.hmap 15 | 16 | ## App packaging 17 | *.ipa 18 | *.dSYM.zip 19 | *.dSYM 20 | 21 | ## Playgrounds 22 | timeline.xctimeline 23 | playground.xcworkspace 24 | 25 | # Swift Package Manager 26 | # 27 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 28 | # Packages/ 29 | # Package.pins 30 | # Package.resolved 31 | # *.xcodeproj 32 | # 33 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 34 | # hence it is not needed unless you have added a package configuration file to your project 35 | # .swiftpm 36 | 37 | .build/ 38 | 39 | # fastlane 40 | Preview.html 41 | fastlane/.env 42 | fastlane/report.xml 43 | fastlane/Preview.html 44 | fastlane/screenshots/screenshots.html 45 | fastlane/screenshots/*/*.png 46 | fastlane/test_output 47 | -------------------------------------------------------------------------------- /.periphery.yml: -------------------------------------------------------------------------------- 1 | project: Cryptomator.xcodeproj 2 | schemes: 3 | - Cryptomator 4 | targets: 5 | - Cryptomator 6 | - CryptomatorFileProvider 7 | - FileProviderExtension 8 | - FileProviderExtensionUI 9 | -------------------------------------------------------------------------------- /.swiftformat: -------------------------------------------------------------------------------- 1 | --minversion 0.49.2 2 | 3 | # format options 4 | 5 | --closurevoid preserve 6 | --commas inline 7 | --ifdef no-indent 8 | --importgrouping testable-bottom 9 | --indent tab 10 | --self init-only 11 | --stripunusedargs closure-only 12 | --swiftversion 5.1 13 | --tabwidth 4 14 | 15 | # rules 16 | 17 | --enable isEmpty 18 | --disable redundantReturn,trailingClosures,wrapMultilineStatementBraces 19 | -------------------------------------------------------------------------------- /.swiftlint.yml: -------------------------------------------------------------------------------- 1 | disabled_rules: 2 | - file_length 3 | - line_length 4 | - redundant_void_return 5 | - todo 6 | - type_body_length 7 | 8 | included: 9 | - Cryptomator 10 | - CryptomatorTests 11 | - CryptomatorCommon 12 | - CryptomatorCommonHostedTests 13 | - CryptomatorFileProvider 14 | - CryptomatorFileProviderTests 15 | - FileProviderExtension 16 | - FileProviderExtensionUI 17 | 18 | excluded: 19 | - CryptomatorCommon/.build 20 | 21 | identifier_name: 22 | min_length: 1 23 | max_length: 50 24 | inclusive_language: 25 | override_allowed_terms: ["masterkey"] 26 | type_name: 27 | max_length: 50 28 | allowed_symbols: "_" 29 | -------------------------------------------------------------------------------- /Cryptomator.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Cryptomator.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Cryptomator.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Cryptomator/AddVault/AddVaultSuccesing.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AddVaultSuccesing.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 01.02.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol AddVaultSuccesing: AnyObject { 12 | func showFilesApp(forVaultUID: String) 13 | func done() 14 | } 15 | -------------------------------------------------------------------------------- /Cryptomator/AddVault/AddVaultSuccessViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AddVaultSuccessViewModel.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 11.06.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCommonCore 10 | import Foundation 11 | 12 | class AddVaultSuccessViewModel: SingleSectionTableViewModel { 13 | let vaultName: String 14 | let vaultUID: String 15 | override var title: String? { 16 | return LocalizedString.getValue("addVault.openExistingVault.title") 17 | } 18 | 19 | override var cells: [TableViewCellViewModel] { 20 | return [openInFilesAppButtonViewModel] 21 | } 22 | 23 | private lazy var openInFilesAppButtonViewModel = ButtonCellViewModel(action: "OpenInFilesApp", title: LocalizedString.getValue("common.cells.openInFilesApp")) 24 | 25 | init(vaultName: String, vaultUID: String) { 26 | self.vaultName = vaultName 27 | self.vaultUID = vaultUID 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Cryptomator/AddVault/ChooseCloudViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ChooseCloudViewModel.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 25.01.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCommonCore 10 | 11 | struct ChooseCloudViewModel { 12 | let clouds: [CloudProviderType] 13 | let headerTitle: String 14 | } 15 | -------------------------------------------------------------------------------- /Cryptomator/AddVault/CloudChoosing.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CloudChoosing.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 25.01.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCommonCore 10 | 11 | protocol CloudChoosing: AnyObject { 12 | func showAccountList(for cloudProviderType: CloudProviderType) 13 | } 14 | -------------------------------------------------------------------------------- /Cryptomator/AddVault/CreateNewVault/VaultNaming.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VaultNaming.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 17.06.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCommonCore 10 | import UIKit 11 | 12 | protocol VaultNaming: AnyObject { 13 | func setVaultName(_ name: String) 14 | } 15 | -------------------------------------------------------------------------------- /Cryptomator/AddVault/LocalVault/LocalFileSystemAuthenticating.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LocalFileSystemAuthenticating.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 21.06.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccessCore 10 | import CryptomatorCommonCore 11 | import Foundation 12 | 13 | protocol LocalFileSystemAuthenticating { 14 | func authenticated(credential: LocalFileSystemCredential) 15 | } 16 | -------------------------------------------------------------------------------- /Cryptomator/AddVault/LocalVault/LocalVaultAdding.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LocalVaultAdding.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 28.06.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol LocalVaultAdding { 12 | func validationFailed(with error: Error, at viewController: UIViewController) 13 | func showPasswordScreen(for result: LocalFileSystemAuthenticationResult) 14 | } 15 | -------------------------------------------------------------------------------- /Cryptomator/AddVault/VaultCoordinatorError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VaultCoordinatorError.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 21.06.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum VaultCoordinatorError: Error { 12 | case wrongItemType 13 | } 14 | -------------------------------------------------------------------------------- /Cryptomator/AddVault/VaultInstallationCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VaultInstallationCoordinator.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 18.01.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccess 10 | import Foundation 11 | 12 | protocol VaultInstallationCoordinator: Coordinator { 13 | func showSuccessfullyAddedVault(withName name: String, vaultUID: String) 14 | } 15 | -------------------------------------------------------------------------------- /Cryptomator/AddVault/VaultInstalling.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VaultInstalling.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 18.01.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol VaultInstalling { 12 | func showSuccessfullyAddedVault(withName name: String, vaultUID: String) 13 | } 14 | -------------------------------------------------------------------------------- /Cryptomator/Common/ActionButton.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActionButton.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 28.07.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ActionButton: UIButton { 12 | var primaryAction: ((UIButton) -> Void)? 13 | 14 | init() { 15 | super.init(frame: .zero) 16 | addTarget(self, action: #selector(primaryActionTriggered(sender:)), for: .primaryActionTriggered) 17 | } 18 | 19 | @available(*, unavailable) 20 | required init?(coder: NSCoder) { 21 | fatalError("init(coder:) has not been implemented") 22 | } 23 | 24 | @objc private func primaryActionTriggered(sender: UIButton) { 25 | primaryAction?(sender) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Cryptomator/Common/AutoHidingLabel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AutoHidingLabel.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 07.03.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class AutoHidingLabel: UILabel { 12 | override var text: String? { 13 | didSet { 14 | isHidden = text == nil && attributedText == nil 15 | } 16 | } 17 | 18 | override var attributedText: NSAttributedString? { 19 | didSet { 20 | isHidden = text == nil && attributedText == nil 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Cryptomator/Common/BaseUITableViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseUITableViewController.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 16.11.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class BaseUITableViewController: UITableViewController { 12 | init() { 13 | super.init(style: .insetGrouped) 14 | } 15 | 16 | override init(style: UITableView.Style) { 17 | super.init(style: style) 18 | } 19 | 20 | @available(*, unavailable) 21 | required init?(coder: NSCoder) { 22 | fatalError("init(coder:) has not been implemented") 23 | } 24 | 25 | override func viewDidLoad() { 26 | super.viewDidLoad() 27 | tableView.backgroundColor = .cryptomatorBackground 28 | tableView.cellLayoutMarginsFollowReadableWidth = true 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Cryptomator/Common/Bindable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Bindable.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 03.08.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Combine 10 | import Foundation 11 | 12 | class Bindable { 13 | @Published var value: Value 14 | 15 | init(_ value: Value) { 16 | self.value = value 17 | } 18 | } 19 | 20 | extension Bindable: Equatable where Value: Equatable { 21 | static func == (lhs: Bindable, rhs: Bindable) -> Bool { 22 | return lhs.value == rhs.value 23 | } 24 | } 25 | 26 | extension Bindable: Hashable where Value: Hashable { 27 | func hash(into hasher: inout Hasher) { 28 | hasher.combine(value) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Cryptomator/Common/Cells/CheckMarkCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CheckMarkCell.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 14.01.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Combine 10 | import UIKit 11 | 12 | class CheckMarkCell: UITableViewCell, ConfigurableTableViewCell { 13 | private var subscriber: AnyCancellable? 14 | 15 | func configure(with viewModel: TableViewCellViewModel) { 16 | guard let viewModel = viewModel as? CheckMarkCellViewModelType else { 17 | return 18 | } 19 | textLabel?.text = viewModel.title 20 | subscriber = viewModel.isSelected.$value.receive(on: DispatchQueue.main).sink { [weak self] isSelected in 21 | if isSelected { 22 | self?.accessoryType = .checkmark 23 | } else { 24 | self?.accessoryType = .none 25 | } 26 | } 27 | } 28 | } 29 | 30 | protocol CheckMarkCellViewModelType { 31 | var title: String? { get } 32 | var isSelected: Bindable { get } 33 | } 34 | -------------------------------------------------------------------------------- /Cryptomator/Common/Cells/LoadingButtonCellViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LoadingButtonCellViewModel.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 07.12.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class LoadingButtonCellViewModel: ButtonCellViewModel, LoadingIndicatorSupport { 12 | override var type: ConfigurableTableViewCell.Type { LoadingButtonCell.self } 13 | let isLoading: Bindable 14 | 15 | init(action: T, title: String, isLoading: Bool = false) { 16 | self.isLoading = Bindable(isLoading) 17 | super.init(action: action, title: title) 18 | } 19 | } 20 | 21 | protocol LoadingIndicatorSupport { 22 | var isLoading: Bindable { get } 23 | } 24 | -------------------------------------------------------------------------------- /Cryptomator/Common/Cells/LoadingWithLabelCellViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LoadingWithLabelCellViewModel.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 05.10.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class LoadingWithLabelCellViewModel: BindableTableViewCellViewModel { 12 | override var type: ConfigurableTableViewCell.Type { 13 | LoadingWithLabelCell.self 14 | } 15 | 16 | let isLoading: Bindable 17 | 18 | init(title: String, isLoading: Bool = false) { 19 | self.isLoading = Bindable(isLoading) 20 | super.init(title: title) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Cryptomator/Common/Cells/PasswordFieldCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PasswordFieldCell.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 29.01.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class PasswordFieldCell: TextFieldCell { 12 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 13 | super.init(style: style, reuseIdentifier: reuseIdentifier) 14 | textField.autocapitalizationType = .none 15 | textField.autocorrectionType = .no 16 | textField.keyboardType = .asciiCapable 17 | textField.isSecureTextEntry = true 18 | textField.textContentType = .password 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Cryptomator/Common/Cells/ReturnButtonSupport.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReturnButtonSupport.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 17.11.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Combine 10 | import Foundation 11 | 12 | protocol ReturnButtonSupport { 13 | var lastReturnButtonPressed: AnyPublisher { get } 14 | } 15 | 16 | extension ReturnButtonSupport where Self: AnyObject { 17 | func setupReturnButtonSupport(for cellViewModels: [TextFieldCellViewModel], subscribers: inout Set) -> AnyPublisher { 18 | let publisher = PassthroughSubject() 19 | for (i, viewModel) in cellViewModels.dropLast().enumerated() { 20 | viewModel.startListeningToReturnButtonPressedEvents().sink { 21 | cellViewModels[i + 1].becomeFirstResponder() 22 | }.store(in: &subscribers) 23 | } 24 | cellViewModels.last?.startListeningToReturnButtonPressedEvents().sink { 25 | publisher.send() 26 | }.store(in: &subscribers) 27 | return publisher.eraseToAnyPublisher() 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Cryptomator/Common/Cells/SwitchCellViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwitchCellViewModel.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 29.07.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Combine 10 | import UIKit 11 | 12 | class SwitchCellViewModel: BindableTableViewCellViewModel { 13 | override var type: ConfigurableTableViewCell.Type { 14 | SwitchCell.self 15 | } 16 | 17 | let isOn: Bindable 18 | var isOnButtonPublisher: PassthroughSubject 19 | 20 | private var subscriber: AnyCancellable? 21 | 22 | init(title: String, titleTextColor: UIColor? = nil, isOn: Bool = false) { 23 | self.isOn = Bindable(isOn) 24 | self.isOnButtonPublisher = PassthroughSubject() 25 | super.init(title: title, titleTextColor: titleTextColor, isEnabled: true, selectionStyle: .none) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Cryptomator/Common/Cells/SystemSymbolButtonCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SystemSymbolButtonCell.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 07.12.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class SystemSymbolButtonCell: ButtonTableViewCell { 13 | override func configure(with viewModel: TableViewCellViewModel) { 14 | super.configure(with: viewModel) 15 | guard let viewModel = viewModel as? SystemSymbolNameProviding else { 16 | return 17 | } 18 | accessoryView = UIImageView(image: UIImage(systemName: viewModel.symbolName)) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Cryptomator/Common/Cells/SystemSymbolButtonCellViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SystemSymbolButtonCellViewModel.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 07.12.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class SystemSymbolButtonCellViewModel: ButtonCellViewModel, SystemSymbolNameProviding { 12 | override var type: ConfigurableTableViewCell.Type { 13 | SystemSymbolButtonCell.self 14 | } 15 | 16 | let symbolName: String 17 | 18 | init(action: T, title: String, symbolName: String) { 19 | self.symbolName = symbolName 20 | super.init(action: action, title: title) 21 | } 22 | } 23 | 24 | protocol SystemSymbolNameProviding { 25 | var symbolName: String { get } 26 | } 27 | -------------------------------------------------------------------------------- /Cryptomator/Common/Cells/URLFieldCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // URLFieldCell.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 06.04.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class URLFieldCell: TextFieldCell { 12 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 13 | super.init(style: style, reuseIdentifier: reuseIdentifier) 14 | textField.autocapitalizationType = .none 15 | textField.autocorrectionType = .no 16 | textField.keyboardType = .URL 17 | textField.textContentType = .URL 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Cryptomator/Common/Cells/UsernameFieldCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UsernameFieldCell.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 06.04.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class UsernameFieldCell: TextFieldCell { 12 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 13 | super.init(style: style, reuseIdentifier: reuseIdentifier) 14 | textField.autocapitalizationType = .none 15 | textField.autocorrectionType = .no 16 | textField.keyboardType = .asciiCapable 17 | textField.textContentType = .username 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Cryptomator/Common/ChildCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ChildCoordinator.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 18.06.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCommonCore 10 | import Foundation 11 | 12 | protocol ChildCoordinator: Coordinator { 13 | func stop() 14 | var parentCoordinator: Coordinator? { get set } 15 | } 16 | -------------------------------------------------------------------------------- /Cryptomator/Common/ChooseFolder/CloudItemCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CloudItemCell.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 25.01.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccessCore 10 | import UIKit 11 | 12 | protocol CloudItemCell: UITableViewCell { 13 | var item: CloudItemMetadata? { get set } 14 | func configure(with item: CloudItemMetadata) 15 | } 16 | -------------------------------------------------------------------------------- /Cryptomator/Common/ChooseFolder/FolderChoosing.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FolderChoosing.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 20.01.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccessCore 10 | 11 | protocol FolderChoosing: AnyObject { 12 | func showItems(for path: CloudPath) 13 | func close() 14 | func chooseItem(_ item: Item) 15 | func showCreateNewFolder(parentPath: CloudPath, delegate: ChooseFolderViewModelProtocol?) 16 | func handleError(error: Error) 17 | } 18 | 19 | protocol Item { 20 | var path: CloudPath { get } 21 | } 22 | 23 | struct Folder: Item { 24 | let path: CloudPath 25 | } 26 | -------------------------------------------------------------------------------- /Cryptomator/Common/ChooseFolder/FolderCreating.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FolderCreating.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 18.06.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccessCore 10 | import Foundation 11 | 12 | protocol FolderCreating: AnyObject { 13 | func createdNewFolder(at folderPath: CloudPath) 14 | func stop() 15 | } 16 | -------------------------------------------------------------------------------- /Cryptomator/Common/CloudAccountList/AccountCellContent.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AccountCellContent.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 20.01.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class AccountCellContent: TableViewCellViewModel { 12 | let mainLabelText: String 13 | let detailLabelText: String? 14 | 15 | init(mainLabelText: String, detailLabelText: String?) { 16 | self.mainLabelText = mainLabelText 17 | self.detailLabelText = detailLabelText 18 | } 19 | 20 | override func hash(into hasher: inout Hasher) { 21 | hasher.combine(mainLabelText) 22 | hasher.combine(detailLabelText) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Cryptomator/Common/CloudAccountList/AccountInfo.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AccountInfo.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 19.01.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCommonCore 10 | import Foundation 11 | import GRDB 12 | 13 | public struct AccountInfo: Decodable, FetchableRecord { 14 | let cloudProviderAccount: CloudProviderAccount 15 | private(set) var accountListPosition: AccountListPosition 16 | 17 | init(cloudProviderAccount: CloudProviderAccount, accountListPosition: AccountListPosition) { 18 | self.cloudProviderAccount = cloudProviderAccount 19 | self.accountListPosition = accountListPosition 20 | } 21 | 22 | var cloudProviderType: CloudProviderType { 23 | return cloudProviderAccount.cloudProviderType 24 | } 25 | 26 | var accountUID: String { 27 | return cloudProviderAccount.accountUID 28 | } 29 | 30 | var listPosition: Int { 31 | get { 32 | accountListPosition.position! 33 | } 34 | set { 35 | accountListPosition.position = newValue 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Cryptomator/Common/CloudAccountList/AccountListing.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AccountListing.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 20.01.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCommonCore 10 | import UIKit 11 | 12 | protocol AccountListing: AnyObject { 13 | func showAddAccount(for cloudProviderType: CloudProviderType, from viewController: UIViewController) 14 | func selectedAccont(_ account: AccountInfo) throws 15 | func showEdit(for account: AccountInfo) 16 | } 17 | -------------------------------------------------------------------------------- /Cryptomator/Common/Combine/Publisher+OptionalAssign.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Publisher+OptionalAssign.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 04.08.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Combine 10 | import Foundation 11 | 12 | extension Publisher where Failure == Never { 13 | func assign(to keyPath: ReferenceWritableKeyPath, on root: Root?) -> AnyCancellable { 14 | sink { [weak root] in 15 | root?[keyPath: keyPath] = $0 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Cryptomator/Common/Combine/UISwitch+Publisher.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UISwitch+Publisher.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 06.08.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Combine 10 | import UIKit 11 | 12 | extension UISwitch { 13 | func publisher(for events: UIControl.Event) -> AnyPublisher.Failure> { 14 | return publisher(for: events).map { $0.isOn }.eraseToAnyPublisher() 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Cryptomator/Common/FilesAppUtil.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FilesAppUtil.swift 3 | // Cryptomator 4 | // 5 | // Created by Tobias Hagemann on 29.06.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CocoaLumberjackSwift 10 | import CryptomatorCommonCore 11 | import UIKit 12 | 13 | public enum FilesAppUtil { 14 | public static func showFilesApp(forVaultUID vaultUID: String) { 15 | guard let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: CryptomatorConstants.appGroupName) else { 16 | DDLogDebug("containerURL is nil") 17 | return 18 | } 19 | let url = containerURL.appendingPathComponent("File Provider Storage").appendingPathComponent(vaultUID) 20 | guard let sharedDocumentsURL = FilesAppUtil.changeSchemeToSharedDocuments(for: url) else { 21 | DDLogDebug("Conversion to \"shareddocuments\" scheme failed") 22 | return 23 | } 24 | UIApplication.shared.open(sharedDocumentsURL) 25 | } 26 | 27 | private static func changeSchemeToSharedDocuments(for url: URL) -> URL? { 28 | var comps = URLComponents(url: url, resolvingAgainstBaseURL: false) 29 | comps?.scheme = "shareddocuments" 30 | return comps?.url 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Cryptomator/Common/HeaderFooter/AttributedTextHeaderFooterViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AttributedTextHeaderFooterViewModel.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 05.08.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class AttributedTextHeaderFooterViewModel: HeaderFooterViewModel { 12 | var viewType: HeaderFooterViewModelConfiguring.Type { return AttributedTextHeaderFooterView.self } 13 | var title: Bindable { return Bindable(nil) } 14 | let attributedText: NSAttributedString 15 | 16 | init(attributedText: NSAttributedString) { 17 | self.attributedText = attributedText 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Cryptomator/Common/HeaderFooter/BaseHeaderFooterView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseHeaderFooterView.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 03.08.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Combine 10 | import UIKit 11 | 12 | class BaseHeaderFooterView: UITableViewHeaderFooterView, HeaderFooterViewModelConfiguring { 13 | weak var tableView: UITableView? 14 | 15 | var subscriber: AnyCancellable? 16 | 17 | func configure(with viewModel: HeaderFooterViewModel) { 18 | textLabel?.numberOfLines = 0 19 | textLabel?.text = viewModel.title.value 20 | subscriber = viewModel.title.$value.receive(on: DispatchQueue.main).sink(receiveValue: { [weak self] text in 21 | self?.textLabel?.text = text 22 | self?.setNeedsLayout() 23 | guard self?.tableView?.window != nil else { 24 | return 25 | } 26 | UIView.performWithoutAnimation { 27 | self?.tableView?.performBatchUpdates({ 28 | // performBatchUpdates call is needed to actually trigger an tableView (layout) update 29 | }) 30 | } 31 | }) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Cryptomator/Common/HeaderFooter/BindableAttributedTextHeaderFooterViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BindableAttributedTextHeaderFooterViewModel.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 05.08.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class BindableAttributedTextHeaderFooterViewModel: HeaderFooterViewModel { 12 | var viewType: HeaderFooterViewModelConfiguring.Type { return BindableAttributedTextHeaderFooterView.self } 13 | var title: Bindable { return Bindable(nil) } 14 | let attributedText: Bindable 15 | 16 | init(attributedText: NSAttributedString) { 17 | self.attributedText = Bindable(attributedText) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Cryptomator/Common/HeaderFooter/HeaderFooterViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HeaderFooterViewModel.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 03.08.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol HeaderFooterViewModel { 12 | var viewType: HeaderFooterViewModelConfiguring.Type { get } 13 | var title: Bindable { get } 14 | } 15 | 16 | protocol HeaderFooterViewModelConfiguring: UIView { 17 | func configure(with viewModel: HeaderFooterViewModel) 18 | var tableView: UITableView? { get set } 19 | } 20 | 21 | class BaseHeaderFooterViewModel: HeaderFooterViewModel { 22 | var viewType: HeaderFooterViewModelConfiguring.Type { return BaseHeaderFooterView.self } 23 | let title: Bindable 24 | 25 | init(title: String) { 26 | self.title = Bindable(title) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Cryptomator/Common/LocalWeb/LocalWebViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LocalWebViewModel.swift 3 | // Cryptomator 4 | // 5 | // Created by Tobias Hagemann on 14.06.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum LocalWebViewError: Error { 12 | case resourceNotFound 13 | } 14 | 15 | class LocalWebViewModel { 16 | let title: String 17 | 18 | private let htmlPathName: String 19 | 20 | var baseURL: URL { 21 | return Bundle.main.bundleURL 22 | } 23 | 24 | init(title: String, htmlPathName: String) { 25 | self.title = title 26 | self.htmlPathName = htmlPathName 27 | } 28 | 29 | func loadHTMLString() throws -> String { 30 | guard let htmlURL = Bundle.main.url(forResource: htmlPathName, withExtension: "html") else { 31 | throw LocalWebViewError.resourceNotFound 32 | } 33 | return try String(contentsOf: htmlURL, encoding: .utf8) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Cryptomator/Common/MaintenanceModeError+Localization.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MaintenanceModeError+Localization.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 28.10.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCommonCore 10 | import Foundation 11 | 12 | extension MaintenanceModeError: LocalizedError { 13 | public var errorDescription: String? { 14 | switch self { 15 | case .runningCloudTask: 16 | return LocalizedString.getValue("maintenanceModeError.runningCloudTask") 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Cryptomator/Common/PoppingCloseCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PoppingCloseCoordinator.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 30.11.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCommonCore 10 | import UIKit 11 | 12 | protocol PoppingCloseCoordinator: Coordinator { 13 | var oldTopViewController: UIViewController? { get } 14 | } 15 | 16 | extension PoppingCloseCoordinator { 17 | func close() { 18 | popToOldTopViewController() 19 | } 20 | 21 | func popToOldTopViewController() { 22 | guard let oldTopViewController = oldTopViewController else { 23 | return 24 | } 25 | navigationController.popToViewController(oldTopViewController, animated: true) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Cryptomator/Common/Previews/UIView+Preview.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Preview.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 11.01.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import UIKit 11 | 12 | extension UIView { 13 | private struct Preview: UIViewRepresentable { 14 | // this variable is used for injecting the current view 15 | let view: UIView 16 | 17 | func makeUIView(context: Context) -> some UIView { 18 | return view 19 | } 20 | 21 | func updateUIView(_ uiView: UIViewType, context: Context) {} 22 | } 23 | 24 | func toPreview() -> some View { 25 | // inject self (the current view) for the preview 26 | Preview(view: self) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Cryptomator/Common/Previews/UIViewController+Preview.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+Preview.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 04.01.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import UIKit 11 | 12 | extension UIViewController { 13 | private struct Preview: UIViewControllerRepresentable { 14 | // this variable is used for injecting the current view controller 15 | let viewController: UIViewController 16 | 17 | func makeUIViewController(context: Context) -> UIViewController { 18 | return viewController 19 | } 20 | 21 | func updateUIViewController(_ uiViewController: UIViewController, context: Context) {} 22 | } 23 | 24 | public func toPreview() -> some View { 25 | // inject self (the current view controller) for the preview 26 | Preview(viewController: self) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Cryptomator/Common/SingleSectionTableViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SingleSectionTableViewController.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 25.01.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SingleSectionTableViewController: BaseUITableViewController { 12 | override func numberOfSections(in tableView: UITableView) -> Int { 13 | return 1 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Cryptomator/Common/TableViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TableViewModel.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 17.11.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class TableViewModel { 12 | var title: String? { 13 | return nil 14 | } 15 | 16 | var sections: [Section] { 17 | return [] 18 | } 19 | 20 | func getHeaderTitle(for section: Int) -> String? { 21 | return nil 22 | } 23 | 24 | func getFooterTitle(for section: Int) -> String? { 25 | return nil 26 | } 27 | } 28 | 29 | struct Section { 30 | let id: T 31 | let elements: [TableViewCellViewModel] 32 | } 33 | 34 | class SingleSectionTableViewModel: TableViewModel { 35 | var cells: [TableViewCellViewModel] { 36 | return [] 37 | } 38 | 39 | override var sections: [Section] { 40 | return [Section(id: .main, elements: cells)] 41 | } 42 | } 43 | 44 | enum SingleSection { 45 | case main 46 | } 47 | -------------------------------------------------------------------------------- /Cryptomator/Common/UIViewController+ProgressHUDError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+ProgressHUDError.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 05.11.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCommonCore 10 | import UIKit 11 | 12 | extension UIViewController { 13 | func handleError(_ error: Error, coordinator: Coordinator?, progressHUD: ProgressHUD) { 14 | progressHUD.dismiss(animated: true).then { 15 | coordinator?.handleError(error, for: self) 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Cryptomator/Common/VaultDetailItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VaultDetailItem.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 24.06.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccessCore 10 | import CryptomatorCommonCore 11 | import Foundation 12 | 13 | struct VaultDetailItem: Item, VaultItem { 14 | var path: CloudPath { 15 | return vaultPath 16 | } 17 | 18 | let name: String 19 | let vaultPath: CloudPath 20 | let isLegacyVault: Bool 21 | } 22 | -------------------------------------------------------------------------------- /Cryptomator/Cryptomator.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.default-data-protection 6 | NSFileProtectionComplete 7 | com.apple.security.application-groups 8 | 9 | group.org.cryptomator.ios 10 | 11 | keychain-access-groups 12 | 13 | $(AppIdentifierPrefix)org.cryptomator.ios 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Cryptomator/MicrosoftGraph/MicrosoftGraphAuthenticatorError+Localization.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MicrosoftGraphAuthenticatorError+Localization.swift 3 | // CryptomatorCommon 4 | // 5 | // Created by Tobias Hagemann on 11.03.25. 6 | // Copyright © 2025 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccess 10 | import CryptomatorCommonCore 11 | import Foundation 12 | 13 | extension MicrosoftGraphAuthenticatorError: LocalizedError { 14 | public var errorDescription: String? { 15 | switch self { 16 | case .missingAccountIdentifier: 17 | return nil 18 | case .serverDeclinedScopes: 19 | return LocalizedString.getValue("microsoftGraphAuthenticator.error.serverDeclinedScopes") 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Cryptomator/MicrosoftGraph/SharePointAuthenticating.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SharePointAuthenticating.swift 3 | // Cryptomator 4 | // 5 | // Created by Majid Achhoud on 03.12.24. 6 | // Copyright © 2024 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccessCore 10 | import UIKit 11 | 12 | protocol SharePointAuthenticating: AnyObject { 13 | func setSiteURL(_ siteURL: URL, from viewController: UIViewController) 14 | func authenticated(_ credential: SharePointCredential) throws 15 | func cancel() 16 | } 17 | -------------------------------------------------------------------------------- /Cryptomator/MicrosoftGraph/SharePointCredential.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SharePointCredential.swift 3 | // Cryptomator 4 | // 5 | // Created by Tobias Hagemann on 12.03.25. 6 | // Copyright © 2025 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccessCore 10 | import Foundation 11 | 12 | public struct SharePointCredential { 13 | public let siteURL: URL 14 | public let credential: MicrosoftGraphCredential 15 | public let driveID: String 16 | } 17 | -------------------------------------------------------------------------------- /Cryptomator/MicrosoftGraph/SharePointURLValidationError+Localization.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SharePointURLValidationError+Localization.swift 3 | // Cryptomator 4 | // 5 | // Created by Tobias Hagemann on 13.03.25. 6 | // Copyright © 2025 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccessCore 10 | import CryptomatorCommonCore 11 | import Foundation 12 | 13 | extension SharePointURLValidationError: LocalizedError { 14 | public var errorDescription: String? { 15 | switch self { 16 | case .emptyURL: 17 | return LocalizedString.getValue("sharePoint.urlValidation.error.emptyURL") 18 | case .invalidURL: 19 | return LocalizedString.getValue("sharePoint.urlValidation.error.invalidURL") 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Cryptomator/Onboarding/OnboardingNavigationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OnboardingNavigationController.swift 3 | // Cryptomator 4 | // 5 | // Created by Tobias Hagemann on 23.09.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCommonCore 10 | import Foundation 11 | 12 | class OnboardingNavigationController: BaseNavigationController { 13 | override func viewDidDisappear(_ animated: Bool) { 14 | super.viewDidDisappear(animated) 15 | CryptomatorUserDefaults.shared.showOnboardingAtStartup = false 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Cryptomator/Purchase/Cells/DisclosureCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DisclosureCell.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 07.03.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class DisclosureCell: UITableViewCell { 12 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 13 | super.init(style: style, reuseIdentifier: reuseIdentifier) 14 | accessoryType = .disclosureIndicator 15 | contentView.heightAnchor.constraint(greaterThanOrEqualToConstant: IAPCell.minimumHeight).isActive = true 16 | } 17 | 18 | @available(*, unavailable) 19 | required init?(coder: NSCoder) { 20 | fatalError("init(coder:) has not been implemented") 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Cryptomator/Purchase/SKProduct+LocalizedPrice.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SKProduct+LocalizedPrice.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 26.11.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import StoreKit 11 | 12 | extension SKProduct { 13 | private static let formatter: NumberFormatter = { 14 | let formatter = NumberFormatter() 15 | formatter.numberStyle = .currency 16 | return formatter 17 | }() 18 | 19 | var localizedPrice: String? { 20 | let formatter = SKProduct.formatter 21 | formatter.locale = priceLocale 22 | return formatter.string(from: price) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Cryptomator/Purchase/TrialExpiredNavigationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TrialExpiredNavigationController.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 03.12.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCommonCore 10 | import Foundation 11 | 12 | class TrialExpiredNavigationController: BaseNavigationController { 13 | override func viewDidDisappear(_ animated: Bool) { 14 | super.viewDidDisappear(animated) 15 | CryptomatorUserDefaults.shared.showedTrialExpiredAtStartup = true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Cryptomator/Resources/style.css: -------------------------------------------------------------------------------- 1 | :root { 2 | color-scheme: light dark; 3 | } 4 | 5 | body { 6 | font-family: "Helvetica Neue", sans-serif; 7 | font-size: 16px; 8 | line-height: 1.75; 9 | font-weight: 400; 10 | background-color: transparent; 11 | margin: 16px; 12 | } 13 | 14 | h1, h2, p, ul, ol, pre { 15 | margin-bottom: 16px; 16 | } 17 | 18 | h1, h2 { 19 | font-weight: 500; 20 | margin-top: 32px; 21 | } 22 | 23 | h1 { 24 | font-size: 28px; 25 | } 26 | 27 | h2 { 28 | font-size: 21px; 29 | } 30 | 31 | h1:first-child, h2:first-child { 32 | margin-top: 0; 33 | } 34 | 35 | ul, ol { 36 | padding-left: 1.5em; 37 | } 38 | 39 | /* links */ 40 | 41 | a { 42 | color: #49b04a; 43 | text-decoration: none; 44 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 45 | } 46 | 47 | a.touched { 48 | text-decoration: underline; 49 | } 50 | -------------------------------------------------------------------------------- /Cryptomator/S3/S3Authenticating.swift: -------------------------------------------------------------------------------- 1 | // 2 | // S3Authenticating.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 28.06.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccessCore 10 | import Foundation 11 | 12 | protocol S3Authenticating { 13 | func authenticated(with credential: S3Credential) 14 | func cancel() 15 | } 16 | -------------------------------------------------------------------------------- /Cryptomator/S3/S3CredentialVerifier.swift: -------------------------------------------------------------------------------- 1 | // 2 | // S3CredentialVerifier.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 29.06.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccessCore 10 | import CryptomatorCommonCore 11 | import Foundation 12 | import Promises 13 | 14 | protocol S3CredentialVerifierType { 15 | func verifyCredential(_ credential: S3Credential) -> Promise 16 | } 17 | 18 | struct S3CredentialVerifier: S3CredentialVerifierType { 19 | static let shared = S3CredentialVerifier() 20 | private init() {} 21 | func verifyCredential(_ credential: S3Credential) -> Promise { 22 | return S3Authenticator.verifyCredential(credential).recover { error -> Void in 23 | switch error { 24 | case let cloudProviderError as CloudProviderError: 25 | throw LocalizedCloudProviderError.convertToLocalized(cloudProviderError, cloudPath: .init("/")) 26 | default: 27 | throw error 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Cryptomator/Settings/About/AboutCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AboutCoordinator.swift 3 | // Cryptomator 4 | // 5 | // Created by Tobias Hagemann on 14.06.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCommonCore 10 | import Foundation 11 | import UIKit 12 | 13 | class AboutCoordinator: Coordinator { 14 | var childCoordinators = [Coordinator]() 15 | var navigationController: UINavigationController 16 | 17 | init(navigationController: UINavigationController) { 18 | self.navigationController = navigationController 19 | } 20 | 21 | func start() { 22 | let localWebViewController = LocalWebViewController(viewModel: AboutViewModel()) 23 | localWebViewController.coordinator = self 24 | if CryptomatorUserDefaults.isTestFlightEnvironment { 25 | localWebViewController.navigationItem.prompt = "TestFlight Build" 26 | navigationController.navigationBar.barStyle = .black 27 | } 28 | navigationController.pushViewController(localWebViewController, animated: true) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Cryptomator/Settings/About/AboutViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AboutViewModel.swift 3 | // Cryptomator 4 | // 5 | // Created by Tobias Hagemann on 14.06.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCommonCore 10 | import Foundation 11 | 12 | class AboutViewModel: LocalWebViewModel { 13 | init() { 14 | // swiftlint:disable:next force_cast 15 | let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String 16 | // swiftlint:disable:next force_cast 17 | let build = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as! String 18 | let title = String(format: LocalizedString.getValue("settings.aboutCryptomator.title"), version, build) 19 | super.init(title: title, htmlPathName: "about") 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Cryptomator/VaultDetail/ChangePassword/VaultPasswordChanging.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VaultPasswordChanging.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 29.10.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol VaultPasswordChanging { 12 | func changedPassword() 13 | } 14 | -------------------------------------------------------------------------------- /Cryptomator/VaultDetail/VaultPasswordVerifying.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VaultPasswordVerifying.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 04.08.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol VaultPasswordVerifying { 12 | func verifiedVaultPassword() 13 | func cancel() 14 | } 15 | -------------------------------------------------------------------------------- /Cryptomator/VaultList/VaultListPosition.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VaultListPosition.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 11.01.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import GRDB 11 | 12 | struct VaultListPosition: Codable { 13 | var id: Int64? 14 | var position: Int? 15 | let vaultUID: String 16 | } 17 | 18 | extension VaultListPosition: FetchableRecord, MutablePersistableRecord { 19 | static let databaseSelection: [SQLSelectable] = [AllColumns(), Column.rowID] 20 | 21 | mutating func didInsert(_ inserted: InsertionSuccess) { 22 | id = inserted.rowID 23 | } 24 | 25 | init(row: Row) throws { 26 | self.id = row[Column.rowID] 27 | self.position = row[Columns.position] 28 | self.vaultUID = row[Columns.vaultUID] 29 | } 30 | 31 | func encode(to container: inout PersistenceContainer) throws { 32 | container[Column.rowID] = id 33 | container[Columns.position] = position 34 | container[Columns.vaultUID] = vaultUID 35 | } 36 | 37 | enum Columns: String, ColumnExpression { 38 | case id, position, vaultUID 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Cryptomator/WebDAV/TLSCertificateValidationHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSCertificateValidationHelper.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 28.08.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccessCore 10 | import Foundation 11 | import Promises 12 | 13 | protocol TLSCertificateValidationHelping { 14 | func validate(url: URL) -> Promise 15 | } 16 | 17 | struct TLSCertificateValidationHelper: TLSCertificateValidationHelping { 18 | func validate(url: URL) -> Promise { 19 | let validator = TLSCertificateValidator(baseURL: url) 20 | return validator.validate() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Cryptomator/WebDAV/WebDAVAuthenticating.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WebDAVAuthenticating.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 07.04.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccessCore 10 | import Foundation 11 | 12 | protocol WebDAVAuthenticating: AnyObject { 13 | func authenticated(with credential: WebDAVCredential) 14 | func cancel() 15 | } 16 | -------------------------------------------------------------------------------- /Cryptomator/WebDAV/WebDAVAuthenticator+VC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WebDAVAuthenticator+VC.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 08.04.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccessCore 10 | import Promises 11 | import UIKit 12 | 13 | extension WebDAVAuthenticator { 14 | private static var coordinator: WebDAVAuthenticationCoordinator? 15 | 16 | static func authenticate(from viewController: UIViewController) -> Promise { 17 | let navigationController = BaseNavigationController() 18 | let webDAVCoordinator = WebDAVAuthenticationCoordinator(navigationController: navigationController) 19 | coordinator = webDAVCoordinator 20 | viewController.present(navigationController, animated: true) 21 | webDAVCoordinator.start() 22 | return webDAVCoordinator.pendingAuthentication.always { 23 | self.coordinator = nil 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CryptomatorCommon/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/CloudPath+Contains.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CloudPath+Contains.swift 3 | // CryptomatorCommonCore 4 | // 5 | // Created by Philipp Schmid on 27.10.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccessCore 10 | import Foundation 11 | 12 | public extension CloudPath { 13 | func contains(_ other: CloudPath) -> Bool { 14 | return pathComponents.starts(with: other.pathComponents) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/CryptoBotHeaderFooterView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptoBotHeaderFooterView.swift 3 | // CryptomatorCommonCore 4 | // 5 | // Created by Philipp Schmid on 08.12.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | open class CryptoBotHeaderFooterView: LargeHeaderFooterView { 12 | public init(infoText: String?) { 13 | super.init(image: UIImage(named: "bot"), infoText: infoText) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/CryptomatorConstants.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptomatorConstants.swift 3 | // CryptomatorCommonCore 4 | // 5 | // This file was automatically generated by create-app-constants.sh and should not be modified. 6 | // 7 | 8 | import Foundation 9 | 10 | public enum CryptomatorConstants { 11 | public static let appGroupName = "group.org.cryptomator.ios" 12 | public static let mainAppBundleId = "org.cryptomator.ios" 13 | } 14 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/CryptomatorErrorView.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | public struct CryptomatorErrorView: View { 4 | let text: String? 5 | 6 | public init(text: String? = nil) { 7 | self.text = text 8 | } 9 | 10 | public var body: some View { 11 | VStack(spacing: 20) { 12 | Image(systemName: "exclamationmark.triangle.fill") 13 | .font(.system(size: 120)) 14 | .foregroundColor(Color(UIColor.cryptomatorYellow)) 15 | if let text { 16 | Text(text) 17 | } 18 | }.padding(.vertical, 20) 19 | } 20 | } 21 | 22 | struct CryptomatorErrorView_Previews: PreviewProvider { 23 | static var previews: some View { 24 | CryptomatorErrorView() 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/CryptomatorSimpleButtonView.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | struct CryptomatorSimpleButtonView: View { 4 | let buttonTitle: String 5 | let onButtonTap: () -> Void 6 | let headerTitle: String 7 | 8 | var body: some View { 9 | List { 10 | Section { 11 | Button(buttonTitle) { 12 | onButtonTap() 13 | } 14 | } header: { 15 | VStack(alignment: .center, spacing: 20) { 16 | Image("bot-vault") 17 | Text(headerTitle) 18 | .textCase(.none) 19 | .foregroundColor(.primary) 20 | .font(.body) 21 | .multilineTextAlignment(.center) 22 | } 23 | .frame(maxWidth: .infinity) 24 | .padding(.bottom, 20) 25 | } 26 | } 27 | .setListBackgroundColor(.cryptomatorBackground) 28 | } 29 | } 30 | 31 | struct CryptomatorSimpleButtonView_Previews: PreviewProvider { 32 | static var previews: some View { 33 | CryptomatorSimpleButtonView(buttonTitle: "Button", onButtonTap: {}, headerTitle: "Header title.") 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/FileProviderXPC/LogLevelUpdating.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LogLevelUpdating.swift 3 | // CryptomatorCommonCore 4 | // 5 | // Created by Philipp Schmid on 11.10.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import FileProvider 10 | import Foundation 11 | 12 | @objc public protocol LogLevelUpdating: NSFileProviderServiceSource { 13 | func logLevelUpdated() 14 | } 15 | 16 | public extension NSFileProviderServiceName { 17 | static let logLevelUpdating = NSFileProviderServiceName("org.cryptomator.ios.log-level-updating") 18 | } 19 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/FileProviderXPC/UploadRetrying.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UploadRetrying.swift 3 | // CryptomatorCommonCore 4 | // 5 | // Created by Philipp Schmid on 03.05.22. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import FileProvider 10 | import Foundation 11 | 12 | @objc public protocol UploadRetrying: NSFileProviderServiceSource { 13 | /** 14 | Retries the upload for the given item identifiers. 15 | */ 16 | func retryUpload(for itemIdentifiers: [NSFileProviderItemIdentifier], reply: @escaping (Error?) -> Void) 17 | 18 | func getCurrentFractionalUploadProgress(for itemIdentifier: NSFileProviderItemIdentifier, reply: @escaping (NSNumber?) -> Void) 19 | } 20 | 21 | public extension NSFileProviderServiceName { 22 | static let uploadRetryingService = NSFileProviderServiceName("org.cryptomator.ios.upload-retrying") 23 | } 24 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/FileProviderXPC/XPCErrorHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XPCErrorHelper.swift 3 | // CryptomatorCommonCore 4 | // 5 | // Created by Philipp Schmid on 07.02.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public enum XPCErrorHelper { 12 | /** 13 | Bridges a Swift Error to an XPC compatible NSError. 14 | 15 | Since the lazy evaluation of the userInfo does not work for XPC, in order to not lose the `localizedDescription`, it is evaluated eagerly. 16 | */ 17 | public static func bridgeError(_ error: Error) -> NSError { 18 | let nsError = error as NSError 19 | var userInfo = nsError.userInfo 20 | userInfo[NSLocalizedDescriptionKey] = error.localizedDescription 21 | return NSError(domain: nsError.domain, code: nsError.code, userInfo: userInfo) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/Hub/HubAuthenticationFlowDelegate.swift: -------------------------------------------------------------------------------- 1 | import CryptoKit 2 | import JOSESwift 3 | 4 | public protocol HubAuthenticationFlowDelegate: AnyObject { 5 | func didSuccessfullyRemoteUnlock(_ response: HubUnlockResponse) async 6 | } 7 | 8 | public struct HubUnlockResponse { 9 | public let jwe: JWE 10 | public let privateKey: P384.KeyAgreement.PrivateKey 11 | public let subscriptionState: HubSubscriptionState 12 | } 13 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/Hub/HubErrorWithRefreshView.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | struct CryptomatorErrorWithRefreshView: View { 4 | var headerTitle: String 5 | var onRefresh: () -> Void 6 | 7 | var body: some View { 8 | CryptomatorSimpleButtonView( 9 | buttonTitle: LocalizedString.getValue("common.button.refresh"), 10 | onButtonTap: onRefresh, 11 | headerTitle: headerTitle 12 | ) 13 | } 14 | } 15 | 16 | struct CryptomatorErrorWithRefreshView_Previews: PreviewProvider { 17 | static var previews: some View { 18 | CryptomatorErrorWithRefreshView(headerTitle: "Example Header Title", onRefresh: {}) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/Hub/HubSubscriptionState.swift: -------------------------------------------------------------------------------- 1 | public enum HubSubscriptionState: String, Codable { 2 | case active 3 | case inactive 4 | } 5 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/Hub/HubUserAuthenticator.swift: -------------------------------------------------------------------------------- 1 | import AppAuthCore 2 | import CryptomatorCloudAccessCore 3 | import UIKit 4 | 5 | struct HubUserAuthenticator: HubUserLogin { 6 | private let hubAuthenticator: HubAuthenticating 7 | private let viewController: UIViewController 8 | 9 | init(hubAuthenticator: HubAuthenticating, viewController: UIViewController) { 10 | self.hubAuthenticator = hubAuthenticator 11 | self.viewController = viewController 12 | } 13 | 14 | func authenticate(with hubConfig: HubConfig) async throws -> OIDAuthState { 15 | try await hubAuthenticator.authenticate(with: hubConfig, from: viewController) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/Hub/HubUserLogin.swift: -------------------------------------------------------------------------------- 1 | import AppAuthCore 2 | import CryptomatorCloudAccessCore 3 | import Foundation 4 | 5 | public protocol HubUserLogin { 6 | func authenticate(with hubConfig: HubConfig) async throws -> OIDAuthState 7 | } 8 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/LocalAuthentication+Localization.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LocalAuthentication+Localization.swift 3 | // Cryptomator 4 | // 5 | // Created by Philipp Schmid on 09.08.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import LocalAuthentication 10 | 11 | public extension LABiometryType { 12 | func localizedName() -> String? { 13 | switch self { 14 | case .faceID: 15 | return LocalizedString.getValue("biometryType.faceID") 16 | case .touchID: 17 | return LocalizedString.getValue("biometryType.touchID") 18 | default: 19 | return nil 20 | } 21 | } 22 | } 23 | 24 | public extension LAContext { 25 | func enrolledBiometricsAuthenticationName() -> String? { 26 | if canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) { 27 | return biometryType.localizedName() 28 | } 29 | return nil 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/LocalizedString.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LocalizedString.swift 3 | // CryptomatorCommonCore 4 | // 5 | // Created by Tobias Hagemann on 12.08.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public enum LocalizedString { 12 | public static func getValue(_ key: String) -> String { 13 | let value = NSLocalizedString(key, comment: "") 14 | if value != key || NSLocale.preferredLanguages.first == "en" { 15 | return value 16 | } 17 | // Fallback to English 18 | guard let path = Bundle.main.path(forResource: "en", ofType: "lproj"), let bundle = Bundle(path: path) else { 19 | return value 20 | } 21 | return NSLocalizedString(key, bundle: bundle, comment: "") 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/Manager/CloudProviderType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CloudProviderType.swift 3 | // CryptomatorCommonCore 4 | // 5 | // Created by Philipp Schmid on 20.10.20. 6 | // Copyright © 2020 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccessCore 10 | import Foundation 11 | import GRDB 12 | 13 | public enum CloudProviderType: Codable, Equatable, Hashable, DatabaseValueConvertible { 14 | case box 15 | case dropbox 16 | case googleDrive 17 | case localFileSystem(type: LocalFileSystemType) 18 | case microsoftGraph(type: MicrosoftGraphType) 19 | case pCloud 20 | case s3(type: S3Type) 21 | case webDAV(type: WebDAVType) 22 | } 23 | 24 | public enum LocalFileSystemType: Codable { 25 | case custom 26 | case iCloudDrive 27 | } 28 | 29 | public enum WebDAVType: Codable { 30 | case custom 31 | } 32 | 33 | public enum S3Type: Codable { 34 | case custom 35 | } 36 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/Manager/ExistingHubVault.swift: -------------------------------------------------------------------------------- 1 | import CryptoKit 2 | import Foundation 3 | 4 | public struct ExistingHubVault { 5 | let vaultUID: String 6 | let delegateAccountUID: String 7 | let jweData: Data 8 | let privateKey: P384.KeyAgreement.PrivateKey 9 | let vaultItem: VaultItem 10 | let downloadedVaultConfig: DownloadedVaultConfig 11 | 12 | public init(vaultUID: String, delegateAccountUID: String, jweData: Data, privateKey: P384.KeyAgreement.PrivateKey, vaultItem: VaultItem, downloadedVaultConfig: DownloadedVaultConfig) { 13 | self.vaultUID = vaultUID 14 | self.delegateAccountUID = delegateAccountUID 15 | self.jweData = jweData 16 | self.privateKey = privateKey 17 | self.vaultItem = vaultItem 18 | self.downloadedVaultConfig = downloadedVaultConfig 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/Mocks/CloudProviderUpdatingMock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CloudProviderUpdatingMock.swift 3 | // CryptomatorCommonCore 4 | // 5 | // Created by Philipp Schmid on 28.08.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | #if DEBUG 10 | import Foundation 11 | 12 | // swiftlint:disable all 13 | 14 | final class CloudProviderUpdatingMock: CloudProviderUpdating { 15 | // MARK: - providerShouldUpdate 16 | 17 | var providerShouldUpdateWithCallsCount = 0 18 | var providerShouldUpdateWithCalled: Bool { 19 | providerShouldUpdateWithCallsCount > 0 20 | } 21 | 22 | var providerShouldUpdateWithReceivedAccountUID: String? 23 | var providerShouldUpdateWithReceivedInvocations: [String] = [] 24 | var providerShouldUpdateWithClosure: ((String) -> Void)? 25 | 26 | func providerShouldUpdate(with accountUID: String) { 27 | providerShouldUpdateWithCallsCount += 1 28 | providerShouldUpdateWithReceivedAccountUID = accountUID 29 | providerShouldUpdateWithReceivedInvocations.append(accountUID) 30 | providerShouldUpdateWithClosure?(accountUID) 31 | } 32 | } 33 | // swiftlint:enable all 34 | #endif 35 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/Mocks/CryptomatorSettingsMock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptomatorSettingsMock.swift 3 | // CryptomatorCommonCore 4 | // 5 | // Created by Philipp Schmid on 23.11.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | #if DEBUG 10 | import Foundation 11 | 12 | class CryptomatorSettingsMock: CryptomatorSettings { 13 | var trialExpirationDate: Date? 14 | var debugModeEnabled: Bool = false 15 | var fullVersionUnlocked: Bool = false 16 | var hasRunningSubscription: Bool = false 17 | #if !ALWAYS_PREMIUM 18 | var summer2025BannerDismissed: Bool = false 19 | #endif 20 | } 21 | #endif 22 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/Mocks/FullVersionCheckerMock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FullVersionCheckerMock.swift 3 | // CryptomatorCommonCore 4 | // 5 | // Created by Philipp Schmid on 02.12.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | final class FullVersionCheckerMock: FullVersionChecker { 12 | var isFullVersion: Bool = false 13 | var hasExpiredTrial: Bool = false 14 | } 15 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/Promise+AllIgnoringResult.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Promise+AllIgnoringResult.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 31.03.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Promises 11 | 12 | public func all(ignoringResult promises: Container) -> Promise where Container.Element == Promise { 13 | return any(promises).then { _ -> Void in 14 | // discard result 15 | }.recover { _ -> Void in 16 | // discard result 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/Promise+StructuredConcurrency.swift: -------------------------------------------------------------------------------- 1 | import Promises 2 | 3 | public extension Promise { 4 | func getValue() async throws -> Value { 5 | try await withCheckedThrowingContinuation({ continuation in 6 | self.then(continuation.resume(returning:)).catch(continuation.resume(throwing:)) 7 | }) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/S3/CryptomatorKeychain+S3.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CryptomatorKeychain+S3.swift 3 | // 4 | // 5 | // Created by Philipp Schmid on 29.06.22. 6 | // 7 | 8 | import CryptomatorCloudAccessCore 9 | import Foundation 10 | 11 | extension CryptomatorKeychainType { 12 | func getS3Credential(_ identifier: String) -> S3Credential? { 13 | guard let data = getAsData(identifier) else { 14 | return nil 15 | } 16 | do { 17 | let jsonDecoder = JSONDecoder() 18 | return try jsonDecoder.decode(S3Credential.self, from: data) 19 | } catch { 20 | return nil 21 | } 22 | } 23 | 24 | func saveS3Credential(_ credential: S3Credential) throws { 25 | let identifier = String(credential.identifier) 26 | let jsonEncoder = JSONEncoder() 27 | let encodedCredential = try jsonEncoder.encode(credential) 28 | try set(identifier, value: encodedCredential) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/SwiftUI/SwiftUI+ListBackground.swift: -------------------------------------------------------------------------------- 1 | import Introspect 2 | import SwiftUI 3 | 4 | public extension View { 5 | func setListBackgroundColor(_ color: Color) -> some View { 6 | modifier(ListBackgroundModifier(color: color)) 7 | } 8 | } 9 | 10 | struct ListBackgroundModifier: ViewModifier { 11 | let color: Color 12 | 13 | public func body(content: Content) -> some View { 14 | if #available(iOS 16, *) { 15 | content 16 | .scrollContentBackground(.hidden) 17 | .background(color) 18 | } else { 19 | content 20 | .introspectTableView { 21 | $0.backgroundColor = UIColor(color) 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/UIColor+CryptomatorColors.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+CryptomatorColors.swift 3 | // CryptomatorCommonCore 4 | // 5 | // Created by Philipp Schmid on 28.02.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import UIKit 11 | 12 | public extension UIColor { 13 | static var cryptomatorPrimary: UIColor { 14 | return UIColor(named: "primary")! 15 | } 16 | 17 | static var cryptomatorBackground: UIColor { 18 | return UIColor(named: "background")! 19 | } 20 | 21 | static var cryptomatorYellow: UIColor { 22 | return UIColor(named: "yellow")! 23 | } 24 | } 25 | 26 | public extension Color { 27 | static var cryptomatorPrimary: Color { Color(UIColor.cryptomatorPrimary) } 28 | static var cryptomatorBackground: Color { Color(UIColor.cryptomatorBackground) } 29 | static var cryptomatorYellow: Color { Color(UIColor.cryptomatorYellow) } 30 | } 31 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/UpgradeChecker.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UpgradeChecker.swift 3 | // CryptomatorCommonCore 4 | // 5 | // Created by Tobias Hagemann on 20.09.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public protocol UpgradeCheckerProtocol { 12 | func isEligibleForUpgrade() -> Bool 13 | } 14 | 15 | public class UpgradeChecker: UpgradeCheckerProtocol { 16 | public static var shared = UpgradeChecker() 17 | public static let upgradeURL = URL(string: "cryptomator-legacy:upgrade")! 18 | 19 | public func isEligibleForUpgrade() -> Bool { 20 | guard let data = CryptomatorKeychain.upgrade.getAsData("eligibleForUpgrade") as NSData? else { 21 | return false 22 | } 23 | var eligible = false 24 | data.getBytes(&eligible, length: MemoryLayout.size) 25 | return eligible 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/VaultAccountManagerError+Localization.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VaultAccountManagerError+Localization.swift 3 | // CryptomatorCommonCore 4 | // 5 | // Created by Philipp Schmid on 08.10.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension VaultAccountManagerError: LocalizedError { 12 | public var errorDescription: String? { 13 | switch self { 14 | case .vaultAccountAlreadyExists: 15 | return LocalizedString.getValue("vaultAccountManager.error.vaultAccountAlreadyExists") 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/VaultItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VaultItem.swift 3 | // CryptomatorCommonCore 4 | // 5 | // Created by Philipp Schmid on 24.06.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccessCore 10 | import Foundation 11 | 12 | public protocol VaultItem { 13 | var name: String { get } 14 | var vaultPath: CloudPath { get } 15 | } 16 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/VaultProviderFactory+Localization.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VaultProviderFactory+Localization.swift 3 | // CryptomatorCommonCore 4 | // 5 | // Created by Tobias Hagemann on 19.07.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccessCore 10 | import Foundation 11 | 12 | extension VaultProviderFactoryError: LocalizedError { 13 | public var errorDescription: String? { 14 | switch self { 15 | case .unsupportedVaultConfig: 16 | return LocalizedString.getValue("vaultProviderFactory.error.unsupportedVaultConfig") 17 | case let .unsupportedVaultVersion(version): 18 | return String(format: LocalizedString.getValue("vaultProviderFactory.error.unsupportedVaultVersion"), version) 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /CryptomatorCommon/Sources/CryptomatorCommonCore/WebDAV/WebDAVAuthenticatorError+Localization.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WebDAVAuthenticatorError+Localization.swift 3 | // CryptomatorCommonCore 4 | // 5 | // Created by Tobias Hagemann on 31.03.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccessCore 10 | import Foundation 11 | 12 | extension WebDAVAuthenticatorError: LocalizedError { 13 | public var errorDescription: String? { 14 | switch self { 15 | case .unsupportedProtocol: 16 | return LocalizedString.getValue("webDAVAuthenticator.error.unsupportedProtocol") 17 | case .untrustedCertificate: 18 | return LocalizedString.getValue("webDAVAuthenticator.error.untrustedCertificate") 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /CryptomatorCommon/Tests/CryptomatorCommonCoreTests/Promise+AllIgnoringResultsTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Promise+AllIgnoringResultsTests.swift 3 | // CryptomatorCommonCoreTests 4 | // 5 | // Created by Philipp Schmid on 31.03.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCommonCore 10 | import Promises 11 | import XCTest 12 | 13 | class Promise_AllIgnoringResultsTests: XCTestCase { 14 | func testWaitForAll() throws { 15 | let pending = Promise.pending() 16 | let fulfilled = Promise(()) 17 | 18 | let ignoringResultPromise = all(ignoringResult: [pending, fulfilled]) 19 | XCTAssertGetsNotExecuted(ignoringResultPromise) 20 | pending.fulfill(()) 21 | wait(for: ignoringResultPromise) 22 | } 23 | 24 | func testWaitForAllWithRejectedPromise() throws { 25 | let pending = Promise.pending() 26 | let rejected: Promise = Promise(NSError(domain: "Test", code: -100)) 27 | 28 | let ignoringResultPromise = all(ignoringResult: [pending, rejected]) 29 | XCTAssertGetsNotExecuted(ignoringResultPromise) 30 | pending.fulfill(()) 31 | wait(for: ignoringResultPromise) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /CryptomatorCommonHostedTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/Actions/FileProviderAction.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FileProviderAction.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 03.05.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public enum FileProviderAction: String { 12 | case retryFailedUpload = "org.cryptomator.ios.fileprovider.retry-failed-upload" 13 | case retryWaitingUpload = "org.cryptomator.ios.fileprovider.retry-waiting-upload" 14 | case evictFileFromCache = "org.cryptomator.ios.fileprovider.evict-file-from-cache" 15 | } 16 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/CloudPath+GetParent.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CloudPath+GetParent.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 31.03.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccessCore 10 | import Foundation 11 | 12 | extension CloudPath { 13 | /// Returns the parent of the current path. Returns nil if the current path is already the root path. 14 | func getParent() -> CloudPath? { 15 | if path == "/" { 16 | return nil 17 | } 18 | return deletingLastPathComponent() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/CloudPath+NameCollision.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CloudPath+NameCollision.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 18.09.20. 6 | // Copyright © 2020 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccessCore 10 | import Foundation 11 | 12 | public extension CloudPath { 13 | func createCollisionCloudPath(conflictResolvingAddition: String) -> CloudPath { 14 | let pathExtension = self.pathExtension 15 | let urlWithoutExtension = deletingPathExtension() 16 | let itemName = urlWithoutExtension.lastPathComponent 17 | let urlWithoutLastPathComponentPath = urlWithoutExtension.deletingLastPathComponent().path 18 | return CloudPath(urlWithoutLastPathComponentPath + (urlWithoutLastPathComponentPath == "/" ? "" : "/") + itemName + " (\(conflictResolvingAddition))" + (pathExtension.isEmpty ? "" : ".") + pathExtension) 19 | } 20 | 21 | func createCollisionCloudPath() -> CloudPath { 22 | let conflictHash = UUID().uuidString.prefix(5) 23 | return createCollisionCloudPath(conflictResolvingAddition: String(conflictHash)) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/CloudTask/CloudTask.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CloudTask.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 18.05.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccessCore 10 | import Foundation 11 | 12 | protocol CloudTask { 13 | var itemMetadata: ItemMetadata { get } 14 | } 15 | 16 | extension CloudTask { 17 | var cloudPath: CloudPath { 18 | return itemMetadata.cloudPath 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/CloudTask/DeletionTask.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DeletionTask.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 12.09.20. 6 | // Copyright © 2020 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import GRDB 10 | 11 | struct DeletionTask: CloudTask, FetchableRecord, Decodable { 12 | let taskRecord: DeletionTaskRecord 13 | let itemMetadata: ItemMetadata 14 | 15 | enum CodingKeys: String, CodingKey { 16 | case taskRecord = "deletionTask" 17 | case itemMetadata 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/CloudTask/DownloadTask.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DownloadTask.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 27.05.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import GRDB 11 | 12 | struct DownloadTask: CloudTask { 13 | let taskRecord: DownloadTaskRecord 14 | let itemMetadata: ItemMetadata 15 | let onURLSessionTaskCreation: URLSessionTaskCreationClosure? 16 | 17 | enum CodingKeys: String, CodingKey { 18 | case taskRecord = "downloadTask" 19 | case itemMetadata 20 | } 21 | } 22 | 23 | typealias URLSessionTaskCreationClosure = (URLSessionTask) -> Void 24 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/CloudTask/FolderCreationTask.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FolderCreationTask.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 07.06.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct FolderCreationTask: CloudTask { 12 | let itemMetadata: ItemMetadata 13 | } 14 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/CloudTask/ItemEnumerationTask.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ItemEnumerationTask.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 29.05.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import GRDB 11 | 12 | struct ItemEnumerationTask: CloudTask { 13 | let taskRecord: ItemEnumerationTaskRecord 14 | let itemMetadata: ItemMetadata 15 | 16 | enum CodingKeys: String, CodingKey { 17 | case taskRecord = "itemEnumerationTask" 18 | case itemMetadata 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/CloudTask/ReparentTask.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReparentTask.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 22.07.20. 6 | // Copyright © 2020 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import GRDB 10 | 11 | struct ReparentTask: CloudTask, FetchableRecord, Decodable { 12 | let taskRecord: ReparentTaskRecord 13 | let itemMetadata: ItemMetadata 14 | 15 | enum CodingKeys: String, CodingKey { 16 | case taskRecord = "reparentTask" 17 | case itemMetadata 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/CloudTask/UploadTask.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UploadTask.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 08.07.20. 6 | // Copyright © 2020 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import GRDB 11 | 12 | struct UploadTask: CloudTask { 13 | let taskRecord: UploadTaskRecord 14 | let itemMetadata: ItemMetadata 15 | let onURLSessionTaskCreation: URLSessionTaskCreationClosure? 16 | } 17 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/CryptomatorFileProvider.h: -------------------------------------------------------------------------------- 1 | // 2 | // CryptomatorFileProvider.h 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 24.06.20. 6 | // Copyright © 2020 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for CryptomatorFileProvider. 12 | FOUNDATION_EXPORT double CryptomatorFileProviderVersionNumber; 13 | 14 | //! Project version string for CryptomatorFileProvider. 15 | FOUNDATION_EXPORT const unsigned char CryptomatorFileProviderVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/DB/DBManagerError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DBManagerError.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 09.06.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum DBManagerError: Error { 12 | case missingItemMetadata 13 | case nonSavedItemMetadata 14 | case taskNotFound 15 | } 16 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/DB/DownloadTaskRecord.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DownloadTaskRecord.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 19.10.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import GRDB 11 | 12 | struct DownloadTaskRecord: Decodable, FetchableRecord, TableRecord { 13 | static let databaseTableName = "downloadTasks" 14 | let correspondingItem: Int64 15 | let replaceExisting: Bool 16 | let localURL: URL 17 | 18 | enum Columns: String, ColumnExpression { 19 | case correspondingItem, replaceExisting, localURL 20 | } 21 | } 22 | 23 | extension DownloadTaskRecord: PersistableRecord { 24 | func encode(to container: inout PersistenceContainer) throws { 25 | container[Columns.correspondingItem] = correspondingItem 26 | container[Columns.replaceExisting] = replaceExisting 27 | container[Columns.localURL] = localURL 28 | } 29 | } 30 | 31 | extension DownloadTaskRecord { 32 | static let itemMetadata = belongsTo(ItemMetadata.self) 33 | var itemMetadata: QueryInterfaceRequest { 34 | request(for: DownloadTaskRecord.itemMetadata) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/DB/ItemEnumerationTaskRecord.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ItemEnumerationTaskRecord.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 19.10.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import GRDB 11 | 12 | struct ItemEnumerationTaskRecord: Decodable, FetchableRecord, TableRecord { 13 | static let databaseTableName = "itemEnumerationTasks" 14 | let correspondingItem: Int64 15 | let pageToken: String? 16 | 17 | enum Columns: String, ColumnExpression { 18 | case correspondingItem, pageToken 19 | } 20 | } 21 | 22 | extension ItemEnumerationTaskRecord: PersistableRecord { 23 | func encode(to container: inout PersistenceContainer) throws { 24 | container[Columns.correspondingItem] = correspondingItem 25 | container[Columns.pageToken] = pageToken 26 | } 27 | } 28 | 29 | extension ItemEnumerationTaskRecord { 30 | static let itemMetadata = belongsTo(ItemMetadata.self) 31 | var itemMetadata: QueryInterfaceRequest { 32 | request(for: ItemEnumerationTaskRecord.itemMetadata) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/DB/TaskError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TaskError.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 08.07.20. 6 | // Copyright © 2020 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum TaskError: Error { 12 | case taskNotFound 13 | } 14 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/DatabaseURLProvider.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DatabaseURLProvider.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 10.05.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import FileProvider 10 | import Foundation 11 | 12 | public struct DatabaseURLProvider { 13 | public static let shared = DatabaseURLProvider(documentStorageURLProvider: NSFileProviderManager.default) 14 | let documentStorageURLProvider: DocumentStorageURLProvider 15 | 16 | public func getDatabaseURL(for domain: NSFileProviderDomain) -> URL { 17 | let documentStorageURL = documentStorageURLProvider.documentStorageURL 18 | let domainURL = documentStorageURL.appendingPathComponent(domain.pathRelativeToDocumentStorage, isDirectory: true) 19 | return domainURL.appendingPathComponent("db.sqlite", isDirectory: false) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/DocumentStorageURLProvider.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DocumentStorageURLProvider.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 05.10.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import FileProvider 10 | import Foundation 11 | 12 | public protocol DocumentStorageURLProvider { 13 | var documentStorageURL: URL { get } 14 | } 15 | 16 | extension NSFileProviderManager: DocumentStorageURLProvider {} 17 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/FileProviderAdapterError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FileProviderAdapterError.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 24.06.20. 6 | // Copyright © 2020 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum FileProviderAdapterError: Error { 12 | case unsupportedItemIdentifier 13 | case folderUploadNotSupported 14 | case parentFolderNotFound 15 | case parentItemTypeMismatch 16 | case unsupportedItemType 17 | } 18 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/FileProviderItemList.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FileProviderItemList.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 25.06.20. 6 | // Copyright © 2020 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import FileProvider 10 | import Foundation 11 | 12 | public struct FileProviderItemList { 13 | public let items: [FileProviderItem] 14 | public let nextPageToken: NSFileProviderPage? 15 | } 16 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/ItemStatus.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ItemStatus.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 25.06.20. 6 | // Copyright © 2020 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public enum ItemStatus: String, Codable { 12 | case isUploading 13 | case isUploaded 14 | case uploadError 15 | case isDownloading 16 | case downloadError 17 | } 18 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/Locks/LockNode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LockNode.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 27.11.20. 6 | // Copyright © 2020 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CocoaLumberjackSwift 10 | import Foundation 11 | 12 | class LockNode { 13 | private let lock: RWLock 14 | private let parent: LockNode? 15 | // path only for debug / log 16 | private let path: String 17 | 18 | init(path: String, lock: RWLock, parent: LockNode? = nil) { 19 | self.path = path 20 | self.lock = lock 21 | self.parent = parent 22 | } 23 | 24 | func readLock() { 25 | DDLogDebug("readLock \(path)(\(Unmanaged.passUnretained(self).toOpaque())) called") 26 | lock.readLock() 27 | DDLogDebug("readLock \(path)(\(Unmanaged.passUnretained(self).toOpaque())) done") 28 | } 29 | 30 | func writeLock() { 31 | DDLogDebug("writeLock \(path)(\(Unmanaged.passUnretained(self).toOpaque())) called") 32 | lock.writeLock() 33 | DDLogDebug("writeLock \(path)(\(Unmanaged.passUnretained(self).toOpaque())) done") 34 | } 35 | 36 | func unlock() { 37 | lock.unlock() 38 | parent?.unlock() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/Locks/RWLock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RWLock.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 27.11.20. 6 | // Copyright © 2020 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | final class RWLock { 12 | private var lock: pthread_rwlock_t 13 | 14 | init() { 15 | self.lock = pthread_rwlock_t() 16 | pthread_rwlock_init(&lock, nil) 17 | } 18 | 19 | deinit { 20 | pthread_rwlock_destroy(&lock) 21 | } 22 | 23 | func writeLock() { 24 | pthread_rwlock_wrlock(&lock) 25 | } 26 | 27 | func readLock() { 28 | pthread_rwlock_rdlock(&lock) 29 | } 30 | 31 | func unlock() { 32 | pthread_rwlock_unlock(&lock) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/NSFileProviderDomainProvider.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSFileProviderDomainProvider.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 10.05.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCommonCore 10 | import FileProvider 11 | import Foundation 12 | import Promises 13 | 14 | protocol NSFileProviderDomainProvider { 15 | func getDomains() -> Promise<[NSFileProviderDomain]> 16 | } 17 | 18 | extension NSFileProviderManager: NSFileProviderDomainProvider { 19 | func getDomains() -> Promise<[NSFileProviderDomain]> { 20 | return NSFileProviderManager.getDomains() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/RootFileProviderItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RootFileProviderItem.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 11.06.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCommonCore 10 | import Dependencies 11 | import FileProvider 12 | import Foundation 13 | import MobileCoreServices 14 | 15 | public class RootFileProviderItem: NSObject, NSFileProviderItem { 16 | public var itemIdentifier = NSFileProviderItemIdentifier.rootContainer 17 | public let parentItemIdentifier = NSFileProviderItemIdentifier.rootContainer 18 | public let filename = "Cryptomator" 19 | public let typeIdentifier = kUTTypeFolder as String 20 | public let documentSize: NSNumber? = nil 21 | public var capabilities: NSFileProviderItemCapabilities { 22 | return permissionProvider.getPermissionsForRootItem(at: domain?.identifier) 23 | } 24 | 25 | private let domain: NSFileProviderDomain? 26 | @Dependency(\.permissionProvider) private var permissionProvider 27 | 28 | public init(domain: NSFileProviderDomain?) { 29 | self.domain = domain 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/ServiceSource/LogLevelUpdatingServiceSource.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LogLevelUpdatingServiceSource.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 11.10.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CocoaLumberjackSwift 10 | import CryptomatorCommonCore 11 | import FileProvider 12 | import Foundation 13 | 14 | public class LogLevelUpdatingServiceSource: ServiceSource, LogLevelUpdating { 15 | private let cryptomatorSettings: CryptomatorSettings 16 | 17 | init(cryptomatorSettings: CryptomatorSettings) { 18 | self.cryptomatorSettings = cryptomatorSettings 19 | super.init(serviceName: .logLevelUpdating, exportedInterface: NSXPCInterface(with: LogLevelUpdating.self)) 20 | } 21 | 22 | public convenience init() { 23 | self.init(cryptomatorSettings: CryptomatorUserDefaults.shared) 24 | } 25 | 26 | // MARK: - LogLevelUpdating 27 | 28 | public func logLevelUpdated() { 29 | LoggerSetup.setDynamicLogLevel(debugModeEnabled: cryptomatorSettings.debugModeEnabled) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/SessionTaskRegistrator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SessionTaskRegistrator.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 30.11.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import FileProvider 10 | import Foundation 11 | 12 | public protocol SessionTaskRegistrator { 13 | func register(_ task: SessionTask, forItemWithIdentifier identifier: NSFileProviderItemIdentifier, completionHandler completion: @escaping (Error?) -> Void) 14 | } 15 | 16 | public protocol SessionTask {} 17 | 18 | extension URLSessionTask: SessionTask {} 19 | 20 | extension NSFileProviderManager: SessionTaskRegistrator { 21 | public func register(_ task: SessionTask, forItemWithIdentifier identifier: NSFileProviderItemIdentifier, completionHandler completion: @escaping (Error?) -> Void) { 22 | guard let urlSessionTask = task as? URLSessionTask else { 23 | completion(UnexpectedSessionTaskTypeError()) 24 | return 25 | } 26 | register(urlSessionTask, forItemWithIdentifier: identifier, completionHandler: completion) 27 | } 28 | } 29 | 30 | struct UnexpectedSessionTaskTypeError: Error {} 31 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/URL+NameCollisionExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // URL+NameCollisionExtension.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 10.07.20. 6 | // Copyright © 2020 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension URL { 12 | func createCollisionURL(conflictResolvingAddition: String) -> URL { 13 | precondition(isFileURL) 14 | 15 | let pathExtension = self.pathExtension 16 | let urlWithoutExtension = deletingPathExtension() 17 | let itemName = urlWithoutExtension.lastPathComponent 18 | let urlWithoutLastPathComponentPath = urlWithoutExtension.deletingLastPathComponent().path 19 | 20 | return URL(fileURLWithPath: urlWithoutLastPathComponentPath + (urlWithoutLastPathComponentPath == "/" ? "" : "/") + itemName + " (\(conflictResolvingAddition))" + (pathExtension.isEmpty ? "" : ".") + pathExtension, isDirectory: hasDirectoryPath) 21 | } 22 | 23 | func createCollisionURL() -> URL { 24 | precondition(isFileURL) 25 | let conflictHash = UUID().uuidString.prefix(5) 26 | return createCollisionURL(conflictResolvingAddition: String(conflictHash)) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/Workflow/Workflow.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Workflow.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 28.05.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class Workflow { 12 | init(middleware: AnyWorkflowMiddleware, task: CloudTask, constraint: WorkflowConstraint) { 13 | self.middleware = middleware 14 | self.task = task 15 | self.constraint = constraint 16 | } 17 | 18 | let middleware: AnyWorkflowMiddleware 19 | let task: CloudTask 20 | let constraint: WorkflowConstraint 21 | } 22 | -------------------------------------------------------------------------------- /CryptomatorFileProvider/Workflow/WorkflowConstraint.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WorkflowConstraint.swift 3 | // CryptomatorFileProvider 4 | // 5 | // Created by Philipp Schmid on 10.06.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum WorkflowConstraint { 12 | case unconstrained 13 | case downloadConstrained 14 | case uploadConstrained 15 | } 16 | -------------------------------------------------------------------------------- /CryptomatorFileProviderTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /CryptomatorFileProviderTests/Middleware/WorkflowMiddlewareMock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WorkflowMiddlewareMock.swift 3 | // CryptomatorFileProviderTests 4 | // 5 | // Created by Philipp Schmid on 25.05.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Promises 11 | @testable import CryptomatorFileProvider 12 | 13 | class WorkflowMiddlewareMock: WorkflowMiddleware { 14 | private var next: AnyWorkflowMiddleware? 15 | private let _execute: (CloudTask) -> Promise 16 | 17 | init(execute: @escaping (CloudTask) -> Promise) { 18 | self._execute = execute 19 | } 20 | 21 | func setNext(_ next: AnyWorkflowMiddleware) { 22 | self.next = next 23 | } 24 | 25 | func getNext() throws -> AnyWorkflowMiddleware { 26 | guard let nextMiddleware = next else { 27 | throw WorkflowMiddlewareError.missingMiddleware 28 | } 29 | return nextMiddleware 30 | } 31 | 32 | func execute(task: CloudTask) -> Promise { 33 | _execute(task) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /CryptomatorFileProviderTests/Mocks/DocumentStorageURLProviderMock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DocumentStorageURLProviderMock.swift 3 | // CryptomatorFileProviderTests 4 | // 5 | // Created by Philipp Schmid on 04.03.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorFileProvider 10 | import Foundation 11 | 12 | class DocumentStorageURLProviderMock: DocumentStorageURLProvider { 13 | private let tmpDirURL: URL 14 | 15 | init(tmpDirURL: URL) { 16 | self.tmpDirURL = tmpDirURL 17 | } 18 | 19 | var documentStorageURL: URL { 20 | return tmpDirURL 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CryptomatorFileProviderTests/Mocks/NSFileProviderDomainProviderMock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSFileProviderDomainProviderMock.swift 3 | // CryptomatorFileProviderTests 4 | // 5 | // Created by Philipp Schmid on 10.05.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import FileProvider 10 | import Foundation 11 | import Promises 12 | @testable import CryptomatorFileProvider 13 | 14 | // swiftlint:disable all 15 | 16 | final class NSFileProviderDomainProviderMock: NSFileProviderDomainProvider { 17 | // MARK: - getDomains 18 | 19 | var getDomainsThrowableError: Error? 20 | var getDomainsCallsCount = 0 21 | var getDomainsCalled: Bool { 22 | getDomainsCallsCount > 0 23 | } 24 | 25 | var getDomainsReturnValue: Promise<[NSFileProviderDomain]>! 26 | var getDomainsClosure: (() -> Promise<[NSFileProviderDomain]>)? 27 | 28 | func getDomains() -> Promise<[NSFileProviderDomain]> { 29 | if let error = getDomainsThrowableError { 30 | return Promise(error) 31 | } 32 | getDomainsCallsCount += 1 33 | return getDomainsClosure.map({ $0() }) ?? getDomainsReturnValue 34 | } 35 | } 36 | 37 | // swiftlint:enable all 38 | -------------------------------------------------------------------------------- /CryptomatorFileProviderTests/Mocks/WorkingSetObservingMock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WorkingSetObservingMock.swift 3 | // CryptomatorFileProviderTests 4 | // 5 | // Created by Philipp Schmid on 24.01.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | @testable import CryptomatorFileProvider 11 | 12 | final class WorkingSetObservingMock: WorkingSetObserving { 13 | // MARK: - startObservation 14 | 15 | var startObservationCallsCount = 0 16 | var startObservationCalled: Bool { 17 | startObservationCallsCount > 0 18 | } 19 | 20 | var startObservationClosure: (() -> Void)? 21 | 22 | func startObservation() { 23 | startObservationCallsCount += 1 24 | startObservationClosure?() 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CryptomatorFileProviderTests/ServiceSource/LogLevelUpdatingServiceSourceTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LogLevelUpdatingServiceSourceTests.swift 3 | // CryptomatorFileProviderTests 4 | // 5 | // Created by Philipp Schmid on 11.10.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CocoaLumberjackSwift 10 | import XCTest 11 | @testable import CryptomatorCommonCore 12 | @testable import CryptomatorFileProvider 13 | 14 | class LogLevelUpdatingServiceSourceTests: XCTestCase { 15 | private var cryptomatorSettingsMock: CryptomatorSettingsMock! 16 | private var serviceSouce: LogLevelUpdatingServiceSource! 17 | 18 | override func setUpWithError() throws { 19 | cryptomatorSettingsMock = CryptomatorSettingsMock() 20 | serviceSouce = LogLevelUpdatingServiceSource(cryptomatorSettings: cryptomatorSettingsMock) 21 | } 22 | 23 | func testLogLevelUpdated() throws { 24 | cryptomatorSettingsMock.debugModeEnabled = false 25 | serviceSouce.logLevelUpdated() 26 | XCTAssertEqual(.error, dynamicLogLevel) 27 | 28 | cryptomatorSettingsMock.debugModeEnabled = true 29 | serviceSouce.logLevelUpdated() 30 | XCTAssertEqual(.debug, dynamicLogLevel) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /CryptomatorIntents/CryptomatorIntents.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.org.cryptomator.ios 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /CryptomatorIntents/GetFolderIntentHandlerError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GetFolderIntentHandlerError.swift 3 | // CryptomatorIntents 4 | // 5 | // Created by Philipp Schmid on 24.05.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCommonCore 10 | import Foundation 11 | 12 | enum GetFolderIntentHandlerError: Error, LocalizedError { 13 | case missingPath 14 | case noVaultSelected 15 | 16 | var errorDescription: String? { 17 | switch self { 18 | case .missingPath: 19 | return LocalizedString.getValue("getFolderIntent.error.missingPath") 20 | case .noVaultSelected: 21 | return LocalizedString.getValue("getFolderIntent.error.noVaultSelected") 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /CryptomatorIntents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDisplayName 6 | Cryptomator 7 | CFBundleIdentifier 8 | $(PRODUCT_BUNDLE_IDENTIFIER) 9 | NSExtension 10 | 11 | NSExtensionAttributes 12 | 13 | IntentsRestrictedWhileLocked 14 | 15 | IntentsRestrictedWhileProtectedDataUnavailable 16 | 17 | IntentsSupported 18 | 19 | GetFolderIntent 20 | IsVaultUnlockedIntent 21 | LockVaultIntent 22 | OpenVaultIntent 23 | SaveFileIntent 24 | 25 | 26 | NSExtensionPointIdentifier 27 | com.apple.intents-service 28 | NSExtensionPrincipalClass 29 | $(PRODUCT_MODULE_NAME).IntentHandler 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /CryptomatorIntents/IntentHandler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IntentHandler.swift 3 | // CryptomatorIntents 4 | // 5 | // Created by Philipp Schmid on 13.05.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CocoaLumberjackSwift 10 | import CryptomatorCommonCore 11 | import Intents 12 | 13 | class IntentHandler: INExtension { 14 | override func handler(for intent: INIntent) -> Any { 15 | IntentHandler.oneTimeSetup() 16 | if intent is SaveFileIntent { 17 | return SaveFileIntentHandler() 18 | } 19 | if intent is GetFolderIntent { 20 | return GetFolderIntentHandler(vaultOptionsProvider: .shared) 21 | } 22 | if intent is LockVaultIntent { 23 | return LockVaultIntentHandler(vaultOptionsProvider: .shared) 24 | } 25 | if intent is OpenVaultIntent { 26 | return OpenVaultIntentHandler(vaultOptionsProvider: .shared) 27 | } 28 | if intent is IsVaultUnlockedIntent { 29 | return IsVaultUnlockedIntentHandler(vaultOptionsProvider: .shared) 30 | } 31 | return self 32 | } 33 | 34 | private static var oneTimeSetup: () -> Void = { 35 | // Set up logger 36 | LoggerSetup.oneTimeSetup() 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /CryptomatorIntents/af.lproj/Intents.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/CryptomatorIntents/af.lproj/Intents.strings -------------------------------------------------------------------------------- /CryptomatorIntents/be.lproj/Intents.strings: -------------------------------------------------------------------------------- 1 | "common.vault" = "Скарбніца"; 2 | "isUnlockedIntent.title" = "Разамкнёны"; 3 | 4 | "isVaultLockedIntent.title" = "Ці разамкнёна скарбніца"; 5 | "isVaultUnlockedIntent.text" = "Ці ${vault} разамкнёны?"; 6 | "openVaultIntent.title" = "Адчыніць скарбніцу"; 7 | 8 | "saveFileIntent.description" = "Захаваць файл у скарбніцы."; 9 | "saveFileIntent.file" = "Файл"; 10 | "saveFileIntent.title" = "Захаваць файл"; 11 | 12 | "vaultFolder.displayName" = "Тэчка скарбніцы"; 13 | "vaultFolder.vaultIdentifier" = "Ідэнтыфікатар скарбніцы"; 14 | -------------------------------------------------------------------------------- /CryptomatorIntents/bg.lproj/Intents.strings: -------------------------------------------------------------------------------- 1 | "common.vault" = "Хранилище"; 2 | -------------------------------------------------------------------------------- /CryptomatorIntents/bn.lproj/Intents.strings: -------------------------------------------------------------------------------- 1 | "common.vault" = "ভোল্ট"; 2 | -------------------------------------------------------------------------------- /CryptomatorIntents/bs.lproj/Intents.strings: -------------------------------------------------------------------------------- 1 | "common.vault" = "Sef"; 2 | -------------------------------------------------------------------------------- /CryptomatorIntents/fa.lproj/Intents.strings: -------------------------------------------------------------------------------- 1 | "common.false" = "غلط"; 2 | "common.folder" = "پوشه"; 3 | "common.true" = "درست"; 4 | "common.vault" = "گاوصندوق"; 5 | "getFolderIntent.path" = "مسیر"; 6 | "getFolderIntent.title" = "دریافت پوشه"; 7 | "isUnlockedIntent.title" = "باز شده است"; 8 | 9 | "isVaultLockedIntent.title" = "گاوصندوق باز شده است"; 10 | "isVaultUnlockedIntent.text" = "آیا ${vault} باز شده است؟"; 11 | "lockVaultIntent.text" = "قفل کردن ${vault}"; 12 | "lockVaultIntent.title" = "قفل کردن گاوصندوق"; 13 | "openVaultIntent.title" = "باز کردن گاوصندوق"; 14 | 15 | "saveFileIntent.description" = "یک فایل در گاوصندوق ذخیره میشود."; 16 | "saveFileIntent.file" = "فایل"; 17 | "saveFileIntent.text" = "ذخیره ${file} در ${folder}"; 18 | "saveFileIntent.title" = "دخیرهٔ پرونده‌"; 19 | 20 | "vaultFolder.displayName" = "پوشه گاوصندوق"; 21 | "vaultFolder.vaultIdentifier" = "مشخص کننده گاوصندوق"; 22 | -------------------------------------------------------------------------------- /CryptomatorIntents/fi.lproj/Intents.strings: -------------------------------------------------------------------------------- 1 | "common.vault" = "Holvi"; 2 | -------------------------------------------------------------------------------- /CryptomatorIntents/gl.lproj/Intents.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/CryptomatorIntents/gl.lproj/Intents.strings -------------------------------------------------------------------------------- /CryptomatorIntents/hi.lproj/Intents.strings: -------------------------------------------------------------------------------- 1 | "common.vault" = "वॉल्ट"; 2 | 3 | "isUnlockedIntent.description" = "बताता है कि वॉल्ट उनलॉकेड है या नहीं।"; 4 | "isUnlockedIntent.title" = "उनलॉकेड है"; 5 | 6 | "isVaultLockedIntent.title" = "क्या वॉल्ट उनलॉकेड है"; 7 | "isVaultUnlockedIntent.text" = "क्या ${vault} उनलॉकेड है?"; 8 | 9 | "lockVaultIntent.description" = "दी गयी वॉल्ट को लॉक कर देता है।"; 10 | "lockVaultIntent.text" = "लॉक ${vault}"; 11 | "lockVaultIntent.title" = "वॉल्ट को लॉक करें"; 12 | 13 | "openVaultIntent.description" = "दी गई वॉल्ट को फाइल्स ऐप पर खोलें"; 14 | "openVaultIntent.text" = "${vault} को फाइल्स ऐप पर खोलें"; 15 | "openVaultIntent.title" = "वॉल्ट खोले"; 16 | -------------------------------------------------------------------------------- /CryptomatorIntents/hr.lproj/Intents.strings: -------------------------------------------------------------------------------- 1 | "common.failureReason" = "Razlog neuspjeha"; 2 | "common.false" = "netočno"; 3 | "common.folder" = "Mapa"; 4 | "common.true" = "točno"; 5 | "common.vault" = "Trezor"; 6 | 7 | "getFolderIntent.description" = "Vraća mapu za odabranu putanju u odabranom trezoru."; 8 | "getFolderIntent.path" = "Putanja"; 9 | "getFolderIntent.text" = "Dohvati mapu smještenu na ${path} u ${vault}"; 10 | "getFolderIntent.title" = "Dohvati mapu"; 11 | 12 | "saveFileIntent.description" = "Sprema datoteku u trezor."; 13 | "saveFileIntent.file" = "Datoteka"; 14 | "saveFileIntent.parameter.ignoreExisting" = "Zanemari postojeću datoteku s istim imenom"; 15 | "saveFileIntent.text" = "Spremi ${file} u ${folder}"; 16 | "saveFileIntent.title" = "Spremi datoteku"; 17 | 18 | "vaultFolder.displayName" = "Mapa trezora"; 19 | "vaultFolder.vaultIdentifier" = "Identifikator trezora"; 20 | -------------------------------------------------------------------------------- /CryptomatorIntents/hu.lproj/Intents.strings: -------------------------------------------------------------------------------- 1 | "common.false" = "hamis"; 2 | "common.folder" = "Mappa"; 3 | "common.true" = "igaz"; 4 | "common.vault" = "Széf"; 5 | 6 | "getFolderIntent.description" = "Visszaad egy mappa objektumot a megadott útvonalhoz a megadott széfben."; 7 | "getFolderIntent.path" = "Útvonal"; 8 | "getFolderIntent.text" = "Visszaadja a mappát ezen a helyen: ${path}, ebben a széfben: ${vault}"; 9 | 10 | "isUnlockedIntent.description" = "Visszaadja, hogy az adott széf fel van-e oldva."; 11 | "lockVaultIntent.text" = "${vault} zárolása"; 12 | "lockVaultIntent.title" = "Széf zárolása"; 13 | 14 | "openVaultIntent.description" = "Megnyitja az adott széfet a Fájlok appban."; 15 | "openVaultIntent.text" = "${vault} megnyitása a Fájlok appban"; 16 | "openVaultIntent.title" = "Széf megnyitása"; 17 | 18 | "saveFileIntent.description" = "Elment egy fájlt egy széfbe."; 19 | 20 | "vaultFolder.displayName" = "Széf mappa"; 21 | "vaultFolder.vaultIdentifier" = "Széf azonosító"; 22 | -------------------------------------------------------------------------------- /CryptomatorIntents/mk.lproj/Intents.strings: -------------------------------------------------------------------------------- 1 | "common.vault" = "Сеф"; 2 | -------------------------------------------------------------------------------- /CryptomatorIntents/mr.lproj/Intents.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/CryptomatorIntents/mr.lproj/Intents.strings -------------------------------------------------------------------------------- /CryptomatorIntents/nn-NO.lproj/Intents.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/CryptomatorIntents/nn-NO.lproj/Intents.strings -------------------------------------------------------------------------------- /CryptomatorIntents/no.lproj/Intents.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/CryptomatorIntents/no.lproj/Intents.strings -------------------------------------------------------------------------------- /CryptomatorIntents/si.lproj/Intents.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/CryptomatorIntents/si.lproj/Intents.strings -------------------------------------------------------------------------------- /CryptomatorIntents/sr-Latn.lproj/Intents.strings: -------------------------------------------------------------------------------- 1 | "common.vault" = "Sef"; 2 | -------------------------------------------------------------------------------- /CryptomatorIntents/sr.lproj/Intents.strings: -------------------------------------------------------------------------------- 1 | "common.vault" = "Sef"; 2 | -------------------------------------------------------------------------------- /CryptomatorIntents/ta.lproj/Intents.strings: -------------------------------------------------------------------------------- 1 | "common.false" = "தவறு"; 2 | "common.vault" = "பெட்டகம்"; 3 | -------------------------------------------------------------------------------- /CryptomatorIntents/te.lproj/Intents.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/CryptomatorIntents/te.lproj/Intents.strings -------------------------------------------------------------------------------- /CryptomatorIntents/th.lproj/Intents.strings: -------------------------------------------------------------------------------- 1 | "common.failureReason" = "สาเหตุความขัดข้อง"; 2 | "common.false" = "เท็จ"; 3 | "common.folder" = "โฟลเดอร์"; 4 | "common.true" = "ถูกต้อง"; 5 | "common.vault" = "Vault"; 6 | "getFolderIntent.path" = "ที่อยู่"; 7 | "isUnlockedIntent.title" = "ปลดล็อกแล้ว"; 8 | 9 | "lockVaultIntent.description" = "ล็อก vault ที่กำหนด"; 10 | "lockVaultIntent.title" = "ล็อก Vault"; 11 | "openVaultIntent.title" = "เปิด Vault"; 12 | 13 | "saveFileIntent.description" = "บันทึกไฟล์ลงใน vault"; 14 | "saveFileIntent.file" = "ไฟล์"; 15 | "saveFileIntent.title" = "บันทึกไฟล์"; 16 | -------------------------------------------------------------------------------- /CryptomatorIntents/ug.lproj/Intents.strings: -------------------------------------------------------------------------------- 1 | "common.vault" = "ئامبار"; 2 | -------------------------------------------------------------------------------- /CryptomatorIntents/ur.lproj/Intents.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/CryptomatorIntents/ur.lproj/Intents.strings -------------------------------------------------------------------------------- /CryptomatorIntents/vi.lproj/Intents.strings: -------------------------------------------------------------------------------- 1 | "common.failureReason" = "Lý do thất bại"; 2 | "common.false" = "sai"; 3 | "common.folder" = "Thư mục"; 4 | "common.true" = "đúng"; 5 | "common.vault" = "Vault"; 6 | "getFolderIntent.path" = "Đường dẫn"; 7 | "isUnlockedIntent.title" = "Đã mở khóa"; 8 | "lockVaultIntent.text" = "Khóa ${vault}"; 9 | "lockVaultIntent.title" = "Khóa Vault"; 10 | "openVaultIntent.title" = "Mở Vault"; 11 | "saveFileIntent.file" = "Tệp"; 12 | "saveFileIntent.text" = "Lưu ${file} vào ${folder}"; 13 | "saveFileIntent.title" = "Lưu tệp"; 14 | -------------------------------------------------------------------------------- /CryptomatorTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /CryptomatorTests/MockError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MockError.swift 3 | // CryptomatorTests 4 | // 5 | // Created by Philipp Schmid on 29.06.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum MockError: Error { 12 | case notMocked 13 | } 14 | -------------------------------------------------------------------------------- /CryptomatorTests/Mocks/TLSCertificateValidationHelperMock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TLSCertificateValidationHelperMock.swift 3 | // CryptomatorTests 4 | // 5 | // Created by Philipp Schmid on 28.08.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import CryptomatorCloudAccessCore 10 | import Foundation 11 | import Promises 12 | @testable import Cryptomator 13 | 14 | // swiftlint:disable all 15 | final class TLSCertificateValidationHelpingMock: TLSCertificateValidationHelping { 16 | // MARK: - validate 17 | 18 | var validateUrlCallsCount = 0 19 | var validateUrlCalled: Bool { 20 | validateUrlCallsCount > 0 21 | } 22 | 23 | var validateUrlReceivedUrl: URL? 24 | var validateUrlReceivedInvocations: [URL] = [] 25 | var validateUrlReturnValue: Promise! 26 | var validateUrlClosure: ((URL) -> Promise)? 27 | 28 | func validate(url: URL) -> Promise { 29 | validateUrlCallsCount += 1 30 | validateUrlReceivedUrl = url 31 | validateUrlReceivedInvocations.append(url) 32 | return validateUrlClosure.map({ $0(url) }) ?? validateUrlReturnValue 33 | } 34 | } 35 | 36 | // swiftlint:enable all 37 | -------------------------------------------------------------------------------- /CryptomatorTests/XCTest+Async.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCTest+Async.swift 3 | // CryptomatorTests 4 | // 5 | // Created by Philipp Schmid on 26.10.22. 6 | // Copyright © 2022 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import XCTest 11 | 12 | extension XCTest { 13 | func XCTAssertThrowsAsyncError( 14 | _ expression: @autoclosure () async throws -> T, 15 | _ message: @autoclosure () -> String = "", 16 | file: StaticString = #filePath, 17 | line: UInt = #line, 18 | _ errorHandler: (_ error: Error) -> Void = { _ in } 19 | ) async { 20 | do { 21 | _ = try await expression() 22 | XCTFail(message(), file: file, line: line) 23 | } catch { 24 | errorHandler(error) 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /FileProviderExtension/FileProviderExtension-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #if DEBUG 6 | #import "FileProviderValidationServiceSource.h" 7 | #endif 8 | -------------------------------------------------------------------------------- /FileProviderExtension/FileProviderExtension.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.default-data-protection 6 | NSFileProtectionCompleteUntilFirstUserAuthentication 7 | com.apple.security.application-groups 8 | 9 | group.org.cryptomator.ios 10 | 11 | keychain-access-groups 12 | 13 | $(AppIdentifierPrefix)org.cryptomator.ios 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /FileProviderExtension/FileProviderValidationServiceSource.h: -------------------------------------------------------------------------------- 1 | // 2 | // FileProviderValidationServiceSource.h 3 | // 4 | // Copyright © 2018 Apple. All rights reserved. 5 | // 6 | 7 | #if DEBUG 8 | #import 9 | #import 10 | 11 | @interface FileProviderValidationServiceSource : NSObject 12 | 13 | - (instancetype)initWithFileProviderExtension:(NSFileProviderExtension *)fileProviderExtension 14 | itemIdentifier:(NSFileProviderItemIdentifier)itemIdentifier; 15 | 16 | @end 17 | #endif 18 | -------------------------------------------------------------------------------- /FileProviderExtension/Snapshots/VaultUnlockingServiceSourceSnapshotMock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VaultUnlockingServiceSourceSnapshotMock.swift 3 | // FileProviderExtension 4 | // 5 | // Created by Philipp Schmid on 14.12.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | #if SNAPSHOTS 10 | import Foundation 11 | @testable import CryptomatorFileProvider 12 | 13 | class VaultUnlockingServiceSourceSnapshotMock: VaultUnlockingServiceSource { 14 | override func unlockVault(kek: [UInt8], reply: @escaping (NSError?) -> Void) { 15 | FileProviderEnumeratorSnapshotMock.isUnlocked = true 16 | reply(nil) 17 | } 18 | } 19 | #endif 20 | -------------------------------------------------------------------------------- /FileProviderExtensionUI/FileProviderCoordinatorError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FileProviderCoordinatorError.swift 3 | // Cryptomator 4 | // 5 | // Created by Majid Achhoud on 11.10.24. 6 | // Copyright © 2024 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public enum FileProviderCoordinatorError: Error { 12 | case unauthorized(vaultName: String) 13 | } 14 | -------------------------------------------------------------------------------- /FileProviderExtensionUI/FileProviderExtensionUI.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.default-data-protection 6 | NSFileProtectionComplete 7 | com.apple.security.application-groups 8 | 9 | group.org.cryptomator.ios 10 | 11 | keychain-access-groups 12 | 13 | $(AppIdentifierPrefix)org.cryptomator.ios 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "fastlane" 4 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "LightIcon.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | }, 9 | { 10 | "appearances" : [ 11 | { 12 | "appearance" : "luminosity", 13 | "value" : "dark" 14 | } 15 | ], 16 | "filename" : "DarkIcon.png", 17 | "idiom" : "universal", 18 | "platform" : "ios", 19 | "size" : "1024x1024" 20 | }, 21 | { 22 | "appearances" : [ 23 | { 24 | "appearance" : "luminosity", 25 | "value" : "tinted" 26 | } 27 | ], 28 | "filename" : "TintedIcon.png", 29 | "idiom" : "universal", 30 | "platform" : "ios", 31 | "size" : "1024x1024" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/AppIcon.appiconset/DarkIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/AppIcon.appiconset/DarkIcon.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/AppIcon.appiconset/LightIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/AppIcon.appiconset/LightIcon.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/AppIcon.appiconset/TintedIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/AppIcon.appiconset/TintedIcon.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/bot-vault.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "bot-vault.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "bot-vault@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "bot-vault@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/bot-vault.imageset/bot-vault.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/bot-vault.imageset/bot-vault.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/bot-vault.imageset/bot-vault@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/bot-vault.imageset/bot-vault@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/bot-vault.imageset/bot-vault@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/bot-vault.imageset/bot-vault@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/bot.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "bot.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "bot@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "bot@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/bot.imageset/bot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/bot.imageset/bot.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/bot.imageset/bot@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/bot.imageset/bot@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/bot.imageset/bot@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/bot.imageset/bot@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/box-vault-selected.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "box-vault-selected.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "box-vault-selected@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "box-vault-selected@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/box-vault-selected.imageset/box-vault-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/box-vault-selected.imageset/box-vault-selected.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/box-vault-selected.imageset/box-vault-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/box-vault-selected.imageset/box-vault-selected@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/box-vault-selected.imageset/box-vault-selected@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/box-vault-selected.imageset/box-vault-selected@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/box-vault.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "box-vault.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "box-vault@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "box-vault@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/box-vault.imageset/box-vault.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/box-vault.imageset/box-vault.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/box-vault.imageset/box-vault@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/box-vault.imageset/box-vault@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/box-vault.imageset/box-vault@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/box-vault.imageset/box-vault@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/box.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "box.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "box@2.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "box@3.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/box.imageset/box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/box.imageset/box.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/box.imageset/box@2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/box.imageset/box@2.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/box.imageset/box@3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/box.imageset/box@3.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/dropbox-vault-selected.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "dropbox-vault-selected.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "dropbox-vault-selected@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "dropbox-vault-selected@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/dropbox-vault-selected.imageset/dropbox-vault-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/dropbox-vault-selected.imageset/dropbox-vault-selected.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/dropbox-vault-selected.imageset/dropbox-vault-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/dropbox-vault-selected.imageset/dropbox-vault-selected@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/dropbox-vault-selected.imageset/dropbox-vault-selected@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/dropbox-vault-selected.imageset/dropbox-vault-selected@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/dropbox-vault.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "dropbox-vault.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "dropbox-vault@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "dropbox-vault@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/dropbox-vault.imageset/dropbox-vault.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/dropbox-vault.imageset/dropbox-vault.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/dropbox-vault.imageset/dropbox-vault@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/dropbox-vault.imageset/dropbox-vault@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/dropbox-vault.imageset/dropbox-vault@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/dropbox-vault.imageset/dropbox-vault@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/dropbox.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "dropbox.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "dropbox@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "dropbox@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/dropbox.imageset/dropbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/dropbox.imageset/dropbox.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/dropbox.imageset/dropbox@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/dropbox.imageset/dropbox@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/dropbox.imageset/dropbox@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/dropbox.imageset/dropbox@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/file-provider-vault-selected.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "file-provider-vault-selected.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "file-provider-vault-selected@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "file-provider-vault-selected@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/file-provider-vault-selected.imageset/file-provider-vault-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/file-provider-vault-selected.imageset/file-provider-vault-selected.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/file-provider-vault-selected.imageset/file-provider-vault-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/file-provider-vault-selected.imageset/file-provider-vault-selected@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/file-provider-vault-selected.imageset/file-provider-vault-selected@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/file-provider-vault-selected.imageset/file-provider-vault-selected@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/file-provider-vault.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "file-provider-vault.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "file-provider-vault@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "file-provider-vault@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/file-provider-vault.imageset/file-provider-vault.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/file-provider-vault.imageset/file-provider-vault.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/file-provider-vault.imageset/file-provider-vault@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/file-provider-vault.imageset/file-provider-vault@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/file-provider-vault.imageset/file-provider-vault@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/file-provider-vault.imageset/file-provider-vault@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/file-provider.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "file-provider.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "file-provider@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "file-provider@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/file-provider.imageset/file-provider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/file-provider.imageset/file-provider.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/file-provider.imageset/file-provider@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/file-provider.imageset/file-provider@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/file-provider.imageset/file-provider@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/file-provider.imageset/file-provider@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/google-drive-vault-selected.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "google-drive-vault-selected.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "google-drive-vault-selected@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "google-drive-vault-selected@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/google-drive-vault-selected.imageset/google-drive-vault-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/google-drive-vault-selected.imageset/google-drive-vault-selected.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/google-drive-vault-selected.imageset/google-drive-vault-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/google-drive-vault-selected.imageset/google-drive-vault-selected@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/google-drive-vault-selected.imageset/google-drive-vault-selected@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/google-drive-vault-selected.imageset/google-drive-vault-selected@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/google-drive-vault.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "google-drive-vault.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "google-drive-vault@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "google-drive-vault@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/google-drive-vault.imageset/google-drive-vault.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/google-drive-vault.imageset/google-drive-vault.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/google-drive-vault.imageset/google-drive-vault@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/google-drive-vault.imageset/google-drive-vault@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/google-drive-vault.imageset/google-drive-vault@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/google-drive-vault.imageset/google-drive-vault@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/google-drive.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "google-drive.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "google-drive@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "google-drive@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/google-drive.imageset/google-drive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/google-drive.imageset/google-drive.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/google-drive.imageset/google-drive@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/google-drive.imageset/google-drive@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/google-drive.imageset/google-drive@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/google-drive.imageset/google-drive@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/icloud-drive-vault-selected.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icloud-drive-vault-selected.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "icloud-drive-vault-selected@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "icloud-drive-vault-selected@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/icloud-drive-vault-selected.imageset/icloud-drive-vault-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/icloud-drive-vault-selected.imageset/icloud-drive-vault-selected.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/icloud-drive-vault-selected.imageset/icloud-drive-vault-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/icloud-drive-vault-selected.imageset/icloud-drive-vault-selected@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/icloud-drive-vault-selected.imageset/icloud-drive-vault-selected@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/icloud-drive-vault-selected.imageset/icloud-drive-vault-selected@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/icloud-drive-vault.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icloud-drive-vault.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "icloud-drive-vault@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "icloud-drive-vault@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/icloud-drive-vault.imageset/icloud-drive-vault.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/icloud-drive-vault.imageset/icloud-drive-vault.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/icloud-drive-vault.imageset/icloud-drive-vault@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/icloud-drive-vault.imageset/icloud-drive-vault@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/icloud-drive-vault.imageset/icloud-drive-vault@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/icloud-drive-vault.imageset/icloud-drive-vault@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/icloud-drive.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icloud-drive.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "icloud-drive@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "icloud-drive@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/icloud-drive.imageset/icloud-drive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/icloud-drive.imageset/icloud-drive.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/icloud-drive.imageset/icloud-drive@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/icloud-drive.imageset/icloud-drive@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/icloud-drive.imageset/icloud-drive@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/icloud-drive.imageset/icloud-drive@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/onedrive-vault-selected.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "onedrive-vault-selected.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "onedrive-vault-selected@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "onedrive-vault-selected@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/onedrive-vault-selected.imageset/onedrive-vault-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/onedrive-vault-selected.imageset/onedrive-vault-selected.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/onedrive-vault-selected.imageset/onedrive-vault-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/onedrive-vault-selected.imageset/onedrive-vault-selected@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/onedrive-vault-selected.imageset/onedrive-vault-selected@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/onedrive-vault-selected.imageset/onedrive-vault-selected@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/onedrive-vault.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "onedrive-vault.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "onedrive-vault@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "onedrive-vault@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/onedrive-vault.imageset/onedrive-vault.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/onedrive-vault.imageset/onedrive-vault.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/onedrive-vault.imageset/onedrive-vault@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/onedrive-vault.imageset/onedrive-vault@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/onedrive-vault.imageset/onedrive-vault@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/onedrive-vault.imageset/onedrive-vault@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/onedrive.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "onedrive.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "onedrive@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "onedrive@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/onedrive.imageset/onedrive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/onedrive.imageset/onedrive.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/onedrive.imageset/onedrive@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/onedrive.imageset/onedrive@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/onedrive.imageset/onedrive@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/onedrive.imageset/onedrive@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/pcloud-vault-selected.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "pcloud-vault-selected.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "pcloud-vault-selected@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "pcloud-vault-selected@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/pcloud-vault-selected.imageset/pcloud-vault-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/pcloud-vault-selected.imageset/pcloud-vault-selected.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/pcloud-vault-selected.imageset/pcloud-vault-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/pcloud-vault-selected.imageset/pcloud-vault-selected@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/pcloud-vault-selected.imageset/pcloud-vault-selected@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/pcloud-vault-selected.imageset/pcloud-vault-selected@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/pcloud-vault.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "pcloud-vault.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "pcloud-vault@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "pcloud-vault@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/pcloud-vault.imageset/pcloud-vault.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/pcloud-vault.imageset/pcloud-vault.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/pcloud-vault.imageset/pcloud-vault@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/pcloud-vault.imageset/pcloud-vault@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/pcloud-vault.imageset/pcloud-vault@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/pcloud-vault.imageset/pcloud-vault@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/pcloud.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "pcloud.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "pcloud@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "pcloud@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/pcloud.imageset/pcloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/pcloud.imageset/pcloud.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/pcloud.imageset/pcloud@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/pcloud.imageset/pcloud@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/pcloud.imageset/pcloud@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/pcloud.imageset/pcloud@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/s3-vault-selected.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "s3-vault-selected.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "s3-vault-selected@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "s3-vault-selected@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/s3-vault-selected.imageset/s3-vault-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/s3-vault-selected.imageset/s3-vault-selected.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/s3-vault-selected.imageset/s3-vault-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/s3-vault-selected.imageset/s3-vault-selected@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/s3-vault-selected.imageset/s3-vault-selected@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/s3-vault-selected.imageset/s3-vault-selected@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/s3-vault.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "s3-vault.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "s3-vault@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "s3-vault@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/s3-vault.imageset/s3-vault.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/s3-vault.imageset/s3-vault.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/s3-vault.imageset/s3-vault@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/s3-vault.imageset/s3-vault@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/s3-vault.imageset/s3-vault@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/s3-vault.imageset/s3-vault@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/s3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "s3.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "s3@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "s3@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/s3.imageset/s3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/s3.imageset/s3.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/s3.imageset/s3@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/s3.imageset/s3@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/s3.imageset/s3@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/s3.imageset/s3@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/sharepoint-selected.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "sharepoint-vault-selected.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "sharepoint-vault-selected@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "sharepoint-vault-selected@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/sharepoint-selected.imageset/sharepoint-vault-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/sharepoint-selected.imageset/sharepoint-vault-selected.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/sharepoint-selected.imageset/sharepoint-vault-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/sharepoint-selected.imageset/sharepoint-vault-selected@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/sharepoint-selected.imageset/sharepoint-vault-selected@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/sharepoint-selected.imageset/sharepoint-vault-selected@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/sharepoint-vault.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "sharepoint-vault.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "sharepoint-vault@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "sharepoint-vault@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/sharepoint-vault.imageset/sharepoint-vault.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/sharepoint-vault.imageset/sharepoint-vault.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/sharepoint-vault.imageset/sharepoint-vault@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/sharepoint-vault.imageset/sharepoint-vault@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/sharepoint-vault.imageset/sharepoint-vault@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/sharepoint-vault.imageset/sharepoint-vault@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/sharepoint.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "sharepoint.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "sharepoint@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "sharepoint@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/sharepoint.imageset/sharepoint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/sharepoint.imageset/sharepoint.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/sharepoint.imageset/sharepoint@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/sharepoint.imageset/sharepoint@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/sharepoint.imageset/sharepoint@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/sharepoint.imageset/sharepoint@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/webdav-vault-selected.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "webdav-vault-selected.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "webdav-vault-selected@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "webdav-vault-selected@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/webdav-vault-selected.imageset/webdav-vault-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/webdav-vault-selected.imageset/webdav-vault-selected.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/webdav-vault-selected.imageset/webdav-vault-selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/webdav-vault-selected.imageset/webdav-vault-selected@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/webdav-vault-selected.imageset/webdav-vault-selected@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/webdav-vault-selected.imageset/webdav-vault-selected@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/webdav-vault.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "webdav-vault.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "webdav-vault@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "webdav-vault@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/webdav-vault.imageset/webdav-vault.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/webdav-vault.imageset/webdav-vault.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/webdav-vault.imageset/webdav-vault@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/webdav-vault.imageset/webdav-vault@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/webdav-vault.imageset/webdav-vault@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/webdav-vault.imageset/webdav-vault@3x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/webdav.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "webdav.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "webdav@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "webdav@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/webdav.imageset/webdav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/webdav.imageset/webdav.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/webdav.imageset/webdav@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/webdav.imageset/webdav@2x.png -------------------------------------------------------------------------------- /SharedResources/Assets.xcassets/webdav.imageset/webdav@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/Assets.xcassets/webdav.imageset/webdav@3x.png -------------------------------------------------------------------------------- /SharedResources/Colors.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SharedResources/Colors.xcassets/background.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0xF7", 9 | "green" : "0xF7", 10 | "red" : "0xF7" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "0x3B", 27 | "green" : "0x39", 28 | "red" : "0x35" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SharedResources/Colors.xcassets/primary.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0x4A", 9 | "green" : "0xB0", 10 | "red" : "0x49" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "idiom" : "universal" 23 | } 24 | ], 25 | "info" : { 26 | "author" : "xcode", 27 | "version" : 1 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SharedResources/Colors.xcassets/yellow.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0x0F", 9 | "green" : "0xC4", 10 | "red" : "0xF1" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "idiom" : "universal" 23 | } 24 | ], 25 | "info" : { 26 | "author" : "xcode", 27 | "version" : 1 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SharedResources/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyAccessedAPITypes 6 | 7 | 8 | NSPrivacyAccessedAPIType 9 | NSPrivacyAccessedAPICategoryFileTimestamp 10 | NSPrivacyAccessedAPITypeReasons 11 | 12 | DDA9.1 13 | C617.1 14 | 3B52.1 15 | 16 | 17 | 18 | NSPrivacyAccessedAPIType 19 | NSPrivacyAccessedAPICategoryUserDefaults 20 | NSPrivacyAccessedAPITypeReasons 21 | 22 | CA92.1 23 | 1C8F.1 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /SharedResources/af.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/af.lproj/Localizable.strings -------------------------------------------------------------------------------- /SharedResources/mr.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/mr.lproj/Localizable.strings -------------------------------------------------------------------------------- /SharedResources/nn-NO.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "common.button.cancel" = "Avbryt"; 2 | "common.button.change" = "Endre"; 3 | "common.button.choose" = "Vel"; 4 | "common.button.close" = "Lukk"; 5 | "common.button.done" = "Ferdig"; 6 | "common.button.next" = "Neste"; 7 | "common.cells.password" = "Passord"; 8 | 9 | "addVault.title" = "Legg til kvelv"; 10 | "addVault.createNewVault.title" = "Opprett ein ny kvelv"; 11 | "addVault.createNewVault.setVaultName.cells.name" = "Namn på kvelven"; 12 | "addVault.createNewVault.chooseCloud.header" = "Kvar skal Cryptomator lagra dei krypterte filene i kvelven din?"; 13 | "addVault.openExistingVault.title" = "Opn ein eksisterande kvelv"; 14 | "fileProvider.error.unlockButton" = "Låse opp"; 15 | 16 | "unlockVault.button.unlock" = "Låse opp"; 17 | 18 | "vaultDetail.button.changeVaultPassword" = "Byt passord"; 19 | -------------------------------------------------------------------------------- /SharedResources/no.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/no.lproj/Localizable.strings -------------------------------------------------------------------------------- /SharedResources/si.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "common.button.cancel" = "අවලංගු"; 2 | "common.button.change" = "වෙනස් කරන්න"; 3 | "common.button.close" = "වසන්න"; 4 | "common.button.done" = "සම්පූර්ණයි"; 5 | "common.button.next" = "ඊළඟ"; 6 | "fileProvider.error.unlockButton" = "අගුළුහරින්න"; 7 | 8 | "unlockVault.button.unlock" = "අගුළුහරින්න"; 9 | -------------------------------------------------------------------------------- /SharedResources/sr-CS.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "common.button.cancel" = "Otkaži"; 2 | "common.button.choose" = "Izaberi"; 3 | "common.button.done" = "Završeno"; 4 | "common.button.next" = "Dalje"; 5 | 6 | "addVault.title" = "Dodavanje safa"; 7 | "addVault.createNewVault.title" = "Napravi novi sef"; 8 | "addVault.createNewVault.setVaultName.cells.name" = "Naziv sefa"; 9 | "addVault.createNewVault.chooseCloud.header" = "Gde Cryptomator da skladišti šifrovane datoteke vašeg sefa?"; 10 | "addVault.openExistingVault.title" = "Otvori postojeći sef"; 11 | 12 | "unlockVault.button.unlock" = "Otključaj"; 13 | -------------------------------------------------------------------------------- /SharedResources/sr-Latn.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "common.button.cancel" = "Otkaži"; 2 | "common.button.change" = "Izmeni"; 3 | "common.button.choose" = "Izaberi"; 4 | "common.button.close" = "Zatvori"; 5 | "common.button.done" = "Završeno"; 6 | "common.button.next" = "Dalje"; 7 | 8 | "addVault.title" = "Dodavanje safa"; 9 | "addVault.createNewVault.title" = "Napravi novi sef"; 10 | "addVault.createNewVault.setVaultName.cells.name" = "Naziv sefa"; 11 | "addVault.createNewVault.chooseCloud.header" = "Gde Cryptomator da skladišti šifrovane datoteke vašeg sefa?"; 12 | "addVault.openExistingVault.title" = "Otvori postojeći sef"; 13 | "fileProvider.error.unlockButton" = "Otključaj"; 14 | 15 | "unlockVault.button.unlock" = "Otključaj"; 16 | 17 | "vaultDetail.button.changeVaultPassword" = "Promena lozinke"; 18 | -------------------------------------------------------------------------------- /SharedResources/sr.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "common.button.cancel" = "Otkaži"; 2 | "common.button.change" = "Izmeni"; 3 | "common.button.choose" = "Изабери"; 4 | "common.button.close" = "Zatvori"; 5 | "common.button.done" = "Završeno"; 6 | "common.button.next" = "Dalje"; 7 | "common.button.remove" = "Уклони"; 8 | "common.cells.password" = "Лозинка"; 9 | 10 | "addVault.title" = "Dodavanje safa"; 11 | "addVault.createNewVault.title" = "Napravi novi sef"; 12 | "addVault.createNewVault.setVaultName.cells.name" = "Naziv sefa"; 13 | "addVault.createNewVault.chooseCloud.header" = "Gde Cryptomator da skladišti šifrovane datoteke vašeg sefa?"; 14 | "addVault.openExistingVault.title" = "Otvori postojeći sef"; 15 | "fileProvider.error.unlockButton" = "Otključaj"; 16 | 17 | "unlockVault.button.unlock" = "Otključaj"; 18 | 19 | "vaultDetail.button.changeVaultPassword" = "Promena lozinke"; 20 | -------------------------------------------------------------------------------- /SharedResources/ug.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "common.button.cancel" = "بىكار قىل"; 2 | "common.button.change" = "ئۆزگەرت"; 3 | "common.button.close" = "ياپ"; 4 | "common.button.done" = "تامام"; 5 | "common.button.next" = "كېيىنكى"; 6 | "common.cells.password" = "پارول"; 7 | 8 | "addVault.title" = "ئامبار قوش"; 9 | "addVault.createNewVault.setVaultName.cells.name" = "ئامبار ئىسمى"; 10 | "addVault.createNewVault.chooseCloud.header" = "Cryptomator ئامبىرىڭىزنىڭ شىفىرلانغان ھۆججەتلىرىنى قەيەردە ساقلىشى كېرەك?"; 11 | "fileProvider.error.unlockButton" = "قۇلۇپنى ئاچ"; 12 | "hubAuthentication.licenseExceeded" = "سىزنىڭ Cryptomator Hub نۇسخىڭىزنىڭ ئىناۋەتسىز ئىجازەتنامىسى بار. Hub باشقۇرغۇچىسىغا ئىجازەتنامىنى يۇقىرى دەرىجىگە كۆتۈر."; 13 | "hubAuthentication.deviceRegistration.deviceName.cells.name" = "ئۈسكۈنە ئىسمى"; 14 | 15 | "unlockVault.button.unlock" = "قۇلۇپنى ئاچ"; 16 | 17 | "vaultDetail.button.changeVaultPassword" = "پارولنى ئۆزگەرتىش"; 18 | -------------------------------------------------------------------------------- /SharedResources/ur.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/SharedResources/ur.lproj/Localizable.strings -------------------------------------------------------------------------------- /Snapshots/SnapshotBiometrics.h: -------------------------------------------------------------------------------- 1 | // 2 | // SnapshotBiometrics.h 3 | // Snapshots 4 | // 5 | // Created by Philipp Schmid on 27.12.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface SnapshotBiometrics : NSObject 14 | 15 | + (void)enrolled; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /Snapshots/SnapshotBiometrics.m: -------------------------------------------------------------------------------- 1 | // 2 | // SnapshotBiometrics.m 3 | // Snapshots 4 | // 5 | // Created by Philipp Schmid on 27.12.21. 6 | // Copyright © 2021 Skymatic GmbH. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "notify.h" 11 | #import "SnapshotBiometrics.h" 12 | 13 | // Taken from: https://github.com/KaneCheshire/BiometricAutomationDemo/blob/main/BiometricsAutomationDemoUITests/Biometrics.m 14 | @implementation SnapshotBiometrics 15 | 16 | + (void)enrolled { 17 | int token; 18 | notify_register_check("com.apple.BiometricKit.enrollmentChanged", &token); 19 | notify_set_state(token, 1); 20 | notify_post("com.apple.BiometricKit.enrollmentChanged"); 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Snapshots/Snapshots-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import "SnapshotBiometrics.h" 6 | -------------------------------------------------------------------------------- /StoreKitTestConfiguration/StoreKitTestCertificate.cer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/StoreKitTestConfiguration/StoreKitTestCertificate.cer -------------------------------------------------------------------------------- /fastlane/.env.freemium: -------------------------------------------------------------------------------- 1 | APP_GROUP=group.org.cryptomator.ios 2 | APP_ICON_DARK_FILE_PATH=config/freemium/DarkIcon.png 3 | APP_ICON_LIGHT_FILE_PATH=config/freemium/LightIcon.png 4 | APP_ICON_TINTED_FILE_PATH=config/freemium/TintedIcon.png 5 | BUNDLE_IDENTIFIER=org.cryptomator.ios 6 | CONFIG_NAME=freemium 7 | DISPLAY_NAME=Cryptomator 8 | ENCRYPTION_EXPORT_COMPLIANCE_CODE=0ecbe108-6127-46e6-8bb0-e9a0cc424582 9 | KEYCHAIN_GROUP=org.cryptomator.ios 10 | METADATA_PATH=./fastlane/config/freemium/metadata 11 | XCARGS="CONFIG_NAME='freemium'" 12 | -------------------------------------------------------------------------------- /fastlane/.env.premium: -------------------------------------------------------------------------------- 1 | APP_GROUP=group.org.cryptomator.ios.premium 2 | APP_ICON_DARK_FILE_PATH=config/premium/DarkIcon.png 3 | APP_ICON_LIGHT_FILE_PATH=config/premium/LightIcon.png 4 | APP_ICON_TINTED_FILE_PATH=config/premium/TintedIcon.png 5 | BUNDLE_IDENTIFIER=org.cryptomator.ios.premium 6 | CONFIG_NAME=premium 7 | DISPLAY_NAME=Cryptomator 8 | ENCRYPTION_EXPORT_COMPLIANCE_CODE=e2282164-3842-4bd8-b3a5-c9fa4b0e087c 9 | KEYCHAIN_GROUP=org.cryptomator.ios.premium 10 | METADATA_PATH=./fastlane/config/premium/metadata 11 | XCARGS="CONFIG_NAME='premium' SWIFT_ACTIVE_COMPILATION_CONDITIONS='\$(inherited) ALWAYS_PREMIUM'" 12 | -------------------------------------------------------------------------------- /fastlane/Appfile: -------------------------------------------------------------------------------- 1 | app_identifier(ENV["BUNDLE_IDENTIFIER"]) 2 | team_id("YZQJQUHA3L") 3 | -------------------------------------------------------------------------------- /fastlane/Deliverfile: -------------------------------------------------------------------------------- 1 | metadata_path(ENV["METADATA_PATH"]) 2 | submission_information({ 3 | add_id_info_uses_idfa: false 4 | }) 5 | -------------------------------------------------------------------------------- /fastlane/Gymfile: -------------------------------------------------------------------------------- 1 | scheme("Cryptomator") 2 | clean(true) 3 | xcargs(ENV["XCARGS"]) 4 | -------------------------------------------------------------------------------- /fastlane/Matchfile: -------------------------------------------------------------------------------- 1 | git_url(ENV["SKYMATIC_MATCH_GIT_URL"]) 2 | app_identifier([ENV["BUNDLE_IDENTIFIER"], "#{ENV["BUNDLE_IDENTIFIER"]}.fileprovider", "#{ENV["BUNDLE_IDENTIFIER"]}.fileprovider-ui", "#{ENV["BUNDLE_IDENTIFIER"]}.intents"]) 3 | -------------------------------------------------------------------------------- /fastlane/Scanfile: -------------------------------------------------------------------------------- 1 | scheme("AllTests") 2 | device("iPhone 15") 3 | clean(true) 4 | output_types("html") 5 | skip_slack(true) 6 | -------------------------------------------------------------------------------- /fastlane/beta_app_description.txt: -------------------------------------------------------------------------------- 1 | Welcome to the beta test of Cryptomator! 2 | 3 | With Cryptomator, the key to your data is in your hands. Cryptomator secures and encrypts your sensitive data in your favorite cloud service. So you can rest assured that only you can access your data. 4 | 5 | This beta version allows you to test new features and improvements before the public release. Your feedback helps us enhance security, stability, and usability. Feel free to reach us at testflight@cryptomator.org. -------------------------------------------------------------------------------- /fastlane/changelog.txt: -------------------------------------------------------------------------------- 1 | - Fixed endless loading when calculating cache size in settings. -------------------------------------------------------------------------------- /fastlane/config/freemium/DarkIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/fastlane/config/freemium/DarkIcon.png -------------------------------------------------------------------------------- /fastlane/config/freemium/LightIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/fastlane/config/freemium/LightIcon.png -------------------------------------------------------------------------------- /fastlane/config/freemium/TintedIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/fastlane/config/freemium/TintedIcon.png -------------------------------------------------------------------------------- /fastlane/config/freemium/metadata/copyright.txt: -------------------------------------------------------------------------------- 1 | 2025 cryptomator.org -------------------------------------------------------------------------------- /fastlane/config/freemium/metadata/de-DE/marketing_url.txt: -------------------------------------------------------------------------------- 1 | https://cryptomator.org/de/ -------------------------------------------------------------------------------- /fastlane/config/freemium/metadata/de-DE/privacy_url.txt: -------------------------------------------------------------------------------- 1 | https://cryptomator.org/de/privacy/ -------------------------------------------------------------------------------- /fastlane/config/freemium/metadata/de-DE/release_notes.txt: -------------------------------------------------------------------------------- 1 | - Endloses Laden beim Berechnen der Cache-Größe in den Einstellungen behoben. -------------------------------------------------------------------------------- /fastlane/config/freemium/metadata/de-DE/subtitle.txt: -------------------------------------------------------------------------------- 1 | Cloudspeicher Verschlüsselung -------------------------------------------------------------------------------- /fastlane/config/freemium/metadata/de-DE/support_url.txt: -------------------------------------------------------------------------------- 1 | https://cryptomator.org/de/contact/ -------------------------------------------------------------------------------- /fastlane/config/freemium/metadata/default/keywords.txt: -------------------------------------------------------------------------------- 1 | open,source,icloud,drive,dropbox,google,onedrive,pcloud,webdav,s3,aws,nextcloud,owncloud,boxcryptor -------------------------------------------------------------------------------- /fastlane/config/freemium/metadata/default/name.txt: -------------------------------------------------------------------------------- 1 | Cryptomator -------------------------------------------------------------------------------- /fastlane/config/freemium/metadata/en-US/marketing_url.txt: -------------------------------------------------------------------------------- 1 | https://cryptomator.org/ -------------------------------------------------------------------------------- /fastlane/config/freemium/metadata/en-US/privacy_url.txt: -------------------------------------------------------------------------------- 1 | https://cryptomator.org/privacy/ -------------------------------------------------------------------------------- /fastlane/config/freemium/metadata/en-US/release_notes.txt: -------------------------------------------------------------------------------- 1 | - Fixed endless loading when calculating cache size in settings. -------------------------------------------------------------------------------- /fastlane/config/freemium/metadata/en-US/subtitle.txt: -------------------------------------------------------------------------------- 1 | Cloud Storage Encryption -------------------------------------------------------------------------------- /fastlane/config/freemium/metadata/en-US/support_url.txt: -------------------------------------------------------------------------------- 1 | https://cryptomator.org/contact/ -------------------------------------------------------------------------------- /fastlane/config/freemium/metadata/primary_category.txt: -------------------------------------------------------------------------------- 1 | PRODUCTIVITY -------------------------------------------------------------------------------- /fastlane/config/freemium/metadata/secondary_category.txt: -------------------------------------------------------------------------------- 1 | UTILITIES -------------------------------------------------------------------------------- /fastlane/config/premium/DarkIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/fastlane/config/premium/DarkIcon.png -------------------------------------------------------------------------------- /fastlane/config/premium/LightIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/fastlane/config/premium/LightIcon.png -------------------------------------------------------------------------------- /fastlane/config/premium/TintedIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cryptomator/ios/d579ed4bb4604caf28fd6a7713ac453e58f735fb/fastlane/config/premium/TintedIcon.png -------------------------------------------------------------------------------- /fastlane/config/premium/metadata/copyright.txt: -------------------------------------------------------------------------------- 1 | 2025 cryptomator.org -------------------------------------------------------------------------------- /fastlane/config/premium/metadata/de-DE/marketing_url.txt: -------------------------------------------------------------------------------- 1 | https://cryptomator.org/de/ -------------------------------------------------------------------------------- /fastlane/config/premium/metadata/de-DE/name.txt: -------------------------------------------------------------------------------- 1 | Cryptomator: Vollversion -------------------------------------------------------------------------------- /fastlane/config/premium/metadata/de-DE/privacy_url.txt: -------------------------------------------------------------------------------- 1 | https://cryptomator.org/de/privacy/ -------------------------------------------------------------------------------- /fastlane/config/premium/metadata/de-DE/release_notes.txt: -------------------------------------------------------------------------------- 1 | - Endloses Laden beim Berechnen der Cache-Größe in den Einstellungen behoben. -------------------------------------------------------------------------------- /fastlane/config/premium/metadata/de-DE/subtitle.txt: -------------------------------------------------------------------------------- 1 | Cloudspeicher Verschlüsselung -------------------------------------------------------------------------------- /fastlane/config/premium/metadata/de-DE/support_url.txt: -------------------------------------------------------------------------------- 1 | https://cryptomator.org/de/contact/ -------------------------------------------------------------------------------- /fastlane/config/premium/metadata/default/keywords.txt: -------------------------------------------------------------------------------- 1 | open,source,icloud,drive,dropbox,google,onedrive,pcloud,webdav,s3,aws,nextcloud,owncloud,boxcryptor -------------------------------------------------------------------------------- /fastlane/config/premium/metadata/en-US/marketing_url.txt: -------------------------------------------------------------------------------- 1 | https://cryptomator.org/ -------------------------------------------------------------------------------- /fastlane/config/premium/metadata/en-US/name.txt: -------------------------------------------------------------------------------- 1 | Cryptomator: Full Version -------------------------------------------------------------------------------- /fastlane/config/premium/metadata/en-US/privacy_url.txt: -------------------------------------------------------------------------------- 1 | https://cryptomator.org/privacy/ -------------------------------------------------------------------------------- /fastlane/config/premium/metadata/en-US/release_notes.txt: -------------------------------------------------------------------------------- 1 | - Fixed endless loading when calculating cache size in settings. -------------------------------------------------------------------------------- /fastlane/config/premium/metadata/en-US/subtitle.txt: -------------------------------------------------------------------------------- 1 | Cloud Storage Encryption -------------------------------------------------------------------------------- /fastlane/config/premium/metadata/en-US/support_url.txt: -------------------------------------------------------------------------------- 1 | https://cryptomator.org/contact/ -------------------------------------------------------------------------------- /fastlane/config/premium/metadata/primary_category.txt: -------------------------------------------------------------------------------- 1 | PRODUCTIVITY -------------------------------------------------------------------------------- /fastlane/config/premium/metadata/secondary_category.txt: -------------------------------------------------------------------------------- 1 | UTILITIES -------------------------------------------------------------------------------- /fastlane/scripts/create-app-constants.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Path is relative to the fastlane folder 4 | cat > ../CryptomatorCommon/Sources/CryptomatorCommonCore/CryptomatorConstants.swift << EOM 5 | // 6 | // CryptomatorConstants.swift 7 | // CryptomatorCommonCore 8 | // 9 | // This file was automatically generated by create-app-constants.sh and should not be modified. 10 | // 11 | 12 | import Foundation 13 | 14 | public enum CryptomatorConstants { 15 | public static let appGroupName = "group.${1}" 16 | public static let mainAppBundleId = "${1}" 17 | } 18 | EOM 19 | -------------------------------------------------------------------------------- /fastlane/scripts/create-app-icon.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Path is relative to the fastlane folder 4 | cp "${1}" ../SharedResources/Assets.xcassets/AppIcon.appiconset/LightIcon.png 5 | cp "${2}" ../SharedResources/Assets.xcassets/AppIcon.appiconset/DarkIcon.png 6 | cp "${3}" ../SharedResources/Assets.xcassets/AppIcon.appiconset/TintedIcon.png 7 | --------------------------------------------------------------------------------