Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class OpenExistingVaultChooseFolderViewController: ChooseFolderViewController {

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if viewModel.foundMasterkey {
let cell = addVaultButtonViewModel.type.init()
let cell = addVaultButtonViewModel.type.init(style: addVaultButtonViewModel.cellStyle, reuseIdentifier: nil)
cell.configure(with: addVaultButtonViewModel)
return cell
} else {
Expand Down
4 changes: 4 additions & 0 deletions Cryptomator/Common/Cells/BindableTableViewCellViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ class TableViewCellViewModel: Hashable {
fatalError("not implemented")
}

var cellStyle: UITableViewCell.CellStyle {
return .default
}

private let identifier = UUID()

static func == (lhs: TableViewCellViewModel, rhs: TableViewCellViewModel) -> Bool {
Expand Down
18 changes: 7 additions & 11 deletions Cryptomator/Common/Cells/ButtonCellViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,16 @@
import UIKit

class ButtonCellViewModel<T>: BindableTableViewCellViewModel {
override var type: ConfigurableTableViewCell.Type { ButtonTableViewCell.self }
private let preferredCellStyle: UITableViewCell.CellStyle
override var cellStyle: UITableViewCell.CellStyle { preferredCellStyle }
let action: T
init(action: T, title: String, titleTextColor: UIColor? = .cryptomatorPrimary, detailTitle: String? = nil, isEnabled: Bool = true, selectionStyle: UITableViewCell.SelectionStyle = .default, accessoryType: UITableViewCell.AccessoryType = .none) {
init(action: T, title: String, titleTextColor: UIColor? = .cryptomatorPrimary, detailTitle: String? = nil, image: UIImage? = nil, isEnabled: Bool = true, selectionStyle: UITableViewCell.SelectionStyle = .default, accessoryType: UITableViewCell.AccessoryType = .none, cellStyle: UITableViewCell.CellStyle = .value1) {
self.action = action
super.init(title: title, titleTextColor: titleTextColor, detailTitle: detailTitle, isEnabled: isEnabled, selectionStyle: selectionStyle, accessoryType: accessoryType)
self.preferredCellStyle = cellStyle
super.init(title: title, titleTextColor: titleTextColor, detailTitle: detailTitle, image: image, isEnabled: isEnabled, selectionStyle: selectionStyle, accessoryType: accessoryType)
}

static func createDisclosureButton(action: T, title: String, detailTitle: String? = nil, accessoryType: UITableViewCell.AccessoryType = .disclosureIndicator, isEnabled: Bool = true) -> ButtonCellViewModel<T> {
return ButtonCellViewModel(action: action, title: title, titleTextColor: nil, detailTitle: detailTitle, isEnabled: isEnabled, accessoryType: accessoryType)
}
}

class ButtonTableViewCell: TableViewCell {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: .value1, reuseIdentifier: reuseIdentifier)
static func createDisclosureButton(action: T, title: String, detailTitle: String? = nil, image: UIImage? = nil, accessoryType: UITableViewCell.AccessoryType = .disclosureIndicator, isEnabled: Bool = true, cellStyle: UITableViewCell.CellStyle = .value1) -> ButtonCellViewModel<T> {
return ButtonCellViewModel(action: action, title: title, titleTextColor: nil, detailTitle: detailTitle, image: image, isEnabled: isEnabled, accessoryType: accessoryType, cellStyle: cellStyle)
}
}
2 changes: 1 addition & 1 deletion Cryptomator/Common/Cells/LoadingButtonCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import UIKit

class LoadingButtonCell: ButtonTableViewCell {
class LoadingButtonCell: TableViewCell {
private lazy var loadingIndicator: UIActivityIndicatorView = {
let loadingIndicator = UIActivityIndicatorView(style: .medium)
loadingIndicator.hidesWhenStopped = true
Expand Down
2 changes: 1 addition & 1 deletion Cryptomator/Common/Cells/SystemSymbolButtonCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import Foundation
import UIKit

class SystemSymbolButtonCell: ButtonTableViewCell {
class SystemSymbolButtonCell: TableViewCell {
override func configure(with viewModel: TableViewCellViewModel) {
super.configure(with: viewModel)
guard let viewModel = viewModel as? SystemSymbolNameProviding else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class CreateNewFolderViewController: SingleSectionStaticUITableViewController {

override func configureDataSource() {
dataSource = BaseDiffableDataSource<SingleSection, TableViewCellViewModel>(viewModel: viewModel, tableView: tableView) { _, _, cellViewModel -> UITableViewCell? in
let cell = cellViewModel.type.init()
let cell = cellViewModel.type.init(style: cellViewModel.cellStyle, reuseIdentifier: nil)
cell.configure(with: cellViewModel)
if let textFieldCell = cell as? TextFieldCell {
let imageConfiguration = UIImage.SymbolConfiguration(font: UIFont.preferredFont(forTextStyle: .title2))
Expand Down
2 changes: 1 addition & 1 deletion Cryptomator/Common/StaticUITableViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class StaticUITableViewController<SectionType: Hashable>: BaseUITableViewControl

func configureDataSource() {
dataSource = BaseDiffableDataSource<SectionType, TableViewCellViewModel>(viewModel: viewModel, tableView: tableView) { _, _, cellViewModel -> UITableViewCell? in
let cell = cellViewModel.type.init()
let cell = cellViewModel.type.init(style: cellViewModel.cellStyle, reuseIdentifier: nil)
cell.configure(with: cellViewModel)
return cell
}
Expand Down
3 changes: 1 addition & 2 deletions Cryptomator/Purchase/Cells/TrialCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,7 @@ struct TrialCellViewModel: Hashable {
var expirationText: String {
let formatter = DateFormatter()
formatter.dateStyle = .short
let formattedExpirationDate = formatter.string(for: expirationDate) ?? "Invalid Date"
return String(format: LocalizedString.getValue("purchase.product.trial.expirationDate"), formattedExpirationDate)
return String(format: LocalizedString.getValue("purchase.product.trial.expirationDate"), formatter.string(from: expirationDate))
}

let expirationDate: Date
Expand Down
3 changes: 1 addition & 2 deletions Cryptomator/Purchase/PurchaseAlert.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ enum PurchaseAlert {
static func showForTrial(title: String, expirationDate: Date, on presentingViewController: UIViewController) -> Promise<Void> {
let formatter = DateFormatter()
formatter.dateStyle = .short
let formattedExpireDate = formatter.string(for: expirationDate) ?? "Invalid Date"
let message = String(format: LocalizedString.getValue("purchase.restorePurchase.validTrialFound.alert.message"), formattedExpireDate)
let message = String(format: LocalizedString.getValue("purchase.restorePurchase.validTrialFound.alert.message"), formatter.string(from: expirationDate))
return showAlert(title: title, message: message, on: presentingViewController)
}

Expand Down
45 changes: 36 additions & 9 deletions Cryptomator/Settings/SettingsViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ enum SettingsButtonAction: String {
}

enum SettingsSection: Int {
case cloudServiceSection = 0
case unlockFullVersionSection = 0
case cloudServiceSection
case cacheSection
case aboutSection
case debugSection
Expand All @@ -44,12 +45,25 @@ class SettingsViewModel: TableViewModel<SettingsSection> {
return _sections
}

override func getFooterTitle(for section: Int) -> String? {
guard sections[section].id == .aboutSection, hasFullVersion else { return nil }
return LocalizedString.getValue("settings.aboutCryptomator.hasFullVersion.footer")
}

var showDebugModeWarning: AnyPublisher<Void, Never> {
return showDebugModeWarningPublisher.eraseToAnyPublisher()
}

private var hasFullVersion: Bool {
cryptomatorSettings.hasRunningSubscription || cryptomatorSettings.fullVersionUnlocked
}

private var _sections: [Section<SettingsSection>] {
return [
var sections: [Section<SettingsSection>] = []
if !hasFullVersion {
sections.append(Section(id: .unlockFullVersionSection, elements: [unlockFullVersionCellViewModel]))
}
sections.append(contentsOf: [
Section(id: .cloudServiceSection, elements: [
ButtonCellViewModel.createDisclosureButton(action: SettingsButtonAction.showCloudServices, title: LocalizedString.getValue("settings.cloudServices"))
]),
Expand All @@ -67,24 +81,37 @@ class SettingsViewModel: TableViewModel<SettingsSection> {
ButtonCellViewModel(action: SettingsButtonAction.showContact, title: LocalizedString.getValue("settings.contact")),
ButtonCellViewModel(action: SettingsButtonAction.showRateApp, title: LocalizedString.getValue("settings.rateApp"))
])
]
])
return sections
}

private var aboutSectionElements: [TableViewCellViewModel] {
var elements = [ButtonCellViewModel.createDisclosureButton(action: SettingsButtonAction.showAbout, title: LocalizedString.getValue("settings.aboutCryptomator"))]
var elements: [TableViewCellViewModel] = [
ButtonCellViewModel.createDisclosureButton(action: SettingsButtonAction.showAbout, title: LocalizedString.getValue("settings.aboutCryptomator"))
]
if cryptomatorSettings.hasRunningSubscription {
elements.append(.init(action: .showManageSubscriptions, title: LocalizedString.getValue("settings.manageSubscriptions")))
elements.append(.init(action: .restorePurchase, title: LocalizedString.getValue("purchase.restorePurchase.button")))
} else if !cryptomatorSettings.fullVersionUnlocked {
elements.append(ButtonCellViewModel.createDisclosureButton(action: SettingsButtonAction.showUnlockFullVersion, title: LocalizedString.getValue("settings.unlockFullVersion")))
elements.append(ButtonCellViewModel.createDisclosureButton(action: SettingsButtonAction.showManageSubscriptions, title: LocalizedString.getValue("settings.manageSubscriptions")))
}
return elements
}

private var unlockFullVersionCellViewModel: ButtonCellViewModel<SettingsButtonAction> {
let detailTitle: String
if let trialExpirationDate = cryptomatorSettings.trialExpirationDate, trialExpirationDate > Date() {
let formatter = DateFormatter()
formatter.dateStyle = .short
detailTitle = String(format: LocalizedString.getValue("settings.unlockFullVersion.trialExpirationDate"), formatter.string(from: trialExpirationDate))
} else {
detailTitle = LocalizedString.getValue("settings.unlockFullVersion.detail")
}
let image = UIImage(systemName: "checkmark.seal.fill", withConfiguration: UIImage.SymbolConfiguration(pointSize: 22))
return ButtonCellViewModel.createDisclosureButton(action: .showUnlockFullVersion, title: LocalizedString.getValue("settings.unlockFullVersion"), detailTitle: detailTitle, image: image, cellStyle: .subtitle)
}

private let cacheSizeCellViewModel = LoadingWithLabelCellViewModel(title: LocalizedString.getValue("settings.cacheSize"))
private let clearCacheButtonCellViewModel = ButtonCellViewModel<SettingsButtonAction>(action: .clearCache, title: LocalizedString.getValue("settings.clearCache"), isEnabled: false)

private var cryptomatorSettings: CryptomatorSettings

private lazy var debugModeViewModel: SwitchCellViewModel = {
let viewModel = SwitchCellViewModel(title: LocalizedString.getValue("settings.debugMode"), isOn: cryptomatorSettings.debugModeEnabled)
bindDebugModeViewModel(viewModel)
Expand Down
2 changes: 1 addition & 1 deletion Cryptomator/VaultDetail/VaultDetailViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class VaultDetailViewController: BaseUITableViewController {

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellViewModel = viewModel.cellViewModel(for: indexPath)
let cell = cellViewModel.type.init()
let cell = cellViewModel.type.init(style: cellViewModel.cellStyle, reuseIdentifier: nil)
cell.configure(with: cellViewModel)
return cell
}
Expand Down
3 changes: 3 additions & 0 deletions SharedResources/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@
"settings.title" = "Settings";
"settings.aboutCryptomator" = "About Cryptomator";
"settings.aboutCryptomator.title" = "Version %@ (%@)";
"settings.aboutCryptomator.hasFullVersion.footer" = "You have unlocked the full version and gained write access to your vaults.";
"settings.cacheSize" = "Cache Size";
"settings.clearCache" = "Clear Cache";
"settings.cloudServices" = "Cloud Services";
Expand All @@ -213,6 +214,8 @@
"settings.sendLogFile" = "Send Log File";
"settings.shortcutsGuide" = "Shortcuts Guide";
"settings.unlockFullVersion" = "Unlock Full Version";
"settings.unlockFullVersion.detail" = "Gain write access to your vaults.";
"settings.unlockFullVersion.trialExpirationDate" = "Trial Expiration Date: %@";

"sharePoint.enterURL.title" = "Enter SharePoint URL";
"sharePoint.enterURL.placeholder" = "SharePoint Site URL";
Expand Down
Loading