donations: add settings in account

Change-Id: I15ff958e64bb298914bc2db188bd5fde0928bd49
diff --git a/Ring/Ring/Features/Me/Me/MeViewController.swift b/Ring/Ring/Features/Me/Me/MeViewController.swift
index 70d17c6..ae38167 100644
--- a/Ring/Ring/Features/Me/Me/MeViewController.swift
+++ b/Ring/Ring/Features/Me/Me/MeViewController.swift
@@ -683,6 +683,10 @@
                         .configureTurnCell(cellType: .turnRealm,
                                            value: self.viewModel.turnRealm.value)
                     return cell
+                case .donationCampaign:
+                    return self.createDonationNotificationCell()
+                case .donate:
+                    return self.createDonationCell()
                 }
             }
 
@@ -695,6 +699,50 @@
             .disposed(by: disposeBag)
     }
 
+    func createDonationCell() -> UITableViewCell {
+        let cell = DisposableCell()
+        cell.textLabel?.text = L10n.Global.donate
+        cell.textLabel?.textColor = UIColor.jamiButtonDark
+        cell.textLabel?.textAlignment = .center
+        cell.textLabel?.numberOfLines = 0
+        cell.selectionStyle = .none
+        cell.sizeToFit()
+        let button = UIButton.init(frame: cell.frame)
+        let size = CGSize(width: self.settingsTable.frame.width, height: button.frame.height)
+        button.frame.size = size
+        cell.addSubview(button)
+        button.rx.tap
+            .subscribe(onNext: { [weak self] in
+                self?.viewModel.donate()
+            })
+            .disposed(by: cell.disposeBag)
+        cell.backgroundColor = .clear
+        cell.contentView.backgroundColor = .systemBackground
+        return cell
+    }
+
+    func createDonationNotificationCell() -> DisposableCell {
+        let cell = DisposableCell()
+        cell.textLabel?.text = L10n.GeneralSettings.enableDonationCampaign
+        let switchView = UISwitch()
+        cell.selectionStyle = .none
+        cell.accessoryType = UITableViewCell.AccessoryType.disclosureIndicator
+        cell.accessoryView = switchView
+        self.viewModel.enableDonationCampaign
+            .asObservable()
+            .observe(on: MainScheduler.instance)
+            .startWith(viewModel.enableDonationCampaign.value)
+            .bind(to: switchView.rx.value)
+            .disposed(by: cell.disposeBag)
+        switchView.rx.value
+            .observe(on: MainScheduler.instance)
+            .subscribe(onNext: { [weak self] (enabled) in
+                self?.viewModel.togleEnableDonationCampaign(enable: enabled)
+            })
+            .disposed(by: cell.disposeBag)
+        return cell
+    }
+
     func configureCellWithEnableTextCopy(text: String, secondaryText: String, style: UIFont.TextStyle) -> DisposableCell {
         let cell = DisposableCell(style: .subtitle, reuseIdentifier: self.jamiIDCell)
         cell.selectionStyle = .none
diff --git a/Ring/Ring/Features/Me/Me/MeViewModel.swift b/Ring/Ring/Features/Me/Me/MeViewModel.swift
index 3c3c6e3..0e9d773 100644
--- a/Ring/Ring/Features/Me/Me/MeViewModel.swift
+++ b/Ring/Ring/Features/Me/Me/MeViewModel.swift
@@ -37,6 +37,7 @@
     case connectivitySettings(items: [SectionRow])
     case credentials(items: [SectionRow])
     case otherSettings(items: [SectionRow])
+    case donations(items: [SectionRow])
     case removeAccountSettings(items: [SectionRow])
 
     enum SectionRow {
@@ -67,11 +68,20 @@
         case turnPassword
         case turnRealm
         case upnpEnabled
+        case donationCampaign
+        case donate
     }
 
     var items: [SectionRow] {
         switch self {
-        case .linkedDevices(let items), .removeAccountSettings(items: let items), .notificationSettings(let items), .connectivitySettings(let items), .credentials(let items), .otherSettings(items: let items), .accountSettings(items: let items):
+        case .linkedDevices(let items),
+             .removeAccountSettings(items: let items),
+             .notificationSettings(let items),
+             .connectivitySettings(let items),
+             .credentials(let items),
+             .otherSettings(items: let items),
+             .accountSettings(items: let items),
+             .donations(items: let items):
             return items
         }
     }
@@ -90,7 +100,9 @@
             return L10n.AccountPage.connectivityHeader
         case .credentials:
             return L10n.AccountPage.credentialsHeader
-        case .accountSettings(items: let items):
+        case .donations(items: _):
+            return L10n.Global.donate
+        case .accountSettings(items: _):
             return nil
         }
     }
