diff --git a/kDrive/Resources/de.lproj/Localizable.strings b/kDrive/Resources/de.lproj/Localizable.strings
index ab76ffb78..944d2cb43 100644
--- a/kDrive/Resources/de.lproj/Localizable.strings
+++ b/kDrive/Resources/de.lproj/Localizable.strings
@@ -3,8 +3,8 @@
* Project: kDrive
* Locale: de, German
* Tagged: ios
- * Exported by: Matthieu Déglon
- * Exported at: Thu, 03 Oct 2024 08:22:20 +0200
+ * Exported by: Baptiste Griva
+ * Exported at: Fri, 20 Dec 2024 14:32:53 +0100
*/
/* loco:610a8791fa12ab20713c09e4 */
@@ -1540,6 +1540,12 @@
/* loco:63846ac1f8786f515b61f752 */
"photoLibraryAccessLimitedTitle" = "Eingeschränkter oder verweigerter Zugang";
+/* loco:6765711b1f6cfc8c5408ee33 */
+"photoSyncSuspended" = "Verbinden Sie sich mit einem Wi-Fi-Netzwerk oder erlauben Sie die mobile Datennutzung";
+
+/* loco:67657012f62b39abc50deb62 */
+"photoSyncSuspendedTitle" = "Fotosicherung ausgesetzt";
+
/* loco:627cf782146a6d748e5e7262 */
"photosHeaderDateFormat" = "MMMM yyyy";
@@ -2155,6 +2161,9 @@
/* loco:6049df4d5c2c3a04bc397a8c */
"uploadNetworkErrorWifiRequired" = "Warten auf WLAN";
+/* loco:66fbba74682fe9a0990df012 */
+"uploadOverDataRestrictedError" = "Warten auf Wi-Fi";
+
/* loco:60928fcf72952001716b86d2 */
"uploadPausedDescription" = "Einige Uploads sind in kDrive noch im Gange. Öffnen Sie die App und lassen Sie das Gerät verbunden, um den Upload zu beschleunigen.";
diff --git a/kDrive/Resources/en.lproj/Localizable.strings b/kDrive/Resources/en.lproj/Localizable.strings
index 792b04078..60dc9e704 100644
--- a/kDrive/Resources/en.lproj/Localizable.strings
+++ b/kDrive/Resources/en.lproj/Localizable.strings
@@ -1,10 +1,10 @@
/*
- * Loco ios export: iOS Localizable.strings
+ * Loco ios export: Xcode Strings (legacy)
* Project: kDrive
* Locale: en, English
* Tagged: ios
* Exported by: Baptiste Griva
- * Exported at: Thu, 26 Sep 2024 10:46:53 +0200
+ * Exported at: Fri, 20 Dec 2024 14:32:53 +0100
*/
/* loco:610a8791fa12ab20713c09e4 */
@@ -1540,6 +1540,12 @@
/* loco:63846ac1f8786f515b61f752 */
"photoLibraryAccessLimitedTitle" = "Restricted or denied access";
+/* loco:6765711b1f6cfc8c5408ee33 */
+"photoSyncSuspended" = "Connect to a Wi-Fi network or allow mobile data usage";
+
+/* loco:67657012f62b39abc50deb62 */
+"photoSyncSuspendedTitle" = "Photo backup suspended";
+
/* loco:627cf782146a6d748e5e7262 */
"photosHeaderDateFormat" = "MMMM yyyy";
@@ -2155,6 +2161,9 @@
/* loco:6049df4d5c2c3a04bc397a8c */
"uploadNetworkErrorWifiRequired" = "Waiting for WiFi network";
+/* loco:66fbba74682fe9a0990df012 */
+"uploadOverDataRestrictedError" = "Waiting for Wi-Fi";
+
/* loco:60928fcf72952001716b86d2 */
"uploadPausedDescription" = "Some uploads are still in progress in kDrive. Open the app and keep the device connected to speed up the upload.";
diff --git a/kDrive/Resources/es.lproj/Localizable.strings b/kDrive/Resources/es.lproj/Localizable.strings
index 62fd6e3dc..e156f2a3a 100644
--- a/kDrive/Resources/es.lproj/Localizable.strings
+++ b/kDrive/Resources/es.lproj/Localizable.strings
@@ -3,8 +3,8 @@
* Project: kDrive
* Locale: es, Spanish
* Tagged: ios
- * Exported by: Matthieu Déglon
- * Exported at: Thu, 03 Oct 2024 08:22:20 +0200
+ * Exported by: Baptiste Griva
+ * Exported at: Fri, 20 Dec 2024 14:32:53 +0100
*/
/* loco:610a8791fa12ab20713c09e4 */
@@ -1540,6 +1540,12 @@
/* loco:63846ac1f8786f515b61f752 */
"photoLibraryAccessLimitedTitle" = "Acceso restringido o denegado";
+/* loco:6765711b1f6cfc8c5408ee33 */
+"photoSyncSuspended" = "Conectarse a una red Wi-Fi o permitir el uso de datos móviles";
+
+/* loco:67657012f62b39abc50deb62 */
+"photoSyncSuspendedTitle" = "Suspendida la copia de seguridad de fotos";
+
/* loco:627cf782146a6d748e5e7262 */
"photosHeaderDateFormat" = "MMMM yyyy";
@@ -2155,6 +2161,9 @@
/* loco:6049df4d5c2c3a04bc397a8c */
"uploadNetworkErrorWifiRequired" = "A la espera de red WiFi";
+/* loco:66fbba74682fe9a0990df012 */
+"uploadOverDataRestrictedError" = "A la espera de Wi-Fi";
+
/* loco:60928fcf72952001716b86d2 */
"uploadPausedDescription" = "Algunas subidas siguen en curso en kDrive. Abre la aplicación y mantén el dispositivo conectado para acelerar la carga.";
diff --git a/kDrive/Resources/fr.lproj/Localizable.strings b/kDrive/Resources/fr.lproj/Localizable.strings
index aa9d63a19..05efc0ef6 100644
--- a/kDrive/Resources/fr.lproj/Localizable.strings
+++ b/kDrive/Resources/fr.lproj/Localizable.strings
@@ -3,8 +3,8 @@
* Project: kDrive
* Locale: fr, French
* Tagged: ios
- * Exported by: Matthieu Déglon
- * Exported at: Thu, 03 Oct 2024 08:22:20 +0200
+ * Exported by: Baptiste Griva
+ * Exported at: Fri, 20 Dec 2024 14:32:53 +0100
*/
/* loco:610a8791fa12ab20713c09e4 */
@@ -1540,6 +1540,12 @@
/* loco:63846ac1f8786f515b61f752 */
"photoLibraryAccessLimitedTitle" = "Accès limité ou refusé";
+/* loco:6765711b1f6cfc8c5408ee33 */
+"photoSyncSuspended" = "Se connecter à un réseau Wi-Fi ou autoriser l’utilisation de données mobiles";
+
+/* loco:67657012f62b39abc50deb62 */
+"photoSyncSuspendedTitle" = "Sauvegarde des photos suspendue";
+
/* loco:627cf782146a6d748e5e7262 */
"photosHeaderDateFormat" = "MMMM yyyy";
@@ -2155,6 +2161,9 @@
/* loco:6049df4d5c2c3a04bc397a8c */
"uploadNetworkErrorWifiRequired" = "En attente de réseau Wi-Fi";
+/* loco:66fbba74682fe9a0990df012 */
+"uploadOverDataRestrictedError" = "En attente de Wi-Fi";
+
/* loco:60928fcf72952001716b86d2 */
"uploadPausedDescription" = "Des importations sont toujours en cours dans kDrive. Ouvrez l’app et gardez l’appareil branché pour accélérer l’upload.";
diff --git a/kDrive/Resources/it.lproj/Localizable.strings b/kDrive/Resources/it.lproj/Localizable.strings
index 59cf14ba1..1562bbbf0 100644
--- a/kDrive/Resources/it.lproj/Localizable.strings
+++ b/kDrive/Resources/it.lproj/Localizable.strings
@@ -3,8 +3,8 @@
* Project: kDrive
* Locale: it, Italian
* Tagged: ios
- * Exported by: Matthieu Déglon
- * Exported at: Thu, 03 Oct 2024 08:22:20 +0200
+ * Exported by: Baptiste Griva
+ * Exported at: Fri, 20 Dec 2024 14:32:53 +0100
*/
/* loco:610a8791fa12ab20713c09e4 */
@@ -1540,6 +1540,12 @@
/* loco:63846ac1f8786f515b61f752 */
"photoLibraryAccessLimitedTitle" = "Accesso limitato o negato";
+/* loco:6765711b1f6cfc8c5408ee33 */
+"photoSyncSuspended" = "Collegarsi a una rete Wi-Fi o consentire l’utilizzo di dati mobili";
+
+/* loco:67657012f62b39abc50deb62 */
+"photoSyncSuspendedTitle" = "Backup delle foto sospeso";
+
/* loco:627cf782146a6d748e5e7262 */
"photosHeaderDateFormat" = "MMMM yyyy";
@@ -2155,6 +2161,9 @@
/* loco:6049df4d5c2c3a04bc397a8c */
"uploadNetworkErrorWifiRequired" = "In attesa di connessione alla rete Wi-Fi";
+/* loco:66fbba74682fe9a0990df012 */
+"uploadOverDataRestrictedError" = "In attesa del Wi-Fi";
+
/* loco:60928fcf72952001716b86d2 */
"uploadPausedDescription" = "Alcuni caricamenti sono ancora in corso in kDrive. Aprite l’app e mantenete il dispositivo connesso per accelerare il caricamento.";
diff --git a/kDrive/UI/Controller/Files/Upload/UploadQueueViewController.swift b/kDrive/UI/Controller/Files/Upload/UploadQueueViewController.swift
index 42d95ddba..e85e23a64 100644
--- a/kDrive/UI/Controller/Files/Upload/UploadQueueViewController.swift
+++ b/kDrive/UI/Controller/Files/Upload/UploadQueueViewController.swift
@@ -42,6 +42,7 @@ final class UploadQueueViewController: UIViewController {
navigationItem.hideBackButtonText()
tableView.register(cellView: UploadTableViewCell.self)
+ tableView.register(cellView: ErrorUploadTableViewCell.self)
retryButton.accessibilityLabel = KDriveResourcesStrings.Localizable.buttonRetry
cancelButton.accessibilityLabel = KDriveResourcesStrings.Localizable.buttonCancel
@@ -58,6 +59,7 @@ final class UploadQueueViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
MatomoUtils.track(view: [MatomoUtils.Views.uploadQueue.displayName, "Main"])
+
}
deinit {
@@ -134,21 +136,35 @@ extension UploadQueueViewController: UITableViewDataSource {
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
- let cell = tableView.dequeueReusableCell(type: UploadTableViewCell.self, for: indexPath)
- cell.initWithPositionAndShadow(isFirst: indexPath.row == 0,
- isLast: indexPath.row == self.tableView(
- tableView,
- numberOfRowsInSection: indexPath.section
- ) - 1)
-
- /// Make sure the file is valid
- let file = uploadingFiles[indexPath.row]
- if !file.isInvalidated {
- let progress: CGFloat? = (file.progress != nil) ? CGFloat(file.progress!) : nil
- cell.configureWith(uploadFile: file, progress: progress)
+ if indexPath.row == 0 && UserDefaults.shared.isWifiOnly && ReachabilityListener.instance.currentStatus == .cellular {
+ let cell = tableView.dequeueReusableCell(type: ErrorUploadTableViewCell.self, for: indexPath)
+ cell.initWithPositionAndShadow(isFirst: true,
+ isLast: true)
+ cell.delegate = self
+ return cell
+ } else {
+ let cell = tableView.dequeueReusableCell(type: UploadTableViewCell.self, for: indexPath)
+ cell.initWithPositionAndShadow(isFirst: indexPath.row == 0,
+ isLast: indexPath.row == self.tableView(
+ tableView,
+ numberOfRowsInSection: indexPath.section
+ ) - 1)
+
+ /// Make sure the file is valid
+ let file = uploadingFiles[indexPath.row]
+ if !file.isInvalidated {
+ let progress: CGFloat? = (file.progress != nil) ? CGFloat(file.progress!) : nil
+ cell.configureWith(uploadFile: file, progress: progress)
+ }
+
+ cell.selectionStyle = .none
+ return cell
}
+ }
+}
- cell.selectionStyle = .none
- return cell
+extension UploadQueueViewController: AccessParametersDelegate {
+ func parameterButtonTapped() {
+ navigationController?.pushViewController(PhotoSyncSettingsViewController(), animated: true)
}
}
diff --git a/kDrive/UI/Controller/Home/RootMenuHeaderView.swift b/kDrive/UI/Controller/Home/RootMenuHeaderView.swift
index 89b305334..a8db7a6cb 100644
--- a/kDrive/UI/Controller/Home/RootMenuHeaderView.swift
+++ b/kDrive/UI/Controller/Home/RootMenuHeaderView.swift
@@ -35,6 +35,10 @@ class RootMenuHeaderView: UICollectionReusableView {
var onUploadCardViewTapped: (() -> Void)?
+ deinit {
+ NotificationCenter.default.removeObserver(self)
+ }
+
override func awakeFromNib() {
super.awakeFromNib()
@@ -45,9 +49,7 @@ class RootMenuHeaderView: UICollectionReusableView {
radius: 10
)
- uploadCardView.titleLabel.text = KDriveResourcesStrings.Localizable.uploadInProgressTitle
- uploadCardView.progressView.setInfomaniakStyle()
- uploadCardView.progressView.enableIndeterminate()
+ updateWifiView()
uploadCardView.isHidden = true
offlineView.isHidden = true
@@ -55,6 +57,13 @@ class RootMenuHeaderView: UICollectionReusableView {
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTapOnUploadCardView))
uploadCardView.addGestureRecognizer(tapGestureRecognizer)
+
+ NotificationCenter.default.addObserver(
+ self,
+ selector: #selector(reloadWifiView),
+ name: .reloadWifiView,
+ object: nil
+ )
}
func configureInCollectionView(
@@ -82,6 +91,11 @@ class RootMenuHeaderView: UICollectionReusableView {
}
}
+ @objc func reloadWifiView(_ notification: Notification) {
+ print("Call observeNetworkChange")
+ updateWifiView()
+ }
+
@objc func didTapOnUploadCardView() {
onUploadCardViewTapped?()
}
@@ -113,11 +127,34 @@ class RootMenuHeaderView: UICollectionReusableView {
guard let self else { return }
offlineView.isHidden = status != .offline
- reloadHeader()
+
+ updateWifiView()
}
}
}
+ private func updateWifiView() {
+ if UserDefaults.shared.isWifiOnly && ReachabilityListener.instance.currentStatus == .cellular {
+ uploadCardView.titleLabel.text = KDriveResourcesStrings.Localizable.uploadPausedTitle
+ uploadCardView.progressView.isHidden = true
+ uploadCardView.iconView.image = UIImage(systemName: "exclamationmark.arrow.triangle.2.circlepath")
+ uploadCardView.iconView.isHidden = false
+ uploadCardView.iconView.translatesAutoresizingMaskIntoConstraints = false
+ NSLayoutConstraint.activate([
+ uploadCardView.iconView.widthAnchor.constraint(equalToConstant: 24),
+ uploadCardView.iconView.heightAnchor.constraint(equalToConstant: 24)
+ ])
+ uploadCardView.iconView.tintColor = .gray
+ } else {
+ uploadCardView.titleLabel.text = KDriveResourcesStrings.Localizable.uploadInProgressTitle
+ uploadCardView.progressView.isHidden = false
+ uploadCardView.iconView.isHidden = true
+ uploadCardView.progressView.setInfomaniakStyle()
+ uploadCardView.progressView.enableIndeterminate()
+ }
+ reloadHeader()
+ }
+
private func reloadHeader() {
hideIfNeeded()
diff --git a/kDrive/UI/Controller/Home/RootMenuHeaderView.xib b/kDrive/UI/Controller/Home/RootMenuHeaderView.xib
index a4f4a3155..5b7319805 100644
--- a/kDrive/UI/Controller/Home/RootMenuHeaderView.xib
+++ b/kDrive/UI/Controller/Home/RootMenuHeaderView.xib
@@ -172,7 +172,7 @@
-
+
diff --git a/kDrive/UI/Controller/Menu/MenuViewController.swift b/kDrive/UI/Controller/Menu/MenuViewController.swift
index ae38221e6..bbab5491e 100644
--- a/kDrive/UI/Controller/Menu/MenuViewController.swift
+++ b/kDrive/UI/Controller/Menu/MenuViewController.swift
@@ -84,6 +84,10 @@ final class MenuViewController: UITableViewController, SelectSwitchDriveDelegate
fatalError("init(coder:) has not been implemented")
}
+ deinit {
+ NotificationCenter.default.removeObserver(self)
+ }
+
override func viewDidLoad() {
super.viewDidLoad()
@@ -92,12 +96,27 @@ final class MenuViewController: UITableViewController, SelectSwitchDriveDelegate
tableView.register(cellView: MenuTableViewCell.self)
tableView.register(cellView: MenuTopTableViewCell.self)
tableView.register(cellView: UploadsInProgressTableViewCell.self)
+ tableView.register(cellView: UploadsPausedTableViewCell.self)
tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: UIConstants.listPaddingBottom, right: 0)
updateTableContent()
navigationItem.title = KDriveResourcesStrings.Localizable.menuTitle
navigationItem.hideBackButtonText()
+
+ NotificationCenter.default.addObserver(
+ self,
+ selector: #selector(reloadWifiView),
+ name: .reloadWifiView,
+ object: nil
+ )
+
+ ReachabilityListener.instance.observeNetworkChange(self) { [weak self] _ in
+ Task { @MainActor in
+ let indexPath = IndexPath(row: 0, section: 1)
+ self?.tableView.reloadRows(at: [indexPath], with: .automatic)
+ }
+ }
}
override func viewWillAppear(_ animated: Bool) {
@@ -163,6 +182,10 @@ final class MenuViewController: UITableViewController, SelectSwitchDriveDelegate
sections.insert(.uploads, at: 1)
}
}
+
+ @objc func reloadWifiView(_ notification: Notification) {
+ reloadData()
+ }
}
// MARK: - Table view delegate
@@ -194,11 +217,18 @@ extension MenuViewController {
cell.switchDriveButton.addTarget(self, action: #selector(switchDriveButtonPressed(_:)), for: .touchUpInside)
return cell
} else if section == .uploads {
- let cell = tableView.dequeueReusableCell(type: UploadsInProgressTableViewCell.self, for: indexPath)
- cell.initWithPositionAndShadow(isFirst: true, isLast: true)
- cell.progressView.enableIndeterminate()
- cell.setUploadCount(uploadCountManager?.uploadCount ?? 0)
- return cell
+ if UserDefaults.shared.isWifiOnly && ReachabilityListener.instance.currentStatus == .cellular {
+ let cell = tableView.dequeueReusableCell(type: UploadsPausedTableViewCell.self, for: indexPath)
+ cell.initWithPositionAndShadow(isFirst: true, isLast: true)
+ cell.setUploadCount(uploadCountManager?.uploadCount ?? 0)
+ return cell
+ } else {
+ let cell = tableView.dequeueReusableCell(type: UploadsInProgressTableViewCell.self, for: indexPath)
+ cell.initWithPositionAndShadow(isFirst: true, isLast: true)
+ cell.progressView.enableIndeterminate()
+ cell.setUploadCount(uploadCountManager?.uploadCount ?? 0)
+ return cell
+ }
} else {
let action = section.actions[indexPath.row]
let cell = tableView.dequeueReusableCell(type: MenuTableViewCell.self, for: indexPath)
diff --git a/kDrive/UI/Controller/Menu/OfflineSyncSettingsViewController.swift b/kDrive/UI/Controller/Menu/OfflineSyncSettingsViewController.swift
new file mode 100644
index 000000000..460fa401d
--- /dev/null
+++ b/kDrive/UI/Controller/Menu/OfflineSyncSettingsViewController.swift
@@ -0,0 +1,64 @@
+/*
+ Infomaniak kDrive - iOS App
+ Copyright (C) 2021 Infomaniak Network SA
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
+
+import kDriveCore
+import UIKit
+
+class OfflineSyncSettingsViewController: BaseGroupedTableViewController {
+ private var tableContent: [SyncMode] = SyncMode.allCases
+ private var selectedOfflineMode: SyncMode = UserDefaults.shared.syncOfflineMode
+
+ weak var delegate: SelectPhotoFormatDelegate?
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ tableView.register(cellView: ParameterSyncTableViewCell.self)
+ }
+
+ override func viewDidAppear(_ animated: Bool) {
+ super.viewDidAppear(animated)
+ MatomoUtils.track(view: [MatomoUtils.Views.menu.displayName, MatomoUtils.Views.settings.displayName, "selectOfflineMode"])
+ }
+
+ override func numberOfSections(in tableView: UITableView) -> Int {
+ return 1
+ }
+
+ override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+ return tableContent.count
+ }
+
+ override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+ let cell = tableView.dequeueReusableCell(type: ParameterSyncTableViewCell.self, for: indexPath)
+ cell.initWithPositionAndShadow(isFirst: true, isLast: true)
+ let currentMode = tableContent[indexPath.row]
+ cell.syncTitleLabel.text = currentMode.title
+ cell.syncDetailLabel.text = currentMode.selectionTitle
+ if currentMode == selectedOfflineMode {
+ tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
+ }
+ return cell
+ }
+
+ override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+ let mode = tableContent[indexPath.row]
+ MatomoUtils.track(eventWithCategory: .settings, name: "mod\(mode.rawValue.capitalized)")
+ UserDefaults.shared.syncOfflineMode = mode
+ navigationController?.popViewController(animated: true)
+ }
+}
diff --git a/kDrive/UI/Controller/Menu/ParameterTableViewController.swift b/kDrive/UI/Controller/Menu/ParameterTableViewController.swift
index e7119e165..c3a5a5946 100644
--- a/kDrive/UI/Controller/Menu/ParameterTableViewController.swift
+++ b/kDrive/UI/Controller/Menu/ParameterTableViewController.swift
@@ -35,7 +35,7 @@ class ParameterTableViewController: BaseGroupedTableViewController {
case theme
case notifications
case security
- case wifi
+ case offlineSync
case storage
case about
case deleteAccount
@@ -50,7 +50,7 @@ class ParameterTableViewController: BaseGroupedTableViewController {
return KDriveResourcesStrings.Localizable.notificationTitle
case .security:
return KDriveResourcesStrings.Localizable.securityTitle
- case .wifi:
+ case .offlineSync:
return KDriveResourcesStrings.Localizable.syncWifiSettingsTitle
case .storage:
return KDriveResourcesStrings.Localizable.manageStorageTitle
@@ -137,11 +137,11 @@ class ParameterTableViewController: BaseGroupedTableViewController {
cell.titleLabel.text = row.title
return cell
- case .wifi:
+ case .offlineSync:
let cell = tableView.dequeueReusableCell(type: AboutDetailTableViewCell.self, for: indexPath)
cell.initWithPositionAndShadow(isFirst: indexPath.row == 0, isLast: indexPath.row == tableContent.count - 1)
- cell.titleLabel.text = UserDefaults.shared.syncMode.title
- cell.detailLabel.text = UserDefaults.shared.syncMode.selectionTitle
+ cell.titleLabel.text = KDriveResourcesStrings.Localizable.syncWifiSettingsTitle
+ cell.detailLabel.text = UserDefaults.shared.syncOfflineMode.title
return cell
}
}
@@ -161,8 +161,8 @@ class ParameterTableViewController: BaseGroupedTableViewController {
navigationController?.pushViewController(NotificationsSettingsTableViewController(), animated: true)
case .security:
navigationController?.pushViewController(SecurityTableViewController(), animated: true)
- case .wifi:
- navigationController?.pushViewController(WifiSyncSettingsViewController(), animated: true)
+ case .offlineSync:
+ navigationController?.pushViewController(OfflineSyncSettingsViewController(), animated: true)
case .about:
navigationController?.pushViewController(AboutTableViewController(), animated: true)
case .deleteAccount:
diff --git a/kDrive/UI/Controller/Menu/PhotoSyncSettingsViewController.swift b/kDrive/UI/Controller/Menu/PhotoSyncSettingsViewController.swift
index 9fb79f767..2258ded18 100644
--- a/kDrive/UI/Controller/Menu/PhotoSyncSettingsViewController.swift
+++ b/kDrive/UI/Controller/Menu/PhotoSyncSettingsViewController.swift
@@ -434,7 +434,7 @@ extension PhotoSyncSettingsViewController {
let cell = tableView.dequeueReusableCell(type: AboutDetailTableViewCell.self, for: indexPath)
cell.initWithPositionAndShadow(isFirst: indexPath.row == 0, isLast: indexPath.row == settingsRows.count - 1)
cell.titleLabel.text = KDriveResourcesStrings.Localizable.syncWifiPicturesTitle
- cell.detailLabel.text = UserDefaults.shared.syncMode.title
+ cell.detailLabel.text = newSyncSettings.wifiSync.title
return cell
}
case .syncDenied:
@@ -584,9 +584,16 @@ extension PhotoSyncSettingsViewController: PhotoSyncSettingsTableViewCellDelegat
extension PhotoSyncSettingsViewController: WifiSyncSettingsDelegate {
func didSelectSyncMode(_ mode: SyncMode) {
newSyncSettings.wifiSync = mode
+ if mode == .onlyWifi {
+ UserDefaults.shared.isWifiOnly = true
+ } else {
+ UserDefaults.shared.isWifiOnly = false
+ }
+ updateSaveButtonState()
tableView.reloadRows(
at: [IndexPath(row: PhotoSyncSettingsRows.wifiSync.rawValue, section: PhotoSyncSection.syncSettings.rawValue)],
with: .fade
)
+ NotificationCenter.default.post(name: .reloadWifiView, object: nil)
}
}
diff --git a/kDrive/UI/Controller/Menu/WifiSyncSettingsViewController.swift b/kDrive/UI/Controller/Menu/WifiSyncSettingsViewController.swift
index c07094505..1eb8c8587 100644
--- a/kDrive/UI/Controller/Menu/WifiSyncSettingsViewController.swift
+++ b/kDrive/UI/Controller/Menu/WifiSyncSettingsViewController.swift
@@ -40,8 +40,6 @@ class WifiSyncSettingsViewController: BaseGroupedTableViewController {
tableView.register(cellView: ParameterSyncTableViewCell.self)
tableView.allowsMultipleSelection = false
-
- selectedMode = UserDefaults.shared.syncMode
}
static func instantiate(selectedMode: SyncMode) -> WifiSyncSettingsViewController {
@@ -67,18 +65,17 @@ class WifiSyncSettingsViewController: BaseGroupedTableViewController {
let cell = tableView.dequeueReusableCell(type: ParameterSyncTableViewCell.self, for: indexPath)
cell.initWithPositionAndShadow(isFirst: true, isLast: true)
let currentMode = tableContent[indexPath.row]
+ cell.syncTitleLabel.text = currentMode.title
+ cell.syncDetailLabel.text = currentMode.selectionTitle
if currentMode == selectedMode {
tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
}
- cell.syncTitleLabel.text = currentMode.title
- cell.syncDetailLabel.text = currentMode.selectionTitle
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let mode = tableContent[indexPath.row]
- MatomoUtils.track(eventWithCategory: .settings, name: "mode\(mode.rawValue.capitalized)")
- UserDefaults.shared.syncMode = mode
+ MatomoUtils.track(eventWithCategory: .settings, name: "mod\(mode.rawValue.capitalized)")
delegate?.didSelectSyncMode(tableContent[indexPath.row])
navigationController?.popViewController(animated: true)
}
diff --git a/kDrive/UI/View/Files/Upload/ErrorUploadTableViewCell.swift b/kDrive/UI/View/Files/Upload/ErrorUploadTableViewCell.swift
new file mode 100644
index 000000000..ea76aa6a3
--- /dev/null
+++ b/kDrive/UI/View/Files/Upload/ErrorUploadTableViewCell.swift
@@ -0,0 +1,40 @@
+/*
+ Infomaniak kDrive - iOS App
+ Copyright (C) 2024 Infomaniak Network SA
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
+
+import InfomaniakCoreUIKit
+import kDriveCore
+import kDriveResources
+import UIKit
+
+protocol AccessParametersDelegate: AnyObject {
+ func parameterButtonTapped()
+}
+
+class ErrorUploadTableViewCell: InsetTableViewCell {
+ @IBOutlet var bannerView: UIView!
+ @IBOutlet var errorIconImageView: UIImageView!
+ @IBOutlet var errorTitleLabel: UILabel!
+ @IBOutlet var errorDetailLabel: UILabel!
+ @IBOutlet var settingButton: UIButton!
+
+ weak var delegate: AccessParametersDelegate?
+
+ @IBAction func updateButtonPressed(_ sender: UIButton) {
+ delegate?.parameterButtonTapped()
+ }
+}
diff --git a/kDrive/UI/View/Files/Upload/ErrorUploadTableViewCell.xib b/kDrive/UI/View/Files/Upload/ErrorUploadTableViewCell.xib
new file mode 100644
index 000000000..3bf5e9028
--- /dev/null
+++ b/kDrive/UI/View/Files/Upload/ErrorUploadTableViewCell.xib
@@ -0,0 +1,164 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/kDrive/UI/View/Files/Upload/UploadTableViewCell.swift b/kDrive/UI/View/Files/Upload/UploadTableViewCell.swift
index c751dbb69..247f1fcd2 100644
--- a/kDrive/UI/View/Files/Upload/UploadTableViewCell.swift
+++ b/kDrive/UI/View/Files/Upload/UploadTableViewCell.swift
@@ -74,8 +74,13 @@ final class UploadTableViewCell: InsetTableViewCell {
if let error = uploadFile.error, error != .taskRescheduled {
cardContentView.retryButton?.isHidden = false
- cardContentView.detailsLabel.text = KDriveResourcesStrings.Localizable
- .errorUpload + " (\(error.localizedDescription))"
+ if error.localizedDescription == KDriveResourcesStrings.Localizable.uploadOverDataRestrictedError {
+ cardContentView.detailsLabel.text = error.localizedDescription
+ } else {
+ cardContentView.detailsLabel.text = KDriveResourcesStrings.Localizable
+ .errorUpload + " (\(error.localizedDescription))"
+ }
+
} else {
cardContentView.retryButton?
.isHidden = (uploadFile.maxRetryCount > 0) // Display retry for uploads that reached automatic retry limit
diff --git a/kDrive/UI/View/Home/UploadsPausedTableViewCell.swift b/kDrive/UI/View/Home/UploadsPausedTableViewCell.swift
new file mode 100644
index 000000000..82c72c3ff
--- /dev/null
+++ b/kDrive/UI/View/Home/UploadsPausedTableViewCell.swift
@@ -0,0 +1,30 @@
+/*
+ Infomaniak kDrive - iOS App
+ Copyright (C) 2024 Infomaniak Network SA
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
+
+import InfomaniakCoreUIKit
+import kDriveCore
+import kDriveResources
+import UIKit
+
+class UploadsPausedTableViewCell: InsetTableViewCell {
+ @IBOutlet var subtitleLabel: IKLabel!
+
+ func setUploadCount(_ count: Int) {
+ subtitleLabel.text = KDriveResourcesStrings.Localizable.uploadInProgressNumberFile(count)
+ }
+}
diff --git a/kDrive/UI/View/Home/UploadsPausedTableViewCell.xib b/kDrive/UI/View/Home/UploadsPausedTableViewCell.xib
new file mode 100644
index 000000000..f01b4c9ff
--- /dev/null
+++ b/kDrive/UI/View/Home/UploadsPausedTableViewCell.xib
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/kDrive/UI/View/Menu/Parameters/ParameterSyncTableViewCell.swift b/kDrive/UI/View/Menu/Parameters/ParameterSyncTableViewCell.swift
index e576a8a0f..1544217af 100644
--- a/kDrive/UI/View/Menu/Parameters/ParameterSyncTableViewCell.swift
+++ b/kDrive/UI/View/Menu/Parameters/ParameterSyncTableViewCell.swift
@@ -17,9 +17,22 @@
*/
import InfomaniakCoreUIKit
+import kDriveResources
import UIKit
class ParameterSyncTableViewCell: InsetTableViewCell {
@IBOutlet var syncTitleLabel: UILabel!
@IBOutlet var syncDetailLabel: UILabel!
+
+ override func setSelected(_ selected: Bool, animated: Bool) {
+ super.setSelected(selected, animated: animated)
+
+ contentInsetView.backgroundColor = KDriveResourcesAsset.backgroundCardViewColor.color
+ if selected {
+ contentInsetView.borderColor = KDriveResourcesAsset.infomaniakColor.color
+ contentInsetView.borderWidth = 2
+ } else {
+ contentInsetView.borderWidth = 0
+ }
+ }
}
diff --git a/kDriveCore/Data/Cache/DriveFileManager/DriveFileManagerConstants.swift b/kDriveCore/Data/Cache/DriveFileManager/DriveFileManagerConstants.swift
index 2fbe346f1..95f14f048 100644
--- a/kDriveCore/Data/Cache/DriveFileManager/DriveFileManagerConstants.swift
+++ b/kDriveCore/Data/Cache/DriveFileManager/DriveFileManagerConstants.swift
@@ -207,7 +207,7 @@ public class DriveFileManagerConstants {
// Migration to add syncWifi
if oldSchemaVersion < 22 {
- migration.enumerateObjects(ofType: UploadFile.className()) { _, newObject in
+ migration.enumerateObjects(ofType: PhotoSyncSettings.className()) { _, newObject in
guard let newObject else {
return
}
diff --git a/kDriveCore/Data/Models/DriveError.swift b/kDriveCore/Data/Models/DriveError.swift
index f85b04a66..5f18f157d 100644
--- a/kDriveCore/Data/Models/DriveError.swift
+++ b/kDriveCore/Data/Models/DriveError.swift
@@ -141,6 +141,10 @@ public struct DriveError: Error, Equatable {
localizedString: KDriveResourcesStrings.Localizable.errorCache)
public static let unknownError = DriveError(type: .localError, code: "unknownError")
+ public static let uploadOverDataRestrictedError = DriveError(type: .localError,
+ code: "uploadOverDataRestrictedError",
+ localizedString: KDriveResourcesStrings.Localizable.uploadOverDataRestrictedError)
+
// MARK: - Server
public static let refreshToken = DriveError(type: .serverError, code: "refreshToken")
@@ -261,7 +265,8 @@ public struct DriveError: Error, Equatable {
uploadTokenIsNotValid,
fileAlreadyExistsError,
errorDeviceStorage,
- limitExceededError]
+ limitExceededError,
+ uploadOverDataRestrictedError]
private static let encoder = JSONEncoder()
private static let decoder = JSONDecoder()
diff --git a/kDriveCore/Data/UploadQueue/Operation/UploadOperation+Error.swift b/kDriveCore/Data/UploadQueue/Operation/UploadOperation+Error.swift
index ef974c081..07e93f2a2 100644
--- a/kDriveCore/Data/UploadQueue/Operation/UploadOperation+Error.swift
+++ b/kDriveCore/Data/UploadQueue/Operation/UploadOperation+Error.swift
@@ -127,6 +127,8 @@ extension UploadOperation {
// Silently stop if an UploadFile is no longer in base
// _not_ overriding file.error
self.cancel()
+ case .uploadOverDataRestrictedError:
+ file.error = DriveError.uploadOverDataRestrictedError
}
errorHandled = true
diff --git a/kDriveCore/Data/UploadQueue/Operation/UploadOperation+PHAsset.swift b/kDriveCore/Data/UploadQueue/Operation/UploadOperation+PHAsset.swift
index 5ae8f002c..c4dfaca69 100644
--- a/kDriveCore/Data/UploadQueue/Operation/UploadOperation+PHAsset.swift
+++ b/kDriveCore/Data/UploadQueue/Operation/UploadOperation+PHAsset.swift
@@ -17,6 +17,7 @@
*/
import Foundation
+import InfomaniakCore
extension UploadOperation {
func getPhAssetIfNeeded() async throws {
@@ -56,4 +57,24 @@ extension UploadOperation {
file.pathURL = url
}
}
+
+ func checkForRestrictedUploadOverDataMode() throws {
+ let file = try readOnlyFile()
+
+ guard file.type == .phAsset else {
+ // This UploadFile is not a PHAsset, return silently
+ return
+ }
+
+ let status = ReachabilityListener.instance.currentStatus
+ let canUpload = !(status == .cellular && UserDefaults.shared.isWifiOnly)
+
+ guard !canUpload else {
+ return
+ }
+
+ uploadQueue.cancelRunningOperations()
+ uploadQueue.suspendAllOperations()
+ throw ErrorDomain.uploadOverDataRestrictedError
+ }
}
diff --git a/kDriveCore/Data/UploadQueue/Operation/UploadOperation.swift b/kDriveCore/Data/UploadQueue/Operation/UploadOperation.swift
index 69f00cec7..6b6ec781f 100644
--- a/kDriveCore/Data/UploadQueue/Operation/UploadOperation.swift
+++ b/kDriveCore/Data/UploadQueue/Operation/UploadOperation.swift
@@ -58,6 +58,8 @@ public final class UploadOperation: AsynchronousOperation, UploadOperationable {
case operationFinished
/// Cannot decrease further retry count, already zero
case retryCountIsZero
+ /// Cannot upload image because we are not in wifi
+ case uploadOverDataRestrictedError
}
// MARK: - Attributes
@@ -127,6 +129,9 @@ public final class UploadOperation: AsynchronousOperation, UploadOperationable {
// Clean existing error if any
try self.cleanUploadFileError()
+ // Pause the upload depending on the status
+ try self.checkForRestrictedUploadOverDataMode()
+
// Fetch content from local library if needed
try await self.getPhAssetIfNeeded()
diff --git a/kDriveCore/Data/UploadQueue/Queue/UploadQueue+Queue.swift b/kDriveCore/Data/UploadQueue/Queue/UploadQueue+Queue.swift
index e1ad324e8..8850db104 100644
--- a/kDriveCore/Data/UploadQueue/Queue/UploadQueue+Queue.swift
+++ b/kDriveCore/Data/UploadQueue/Queue/UploadQueue+Queue.swift
@@ -88,7 +88,7 @@ extension UploadQueue: UploadQueueable {
return lazyCollection.filter(uploadFileQuery)
.sorted(byKeyPath: "taskCreationDate")
}
- let uploadingFileIds = uploadingFiles.map(\.id)
+ let uploadingFileIds = Array(uploadingFiles.map(\.id))
Log.uploadQueue("rebuildUploadQueueFromObjectsInRealm uploads to restart:\(uploadingFileIds.count)")
let batches = uploadingFileIds.chunks(ofCount: 100)
diff --git a/kDriveCore/Data/UploadQueue/Queue/UploadQueue.swift b/kDriveCore/Data/UploadQueue/Queue/UploadQueue.swift
index 56fa6f94a..8054f82c9 100644
--- a/kDriveCore/Data/UploadQueue/Queue/UploadQueue.swift
+++ b/kDriveCore/Data/UploadQueue/Queue/UploadQueue.swift
@@ -102,7 +102,7 @@ public final class UploadQueue: ParallelismHeuristicDelegate {
}
let status = ReachabilityListener.instance.currentStatus
- return status == .offline || (status != .wifi && UserDefaults.shared.isWifiOnly)
+ return status == .offline
}
/// Should suspend operation queue based on explicit `suspendAllOperations()` call
@@ -139,6 +139,9 @@ public final class UploadQueue: ParallelismHeuristicDelegate {
let isSuspended = (shouldSuspendQueue || forceSuspendQueue)
operationQueue.isSuspended = isSuspended
Log.uploadQueue("observeNetworkChange :\(isSuspended)")
+ if ReachabilityListener.instance.currentStatus == .wifi || !UserDefaults.shared.isWifiOnly {
+ self.resumeAllOperations()
+ }
}
observeMemoryWarnings()
diff --git a/kDriveCore/Utils/DriveUserDefaults+Extension.swift b/kDriveCore/Utils/DriveUserDefaults+Extension.swift
index 1a0682295..5c89598b7 100644
--- a/kDriveCore/Utils/DriveUserDefaults+Extension.swift
+++ b/kDriveCore/Utils/DriveUserDefaults+Extension.swift
@@ -49,7 +49,7 @@ extension UserDefaults.Keys {
static let selectedHomeIndex = UserDefaults.Keys(rawValue: "selectedHomeIndex")
static let fpStorageVersion = UserDefaults.Keys(rawValue: "fpStorageVersion")
static let importPhotoFormat = UserDefaults.Keys(rawValue: "importPhotoFormat")
- static let syncMode = UserDefaults.Keys(rawValue: "syncMode")
+ static let syncOfflineMode = UserDefaults.Keys(rawValue: "syncOfflineMod")
}
public extension UserDefaults {
@@ -338,16 +338,16 @@ public extension UserDefaults {
}
}
- var syncMode: SyncMode {
+ var syncOfflineMode: SyncMode {
get {
- if let rawValue = object(forKey: key(.syncMode)) as? String,
+ if let rawValue = object(forKey: key(.syncOfflineMode)) as? String,
let mode = SyncMode(rawValue: rawValue) {
return mode
}
return .onlyWifi
}
set {
- set(newValue.rawValue, forKey: key(.syncMode))
+ set(newValue.rawValue, forKey: key(.syncOfflineMode))
}
}
}
diff --git a/kDriveCore/Utils/NotificationName+Extension.swift b/kDriveCore/Utils/NotificationName+Extension.swift
index a4454d7e0..1711bbc9c 100644
--- a/kDriveCore/Utils/NotificationName+Extension.swift
+++ b/kDriveCore/Utils/NotificationName+Extension.swift
@@ -21,4 +21,5 @@ import Foundation
public extension Notification.Name {
static let locateUploadActionTapped = Notification.Name(rawValue: "kDriveLocateUploadActionTapped")
static let reloadDrive = Notification.Name(rawValue: "kDriveReloadDrive")
+ static let reloadWifiView = Notification.Name(rawValue: "kDriveReloadWifiView")
}