diff --git a/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_download_all.imageset/Contents.json b/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_download_all.imageset/Contents.json new file mode 100644 index 0000000000..9987bb3ec1 --- /dev/null +++ b/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_download_all.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Download All.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "Download All@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "Download All@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_download_all.imageset/Download All.png b/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_download_all.imageset/Download All.png new file mode 100644 index 0000000000..c8606c45c5 Binary files /dev/null and b/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_download_all.imageset/Download All.png differ diff --git a/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_download_all.imageset/Download All@2x.png b/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_download_all.imageset/Download All@2x.png new file mode 100644 index 0000000000..7f076b764d Binary files /dev/null and b/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_download_all.imageset/Download All@2x.png differ diff --git a/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_download_all.imageset/Download All@3x.png b/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_download_all.imageset/Download All@3x.png new file mode 100644 index 0000000000..f94d6f71e2 Binary files /dev/null and b/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_download_all.imageset/Download All@3x.png differ diff --git a/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_update_all.imageset/Contents.json b/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_update_all.imageset/Contents.json new file mode 100644 index 0000000000..62c2bf70e3 --- /dev/null +++ b/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_update_all.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Warning.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "Warning@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "Warning@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_update_all.imageset/Warning.png b/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_update_all.imageset/Warning.png new file mode 100644 index 0000000000..e27d47d681 Binary files /dev/null and b/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_update_all.imageset/Warning.png differ diff --git a/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_update_all.imageset/Warning@2x.png b/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_update_all.imageset/Warning@2x.png new file mode 100644 index 0000000000..b7759041f8 Binary files /dev/null and b/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_update_all.imageset/Warning@2x.png differ diff --git a/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_update_all.imageset/Warning@3x.png b/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_update_all.imageset/Warning@3x.png new file mode 100644 index 0000000000..7eaa817f11 Binary files /dev/null and b/iphone/Maps/Images.xcassets/CircularProgress/Downloader/ic_update_all.imageset/Warning@3x.png differ diff --git a/iphone/Maps/Maps.xcodeproj/project.pbxproj b/iphone/Maps/Maps.xcodeproj/project.pbxproj index 652722241f..a3c2140e3a 100644 --- a/iphone/Maps/Maps.xcodeproj/project.pbxproj +++ b/iphone/Maps/Maps.xcodeproj/project.pbxproj @@ -696,6 +696,8 @@ 99F3EB1123F418C900C713F8 /* PlacePageBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99F3EB0B23F418C900C713F8 /* PlacePageBuilder.swift */; }; 99F3EB1223F418C900C713F8 /* PlacePageInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99F3EB0C23F418C900C713F8 /* PlacePageInteractor.swift */; }; 99F8B4C623B644A6009FF0B4 /* MapStyleSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99F8B4C523B644A6009FF0B4 /* MapStyleSheet.swift */; }; + 99F9A0E52462CA0E00AE21E0 /* DownloadAllView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99F9A0E42462CA0E00AE21E0 /* DownloadAllView.swift */; }; + 99F9A0E72462CA1700AE21E0 /* DownloadAllView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 99F9A0E62462CA1700AE21E0 /* DownloadAllView.xib */; }; A630D1EA207CA95900976DEA /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = A630D1E8207CA95900976DEA /* Localizable.stringsdict */; }; B32FE74020D2844600EF7446 /* DownloadedBookmarksViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B32FE73E20D2844600EF7446 /* DownloadedBookmarksViewController.swift */; }; B32FE74120D2844600EF7446 /* DownloadedBookmarksViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = B32FE73F20D2844600EF7446 /* DownloadedBookmarksViewController.xib */; }; @@ -1783,6 +1785,8 @@ 99F3EB0B23F418C900C713F8 /* PlacePageBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlacePageBuilder.swift; sourceTree = ""; }; 99F3EB0C23F418C900C713F8 /* PlacePageInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlacePageInteractor.swift; sourceTree = ""; }; 99F8B4C523B644A6009FF0B4 /* MapStyleSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapStyleSheet.swift; sourceTree = ""; }; + 99F9A0E42462CA0E00AE21E0 /* DownloadAllView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadAllView.swift; sourceTree = ""; }; + 99F9A0E62462CA1700AE21E0 /* DownloadAllView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DownloadAllView.xib; sourceTree = ""; }; 9DF04B231B71010E00DACAF1 /* 02_droidsans-fallback.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "02_droidsans-fallback.ttf"; path = "../../data/02_droidsans-fallback.ttf"; sourceTree = ""; }; A367C93A1B17334800E2B6E7 /* resources-default */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "resources-default"; path = "../../data/resources-default"; sourceTree = ""; }; A630D1E9207CA95900976DEA /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ar; path = ar.lproj/Localizable.stringsdict; sourceTree = ""; }; @@ -4008,6 +4012,15 @@ path = PlacePageManager; sourceTree = ""; }; + 99F9A0E32462C9E800AE21E0 /* DownloadAllView */ = { + isa = PBXGroup; + children = ( + 99F9A0E42462CA0E00AE21E0 /* DownloadAllView.swift */, + 99F9A0E62462CA1700AE21E0 /* DownloadAllView.xib */, + ); + path = DownloadAllView; + sourceTree = ""; + }; B32FE73D20D283D600EF7446 /* Catalog */ = { isa = PBXGroup; children = ( @@ -4416,6 +4429,7 @@ F6E2FBFC1E097B9F0083EBEC /* Downloader */ = { isa = PBXGroup; children = ( + 99F9A0E32462C9E800AE21E0 /* DownloadAllView */, F6E2FBFD1E097B9F0083EBEC /* Cells */, F6E2FC211E097B9F0083EBEC /* MWMMapDownloaderMode.h */, F6E2FC241E097B9F0083EBEC /* NoMaps */, @@ -5082,6 +5096,7 @@ F6E2FD9B1E097BA00083EBEC /* MWMBookmarkTitleCell.xib in Resources */, 4501B1942077C35A001B9173 /* resources-xxxhdpi_clear in Resources */, 3467CEB7202C6FA900D3C670 /* BMCNotificationsCell.xib in Resources */, + 99F9A0E72462CA1700AE21E0 /* DownloadAllView.xib in Resources */, 349D1AD51E2E325B004A2006 /* BottomMenuItemCell.xib in Resources */, 349D1AE11E2E325C004A2006 /* BottomTabBarViewController.xib in Resources */, 34D3B01E1E389D05004100F9 /* MWMButtonCell.xib in Resources */, @@ -5772,6 +5787,7 @@ CD4A1F132305872700F2A6B6 /* PromoBookingPresentationController.swift in Sources */, 3472B5D3200F501500DC6CD5 /* BackgroundFetchTaskFrameworkType.swift in Sources */, 47E460AD240D737D00385B45 /* OpeinigHoursLocalization.swift in Sources */, + 99F9A0E52462CA0E00AE21E0 /* DownloadAllView.swift in Sources */, F6E2FF301E097BA00083EBEC /* MWMSearchCommonCell.mm in Sources */, F655C027207278300048A241 /* DiscoveryMoreCell.swift in Sources */, 337F98B821D3D67E00C8AC27 /* SearchHistoryQueryCell.swift in Sources */, diff --git a/iphone/Maps/UI/Downloader/DownloadAllView/DownloadAllView.swift b/iphone/Maps/UI/Downloader/DownloadAllView/DownloadAllView.swift new file mode 100644 index 0000000000..4355f7d2e3 --- /dev/null +++ b/iphone/Maps/UI/Downloader/DownloadAllView/DownloadAllView.swift @@ -0,0 +1,115 @@ +import UIKit + +protocol DownloadAllViewDelegate: AnyObject { + func onDownloadButtonPressed() + func onCancelButtonPressed() + func onStateChanged(state: DownloadAllView.State) +} + +class DownloadAllView: UIView { + enum State { + case none + case ready + case dowloading + } + enum Style { + case download + case update + } + + @IBOutlet private var iconImageView: UIImageView! + @IBOutlet private var title: UILabel! + @IBOutlet private var downloadSizeLabel: UILabel! + @IBOutlet private var stateWrapper: UIView! + @IBOutlet private var downloadButton: UIButton! + @IBOutlet private var titleCenterConstraint: NSLayoutConstraint! + lazy private var progress: MWMCircularProgress = { + let view = MWMCircularProgress.downloaderProgress(forParentView: stateWrapper) + view.delegate = self + return view + }() + + var isSizeHidden: Bool = false { + didSet { + if oldValue != isSizeHidden { + updateView() + } + } + } + var style: Style = .download { + didSet { + if oldValue != style { + updateView() + } + } + } + var state: State = .ready { + didSet { + if oldValue != state { + updateView() + delegate?.onStateChanged(state: state) + } + } + } + var downloadSize: UInt64 = 0 { + didSet { + downloadSizeLabel.text = formattedSize(downloadSize) + } + } + var downloadProgress: CGFloat = 0 { + didSet { + self.progress.progress = downloadProgress + } + } + weak var delegate: DownloadAllViewDelegate? + + @IBAction func onDownloadButtonPress(_ sender: Any) { + delegate?.onDownloadButtonPressed() + } + + private func updateView() { + let readyTitle: String + let downloadingTitle: String + let buttonTitle: String + + switch style { + case .download: + iconImageView.image = UIImage(named: "ic_download_all") + readyTitle = L("downloader_download_all_button") + downloadingTitle = L("downloader_loading_ios") + buttonTitle = L("download_button") + case .update: + iconImageView.image = UIImage(named: "ic_update_all") + readyTitle = L("downloader_update_maps") + downloadingTitle = L("downloader_updating_ios") + buttonTitle = L("downloader_update_all_button") + } + + titleCenterConstraint.priority = isSizeHidden ? .defaultHigh : .defaultLow + downloadSizeLabel.isHidden = isSizeHidden + + switch state { + case .ready: + title.text = readyTitle + downloadButton.setTitle(buttonTitle, for: .normal) + downloadButton.isHidden = false + stateWrapper.isHidden = true + progress.state = .spinner + downloadSizeLabel.isHidden = false + case .dowloading: + title.text = downloadingTitle + downloadButton.isHidden = true + stateWrapper.isHidden = false + progress.state = .spinner + case .none: + self.downloadButton.isHidden = true + self.stateWrapper.isHidden = true + } + } +} + +extension DownloadAllView: MWMCircularProgressProtocol { + func progressButtonPressed(_ progress: MWMCircularProgress) { + delegate?.onCancelButtonPressed() + } +} diff --git a/iphone/Maps/UI/Downloader/DownloadAllView/DownloadAllView.xib b/iphone/Maps/UI/Downloader/DownloadAllView/DownloadAllView.xib new file mode 100644 index 0000000000..99a4af018e --- /dev/null +++ b/iphone/Maps/UI/Downloader/DownloadAllView/DownloadAllView.xib @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iphone/Maps/UI/Downloader/DownloadMapsViewController.swift b/iphone/Maps/UI/Downloader/DownloadMapsViewController.swift index cb7358b777..4055afa0c8 100644 --- a/iphone/Maps/UI/Downloader/DownloadMapsViewController.swift +++ b/iphone/Maps/UI/Downloader/DownloadMapsViewController.swift @@ -20,13 +20,11 @@ class DownloadMapsViewController: MWMViewController { // MARK: - Outlets @IBOutlet var tableView: UITableView! - @IBOutlet var allMapsView: UIView! - @IBOutlet var allMapsButton: UIButton! - @IBOutlet var allMapsCancelButton: UIButton! @IBOutlet var searchBar: UISearchBar! @IBOutlet var statusBarBackground: UIView! @IBOutlet var noMapsContainer: UIView! @IBOutlet var searchBarTopOffset: NSLayoutConstraint! + @IBOutlet var downloadAllViewContainer: UIView! // MARK: - Properties @@ -34,7 +32,7 @@ class DownloadMapsViewController: MWMViewController { @objc var mode: MWMMapDownloaderMode = .downloaded private var skipCountryEvent = false private var hasAddMapSection: Bool { dataSource.isRoot && mode == .downloaded } - private let allMapsViewBottomOffsetConstant: CGFloat = 60 + private let allMapsViewBottomOffsetConstant: CGFloat = 64 lazy var noSerchResultViewController: SearchNoResultsViewController = { let vc = storyboard!.instantiateViewController(ofType: SearchNoResultsViewController.self) @@ -45,6 +43,13 @@ class DownloadMapsViewController: MWMViewController { vc.didMove(toParent: self) return vc }() + lazy var downloadAllView: DownloadAllView = { + let view = Bundle.main.load(viewClass: DownloadAllView.self)?.first as! DownloadAllView + view.delegate = self + downloadAllViewContainer.addSubview(view) + view.alignToSuperview() + return view + }() // MARK: - Methods @@ -80,6 +85,11 @@ class DownloadMapsViewController: MWMViewController { configButtons() } + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + configButtons() + } + fileprivate func showChildren(_ nodeAttrs: MapNodeAttributes) { let vc = storyboard!.instantiateViewController(ofType: DownloadMapsViewController.self) vc.mode = mode @@ -160,73 +170,45 @@ class DownloadMapsViewController: MWMViewController { } } - private func setAllMapsButton(_ state: AllMapsButtonState) { - switch state { - case .none: - allMapsView.isHidden = true - case .download(let buttonTitle): - allMapsView.isHidden = false - allMapsButton.isHidden = false - allMapsButton.setTitle(buttonTitle, for: .normal) - allMapsCancelButton.isHidden = true - case .cancel(let buttonTitle): - allMapsView.isHidden = false - allMapsButton.isHidden = true - allMapsCancelButton.isHidden = false - allMapsCancelButton.setTitle(buttonTitle, for: .normal) - } - if !allMapsView.isHidden { - tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: allMapsViewBottomOffsetConstant, right: 0) - } else { - tableView.contentInset = UIEdgeInsets.zero - } + fileprivate func reloadData() { + tableView.reloadData() + configButtons() } fileprivate func configButtons() { - allMapsView.isHidden = true - if mode == .available { + downloadAllView.state = .none + downloadAllView.isSizeHidden = false + let parentAttributes = dataSource.parentAttributes() + switch mode { + case .available: if dataSource.isRoot { - setAllMapsButton(.none) - } else { - let parentAttributes = dataSource.parentAttributes() - if parentAttributes.downloadingMwmCount > 0 { - setAllMapsButton(.cancel("\(L("downloader_cancel_all")) (\(formattedSize(parentAttributes.downloadingSize)))")) - } else if parentAttributes.downloadedMwmCount < parentAttributes.totalMwmCount { - setAllMapsButton(.download("\(L("downloader_download_all_button")) (\(formattedSize(parentAttributes.totalSize - parentAttributes.downloadedSize)))")) - } + break } - } else { - let updateInfo = Storage.shared().updateInfo(withParent: dataSource.parentAttributes().countryId) - if updateInfo.numberOfFiles > 0 { - setAllMapsButton(.download("\(L("downloader_update_all_button")) (\(formattedSize(updateInfo.updateSize)))")) - } else { - let parentAttributes = dataSource.parentAttributes() - if parentAttributes.downloadingMwmCount > 0 { - setAllMapsButton(.cancel(L("downloader_cancel_all"))) - } + if parentAttributes.downloadingMwmCount > 0 { + downloadAllView.state = .dowloading + downloadAllView.downloadSize = parentAttributes.downloadingSize + } else if parentAttributes.downloadedMwmCount < parentAttributes.totalMwmCount { + downloadAllView.state = .ready + downloadAllView.style = .download + downloadAllView.downloadSize = parentAttributes.totalSize - parentAttributes.downloadedSize } + case .downloaded: + if parentAttributes.downloadingMwmCount > 0 && dataSource is DownloadedMapsDataSource { + downloadAllView.state = .dowloading + if dataSource.isRoot { + downloadAllView.style = parentAttributes.totalUpdateSizeBytes > 0 ? .update : .download + downloadAllView.isSizeHidden = true + } + downloadAllView.downloadSize = parentAttributes.downloadingSize + } else if parentAttributes.totalUpdateSizeBytes > 0 { + downloadAllView.state = .ready + downloadAllView.style = .update + downloadAllView.downloadSize = parentAttributes.totalUpdateSizeBytes + } + @unknown default: + fatalError() } } - - @IBAction func onAllMaps(_ sender: UIButton) { - skipCountryEvent = true - if mode == .downloaded { - Storage.shared().updateNode(dataSource.parentAttributes().countryId) - } else { - Storage.shared().downloadNode(dataSource.parentAttributes().countryId) - } - skipCountryEvent = false - self.processCountryEvent(dataSource.parentAttributes().countryId) - } - - @IBAction func onCancelAllMaps(_ sender: UIButton) { - skipCountryEvent = true - Storage.shared().cancelDownloadNode(dataSource.parentAttributes().countryId) - Statistics.logEvent(kStatDownloaderDownloadCancel, withParameters: [kStatFrom: kStatMap]) - skipCountryEvent = false - self.processCountryEvent(dataSource.parentAttributes().countryId) - tableView.reloadData() - } } // MARK: - UITableViewDataSource @@ -395,7 +377,7 @@ extension DownloadMapsViewController: StorageObserver { return } dataSource.reload { - tableView.reloadData() + reloadData() noMapsContainer.isHidden = !dataSource.isEmpty || Storage.shared().downloadInProgress() } if countryId == dataSource.parentAttributes().countryId { @@ -416,6 +398,15 @@ extension DownloadMapsViewController: StorageObserver { if downloaderCell.nodeAttrs.countryId != countryId { continue } downloaderCell.setDownloadProgress(CGFloat(downloadedBytes) / CGFloat(totalBytes)) } + + let parentAttributes = dataSource.parentAttributes() + if countryId == parentAttributes.countryId { + downloadAllView.downloadProgress = CGFloat(downloadedBytes) / CGFloat(totalBytes) + downloadAllView.downloadSize = totalBytes + } else if dataSource.isRoot && dataSource is DownloadedMapsDataSource { + downloadAllView.state = .dowloading + downloadAllView.isSizeHidden = true + } } } @@ -442,7 +433,7 @@ extension DownloadMapsViewController: UISearchBarDelegate { searchBar.text = nil searchBar.resignFirstResponder() dataSource.cancelSearch() - tableView.reloadData() + reloadData() self.noSerchResultViewController.view.isHidden = true } @@ -450,7 +441,7 @@ extension DownloadMapsViewController: UISearchBarDelegate { let locale = searchBar.textInputMode?.primaryLanguage dataSource.search(searchText, locale: locale ?? "") { [weak self] (finished) in guard let self = self else { return } - self.tableView.reloadData() + self.reloadData() self.noSerchResultViewController.view.isHidden = !self.dataSource.isEmpty } } @@ -473,3 +464,37 @@ extension DownloadMapsViewController: MWMMapDownloaderButtonTableViewCellProtoco navigationController?.pushViewController(vc, animated: true) } } + +// MARK: - DownloadAllViewDelegate + +extension DownloadMapsViewController: DownloadAllViewDelegate { + func onStateChanged(state: DownloadAllView.State) { + if state == .none { + downloadAllViewContainer.isHidden = true + tableView.contentInset = UIEdgeInsets.zero + } else { + downloadAllViewContainer.isHidden = false + tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: allMapsViewBottomOffsetConstant, right: 0) + } + } + + func onDownloadButtonPressed() { + skipCountryEvent = true + if mode == .downloaded { + Storage.shared().updateNode(dataSource.parentAttributes().countryId) + } else { + Storage.shared().downloadNode(dataSource.parentAttributes().countryId) + } + skipCountryEvent = false + self.processCountryEvent(dataSource.parentAttributes().countryId) + } + + func onCancelButtonPressed() { + skipCountryEvent = true + Storage.shared().cancelDownloadNode(dataSource.parentAttributes().countryId) + Statistics.logEvent(kStatDownloaderDownloadCancel, withParameters: [kStatFrom: kStatMap]) + skipCountryEvent = false + self.processCountryEvent(dataSource.parentAttributes().countryId) + reloadData() + } +} diff --git a/iphone/Maps/UI/Storyboard/Main.storyboard b/iphone/Maps/UI/Storyboard/Main.storyboard index 91d89f7ddd..78110e9531 100644 --- a/iphone/Maps/UI/Storyboard/Main.storyboard +++ b/iphone/Maps/UI/Storyboard/Main.storyboard @@ -824,71 +824,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -916,6 +851,16 @@ + + + + + + + + + + @@ -924,19 +869,18 @@ - + - - + - + @@ -945,9 +889,7 @@ - - - + @@ -957,7 +899,7 @@ - +