@@ -111,6 +123,8 @@
             self = .otherSettings(items: items)
         case .removeAccountSettings(items: let items):
             self = .removeAccountSettings(items: items)
+        case .donations(items: let items):
+            self = .donations(items: items)
         }
     }
 }
@@ -207,6 +221,20 @@
             .just(.notificationSettings( items: [.notifications]))
     }()
 
+    lazy var donationsSettings: Observable<SettingsSection> = {
+        var items: [SettingsSection.SectionRow] = []
+        if !PreferenceManager.isReachEndOfDonationCampaign() {
+            items.append(contentsOf: [
+                .donationCampaign
+            ])
+        }
+        items.append(contentsOf: [
+            .donate
+        ])
+        return Observable
+            .just(.donations( items: items))
+    }()
+
     lazy var connectivitySettings: Observable<SettingsSection> = {
         var server = ""
         var username = ""
@@ -261,11 +289,12 @@
     lazy var jamiSettings: Observable<[SettingsSection]> = {
         Observable.combineLatest(accountCredentials,
                                  linkedDevices,
+                                 donationsSettings,
                                  accountJamiSettings,
                                  connectivitySettings,
                                  otherJamiSettings,
-                                 removeAccountSettings) { (credentials, devices, settings, connectivity, other, removeAccount) in
-            return [credentials, devices, settings, connectivity, other, removeAccount]
+                                 removeAccountSettings) { (credentials, devices, donate, settings, connectivity, other, removeAccount) in
+            return [credentials, devices, donate, settings, connectivity, other, removeAccount]
         }
     }()
 
@@ -323,8 +352,9 @@
 
     lazy var sipSettings: Observable<[SettingsSection]> = {
         Observable.combineLatest(sipCredentials,
-                                 otherSipSettings) { (credentials, other) in
-            return [credentials, other]
+                                 donationsSettings,
+                                 otherSipSettings) { (credentials, donate, other) in
+            return [credentials, donate, other]
         }
     }()
 
@@ -354,6 +384,7 @@
         self.contactService = injectionBag.contactsService
         self.presenceService = injectionBag.presenceService
         self.secureTextEntry.onNext(true)
+        self.enableDonationCampaign = BehaviorRelay<Bool>(value: PreferenceManager.isCampaignEnabled())
     }
 
     func updateDataFor(account: AccountModel) {
@@ -554,6 +585,8 @@
     let currentAccountProxy = PublishSubject<Bool>()
     let currentAccountState = PublishSubject<AccountState>()
 
+    var enableDonationCampaign: BehaviorRelay<Bool>
+
     lazy var accountState: Observable<AccountState> = {
         var state = AccountState.registered
         if let account = self.accountService.currentAccount {
@@ -807,6 +840,21 @@
         keepAliveEnabled.accept(enable)
     }
 
+    func donate() {
+        SharedActionsPresenter.openDonationLink()
+    }
+
+    func togleEnableDonationCampaign(enable: Bool) {
+        if enableDonationCampaign.value == enable {
+            return
+        }
+        PreferenceManager.setCampaignEnabled(enable)
+        if enable {
+            PreferenceManager.setStartDonationDate(DefaultValues.donationStartDate)
+        }
+        enableDonationCampaign.accept(enable)
+    }
+
     // MARK: Connectivity
     lazy var turnEnabled: BehaviorRelay<Bool> = {
         if let account = self.accountService.currentAccount,