Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: PhotoSync with explicit wifi or 4G #1440

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 81 additions & 20 deletions kDrive/UI/Controller/Files/Upload/UploadQueueViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ import UIKit
typealias UploadFileDisplayed = CornerCellContainer<UploadFile>

final class UploadQueueViewController: UIViewController {
private let errorFile = UploadFileDisplayed(isFirstInList: true, isLastInList: true, content: UploadFile())

enum SectionModel: Differentiable {
case error, files
}

@IBOutlet var tableView: UITableView!
@IBOutlet var retryButton: UIBarButtonItem!
@IBOutlet var cancelButton: UIBarButtonItem!
Expand All @@ -37,6 +43,7 @@ final class UploadQueueViewController: UIViewController {

var currentDirectory: File!
private var frozenUploadingFiles = [UploadFileDisplayed]()
private lazy var sections = buildSections(files: [UploadFileDisplayed]())
private var notificationToken: NotificationToken?

override func viewDidLoad() {
Expand All @@ -45,6 +52,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
Expand All @@ -53,7 +61,7 @@ final class UploadQueueViewController: UIViewController {

ReachabilityListener.instance.observeNetworkChange(self) { [weak self] _ in
Task { @MainActor in
self?.tableView.reloadData()
self?.reloadCollectionView()
}
}
}
Expand Down Expand Up @@ -94,7 +102,7 @@ final class UploadQueueViewController: UIViewController {
}

guard let newResults else {
reloadCollectionViewWith([])
reloadCollectionView(with: [])
return
}

Expand All @@ -105,22 +113,52 @@ final class UploadQueueViewController: UIViewController {
content: frozenFile)
}

reloadCollectionViewWith(wrappedFrozenFiles)
reloadCollectionView(with: wrappedFrozenFiles)
}
}

func reloadCollectionViewWith(_ frozenFiles: [UploadFileDisplayed]) {
let changeSet = StagedChangeset(source: frozenUploadingFiles, target: frozenFiles)
@MainActor func reloadCollectionView(with frozenFiles: [UploadFileDisplayed]? = nil) {
let newSections: [ArraySection<SectionModel, UploadFileDisplayed>]
if let frozenFiles {
newSections = buildSections(files: frozenFiles)
} else {
newSections = buildSections(files: frozenUploadingFiles)
}

let changeSet = StagedChangeset(source: sections, target: newSections)

tableView.reload(using: changeSet,
with: UITableView.RowAnimation.automatic,
interrupt: { $0.changeCount > Endpoint.itemsPerPage },
setData: { self.frozenUploadingFiles = $0 })

if frozenFiles.isEmpty {
setData: { newValues in
if let frozenFiles {
frozenUploadingFiles = frozenFiles
}
sections = newValues
})

if let frozenFiles, frozenFiles.isEmpty {
navigationController?.popViewController(animated: true)
}
}

private func buildSections(files: [UploadFileDisplayed]) -> [ArraySection<SectionModel, UploadFileDisplayed>] {
guard !isUploadLimited else {
return [
ArraySection(model: SectionModel.error, elements: [errorFile]),
ArraySection(model: SectionModel.files, elements: files)
]
}

return [
ArraySection(model: SectionModel.files, elements: files)
]
}

private var isUploadLimited: Bool {
UserDefaults.shared.isWifiOnly && ReachabilityListener.instance.currentStatus == .cellular
}

@IBAction func cancelButtonPressed(_ sender: UIBarButtonItem) {
uploadQueue.cancelAllOperations(withParent: currentDirectory.id,
userId: accountManager.currentUserId,
Expand All @@ -143,23 +181,46 @@ final class UploadQueueViewController: UIViewController {

extension UploadQueueViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return frozenUploadingFiles.count
guard let rows = sections[safe: section] else {
return 0
}
return rows.elements.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(type: UploadTableViewCell.self, for: indexPath)
let fileWrapper = frozenUploadingFiles[indexPath.row]
let frozenFile = fileWrapper.content
func numberOfSections(in tableView: UITableView) -> Int {
return sections.count
}

cell.initWithPositionAndShadow(isFirst: fileWrapper.isFirstInList,
isLast: fileWrapper.isLastInList)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 && isUploadLimited {
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)

guard let frozenUploadingFiles = sections[safe: indexPath.section]?.elements,
let file = frozenUploadingFiles[safe: indexPath.row]?.content, !file.isInvalidated else {
return cell
}

if !frozenFile.isInvalidated {
let progress: CGFloat? = (frozenFile.progress != nil) ? CGFloat(frozenFile.progress!) : nil
cell.configureWith(frozenUploadFile: frozenFile, progress: progress)
let progress: CGFloat? = (file.progress != nil) ? CGFloat(file.progress!) : nil
cell.configureWith(frozenUploadFile: file, progress: progress)
cell.selectionStyle = .none
return cell
}
}
}

cell.selectionStyle = .none
return cell
extension UploadQueueViewController: AccessParametersDelegate {
func parameterButtonTapped() {
navigationController?.pushViewController(PhotoSyncSettingsViewController(), animated: true)
}
}
44 changes: 40 additions & 4 deletions kDrive/UI/Controller/Home/RootMenuHeaderView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ class RootMenuHeaderView: UICollectionReusableView {

var onUploadCardViewTapped: (() -> Void)?

deinit {
NotificationCenter.default.removeObserver(self)
}

override func awakeFromNib() {
super.awakeFromNib()

Expand All @@ -45,16 +49,21 @@ class RootMenuHeaderView: UICollectionReusableView {
radius: 10
)

uploadCardView.titleLabel.text = KDriveResourcesStrings.Localizable.uploadInProgressTitle
uploadCardView.progressView.setInfomaniakStyle()
uploadCardView.progressView.enableIndeterminate()
updateWifiView()

uploadCardView.isHidden = true
offlineView.isHidden = true
hideIfNeeded()

let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTapOnUploadCardView))
uploadCardView.addGestureRecognizer(tapGestureRecognizer)

NotificationCenter.default.addObserver(
self,
selector: #selector(reloadWifiView),
name: .reloadWifiView,
object: nil
)
}

func configureInCollectionView(
Expand Down Expand Up @@ -82,6 +91,10 @@ class RootMenuHeaderView: UICollectionReusableView {
}
}

@objc func reloadWifiView(_ notification: Notification) {
updateWifiView()
}

@objc func didTapOnUploadCardView() {
onUploadCardViewTapped?()
}
Expand Down Expand Up @@ -113,11 +126,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()

Expand Down
2 changes: 1 addition & 1 deletion kDrive/UI/Controller/Home/RootMenuHeaderView.xib
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@
<color red="0.62352941176470589" green="0.62352941176470589" blue="0.62352941176470589" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="titleColor">
<color red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color red="0.20000000298023224" green="0.20000000298023224" blue="0.20000000298023224" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
Expand Down
40 changes: 35 additions & 5 deletions kDrive/UI/Controller/Menu/MenuViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand All @@ -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.List.paddingBottom, 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) {
Expand Down Expand Up @@ -158,6 +177,10 @@ final class MenuViewController: UITableViewController, SelectSwitchDriveDelegate
sections.insert(.uploads, at: 1)
}
}

@objc func reloadWifiView(_ notification: Notification) {
reloadData()
}
}

// MARK: - Table view delegate
Expand Down Expand Up @@ -189,11 +212,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)
Expand Down
Loading
Loading