diff --git a/Riot/Modules/Room/EditHistory/EditHistoryViewController.storyboard b/Riot/Modules/Room/EditHistory/EditHistoryViewController.storyboard index 7a2d5f148..059dae309 100644 --- a/Riot/Modules/Room/EditHistory/EditHistoryViewController.storyboard +++ b/Riot/Modules/Room/EditHistory/EditHistoryViewController.storyboard @@ -18,70 +18,26 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - - + + + + - - - + diff --git a/Riot/Modules/Room/EditHistory/EditHistoryViewController.swift b/Riot/Modules/Room/EditHistory/EditHistoryViewController.swift index 59ae30e10..88c254182 100644 --- a/Riot/Modules/Room/EditHistory/EditHistoryViewController.swift +++ b/Riot/Modules/Room/EditHistory/EditHistoryViewController.swift @@ -17,31 +17,47 @@ */ import UIKit +import Reusable final class EditHistoryViewController: UIViewController { // MARK: - Constants private enum Constants { - static let aConstant: Int = 666 + static let estimatedRowHeight: CGFloat = 38.0 + static let estimatedSectionHeaderHeight: CGFloat = 28.0 + static let editHistoryMessageTimeFormat = "HH:mm" } // MARK: - Properties // MARK: Outlets - - @IBOutlet private weak var scrollView: UIScrollView! - @IBOutlet private weak var messageLabel: UILabel! - @IBOutlet private weak var loadMoreButton: UIButton! + @IBOutlet private weak var tableView: UITableView! // MARK: Private private var viewModel: EditHistoryViewModelType! private var theme: Theme! - private var keyboardAvoider: KeyboardAvoider? private var errorPresenter: MXKErrorPresentation! - private var activityPresenter: ActivityIndicatorPresenter! + private var activityIndicatorPresenter: ActivityIndicatorPresenter! + + private var editHistorySections: [EditHistorySection] = [] + + private lazy var sectionDateFormatter: DateFormatter = { + let dateFormatter = DateFormatter() + dateFormatter.dateStyle = .full + dateFormatter.timeStyle = .none + dateFormatter.doesRelativeDateFormatting = true + return dateFormatter + }() + + private lazy var messageDateFormatter: DateFormatter = { + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = Constants.editHistoryMessageTimeFormat + dateFormatter.locale = Locale(identifier: "en_US_POSIX") + return dateFormatter + }() // MARK: - Setup @@ -59,11 +75,10 @@ final class EditHistoryViewController: UIViewController { // Do any additional setup after loading the view. - self.title = "Edits history" + self.title = VectorL10n.roomMessageEditsHistoryTitle self.setupViews() - self.keyboardAvoider = KeyboardAvoider(scrollViewContainerView: self.view, scrollView: self.scrollView) - self.activityPresenter = ActivityIndicatorPresenter() + self.activityIndicatorPresenter = ActivityIndicatorPresenter() self.errorPresenter = MXKErrorAlertPresentation() self.registerThemeServiceDidChangeThemeNotification() @@ -73,18 +88,6 @@ final class EditHistoryViewController: UIViewController { self.viewModel.process(viewAction: .loadMore) } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - - self.keyboardAvoider?.startAvoiding() - } - - override func viewDidDisappear(_ animated: Bool) { - super.viewDidDisappear(animated) - - self.keyboardAvoider?.stopAvoiding() - } override var preferredStatusBarStyle: UIStatusBarStyle { return self.theme.statusBarStyle @@ -95,18 +98,12 @@ final class EditHistoryViewController: UIViewController { private func update(theme: Theme) { self.theme = theme - self.view.backgroundColor = theme.headerBackgroundColor + self.view.backgroundColor = theme.backgroundColor + self.tableView.backgroundColor = theme.backgroundColor if let navigationBar = self.navigationController?.navigationBar { theme.applyStyle(onNavigationBar: navigationBar) } - - - // TODO: - self.messageLabel.textColor = theme.textPrimaryColor - - self.loadMoreButton.backgroundColor = theme.backgroundColor - theme.applyStyle(onButton: self.loadMoreButton) } private func registerThemeServiceDidChangeThemeNotification() { @@ -118,74 +115,109 @@ final class EditHistoryViewController: UIViewController { } private func setupViews() { - let closeBarButtonItem = MXKBarButtonItem(title: "Close", style: .plain) { [weak self] in + let closeBarButtonItem = MXKBarButtonItem(title: VectorL10n.close, style: .plain) { [weak self] in self?.closeButtonAction() } self.navigationItem.rightBarButtonItem = closeBarButtonItem - self.scrollView.keyboardDismissMode = .interactive + self.setupTableView() + } + + private func setupTableView() { + self.tableView.rowHeight = UITableView.automaticDimension + self.tableView.estimatedRowHeight = Constants.estimatedRowHeight + self.tableView.register(cellType: EditHistoryCell.self) - self.messageLabel.text = "VectorL10n.editHistoryTitle" - self.messageLabel.isHidden = true + self.tableView.sectionHeaderHeight = UITableView.automaticDimension + self.tableView.estimatedSectionHeaderHeight = Constants.estimatedSectionHeaderHeight + self.tableView.register(headerFooterViewType: EditHistoryHeaderView.self) + + self.tableView.tableFooterView = UIView() } private func render(viewState: EditHistoryViewState) { switch viewState { case .loading: self.renderLoading() - case .loaded(let messages, let addedCount): - self.renderLoaded(messages: messages, addedCount: addedCount) - case .allLoaded: - self.renderAllLoaded() + case .loaded(let sections, let addedCount, let allDataLoaded): + self.renderLoaded(sections: sections, addedCount: addedCount, allDataLoaded: allDataLoaded) case .error(let error): - self.render(error: error) + self.render(error: error) } } private func renderLoading() { - self.activityPresenter.presentActivityIndicator(on: self.view, animated: true) + self.activityIndicatorPresenter.presentActivityIndicator(on: self.view, animated: true) } - private func renderLoaded(messages: [EditHistoryMessage], addedCount: Int) { - self.activityPresenter.removeCurrentActivityIndicator(animated: true) - - let calendar = Calendar.current - - let attributedText = NSMutableAttributedString() - for message in messages { - let time=calendar.dateComponents([.hour, .minute], from: message.date) - attributedText.append(NSAttributedString(string: "\(time.hour!):\(time.minute!)")) - attributedText.append(NSAttributedString(string: " - ")) - attributedText.append(message.message) - attributedText.append(NSAttributedString(string: "\n")) - } - - self.messageLabel.attributedText = attributedText - self.messageLabel.isHidden = false - } - - private func renderAllLoaded() { - self.loadMoreButton.isHidden = true + private func renderLoaded(sections: [EditHistorySection], addedCount: Int, allDataLoaded: Bool) { + self.activityIndicatorPresenter.removeCurrentActivityIndicator(animated: true) + self.editHistorySections = sections + self.tableView.reloadData() } private func render(error: Error) { - self.activityPresenter.removeCurrentActivityIndicator(animated: true) + self.activityIndicatorPresenter.removeCurrentActivityIndicator(animated: true) self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: nil) } - // MARK: - Actions - @IBAction private func loadMoreButtonAction(_ sender: Any) { - self.viewModel.process(viewAction: .loadMore) - } - private func closeButtonAction() { self.viewModel.process(viewAction: .close) } } +// MARK: - UITableViewDataSource +extension EditHistoryViewController: UITableViewDataSource { + + func numberOfSections(in tableView: UITableView) -> Int { + return self.editHistorySections.count + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return self.editHistorySections[section].messages.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let editHistoryCell = tableView.dequeueReusableCell(for: indexPath, cellType: EditHistoryCell.self) + + let editHistoryMessage = self.editHistorySections[indexPath.section].messages[indexPath.row] + + let timeString = self.messageDateFormatter.string(from: editHistoryMessage.date) + + editHistoryCell.update(theme: self.theme) + editHistoryCell.fill(with: timeString, and: editHistoryMessage.message) + + return editHistoryCell + } + + func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + guard let editHistoryHeaderView: EditHistoryHeaderView = tableView.dequeueReusableHeaderFooterView() else { + return nil + } + let editHistorySection = self.editHistorySections[section] + let dateString = self.sectionDateFormatter.string(from: editHistorySection.date) + + editHistoryHeaderView.update(theme: self.theme) + editHistoryHeaderView.fill(with: dateString) + return editHistoryHeaderView + } +} + +// MARK: - UITableViewDelegate +extension EditHistoryViewController: UITableViewDelegate { + + func scrollViewDidScroll(_ scrollView: UIScrollView) { + + // Check if a scroll beyond scroll view content occurs + let distanceFromBottom = scrollView.contentSize.height - scrollView.contentOffset.y + if distanceFromBottom < scrollView.frame.size.height { + self.viewModel.process(viewAction: .loadMore) + } + } +} // MARK: - EditHistoryViewModelViewDelegate extension EditHistoryViewController: EditHistoryViewModelViewDelegate {