├── .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 |
--------------------------------------------------------------------------------