diff --git a/Localization/app.json b/Localization/app.json index b85f6732..45c77123 100644 --- a/Localization/app.json +++ b/Localization/app.json @@ -60,7 +60,10 @@ } }, "timeline": { - "load_more": "Load More" + "loader": { + "load_missing_posts": "Load missing posts", + "loading_missing_posts": "Loading missing posts..." + } } }, "countable": { diff --git a/Mastodon/Diffiable/Section/StatusSection.swift b/Mastodon/Diffiable/Section/StatusSection.swift index e0620b10..bc95e2a2 100644 --- a/Mastodon/Diffiable/Section/StatusSection.swift +++ b/Mastodon/Diffiable/Section/StatusSection.swift @@ -77,7 +77,7 @@ extension StatusSection { return cell case .bottomLoader: let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self), for: indexPath) as! TimelineBottomLoaderTableViewCell - cell.activityIndicatorView.startAnimating() + cell.startAnimating() return cell } } diff --git a/Mastodon/Generated/Assets.swift b/Mastodon/Generated/Assets.swift index cbfdfd10..1aabf5f3 100644 --- a/Mastodon/Generated/Assets.swift +++ b/Mastodon/Generated/Assets.swift @@ -22,9 +22,6 @@ internal typealias AssetImageTypeAlias = ImageAsset.Image // swiftlint:disable identifier_name line_length nesting type_body_length type_name internal enum Asset { internal static let accentColor = ColorAsset(name: "AccentColor") - internal enum Arrows { - internal static let arrowTriangle2Circlepath = ImageAsset(name: "Arrows/arrow.triangle.2.circlepath") - } internal enum Asset { internal static let mastodonTextLogo = ImageAsset(name: "Asset/mastodon.text.logo") } diff --git a/Mastodon/Generated/Strings.swift b/Mastodon/Generated/Strings.swift index 63259503..7079b297 100644 --- a/Mastodon/Generated/Strings.swift +++ b/Mastodon/Generated/Strings.swift @@ -120,8 +120,12 @@ internal enum L10n { } } internal enum Timeline { - /// Load More - internal static let loadMore = L10n.tr("Localizable", "Common.Controls.Timeline.LoadMore") + internal enum Loader { + /// Loading missing posts... + internal static let loadingMissingPosts = L10n.tr("Localizable", "Common.Controls.Timeline.Loader.LoadingMissingPosts") + /// Load missing posts + internal static let loadMissingPosts = L10n.tr("Localizable", "Common.Controls.Timeline.Loader.LoadMissingPosts") + } } } internal enum Countable { diff --git a/Mastodon/Resources/Assets.xcassets/Arrows/Contents.json b/Mastodon/Resources/Assets.xcassets/Arrows/Contents.json deleted file mode 100644 index 6e965652..00000000 --- a/Mastodon/Resources/Assets.xcassets/Arrows/Contents.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "provides-namespace" : true - } -} diff --git a/Mastodon/Resources/Assets.xcassets/Arrows/arrow.triangle.2.circlepath.imageset/Contents.json b/Mastodon/Resources/Assets.xcassets/Arrows/arrow.triangle.2.circlepath.imageset/Contents.json deleted file mode 100644 index c59347e9..00000000 --- a/Mastodon/Resources/Assets.xcassets/Arrows/arrow.triangle.2.circlepath.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images" : [ - { - "filename" : "arrow.triangle.2.circlepath.pdf", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Mastodon/Resources/Assets.xcassets/Arrows/arrow.triangle.2.circlepath.imageset/arrow.triangle.2.circlepath.pdf b/Mastodon/Resources/Assets.xcassets/Arrows/arrow.triangle.2.circlepath.imageset/arrow.triangle.2.circlepath.pdf deleted file mode 100644 index b864ab38..00000000 --- a/Mastodon/Resources/Assets.xcassets/Arrows/arrow.triangle.2.circlepath.imageset/arrow.triangle.2.circlepath.pdf +++ /dev/null @@ -1,193 +0,0 @@ -%PDF-1.7 - -1 0 obj - << >> -endobj - -2 0 obj - << /Length 3 0 R >> -stream -/DeviceRGB CS -/DeviceRGB cs -q -1.000000 0.000000 -0.000000 1.000000 4.000000 10.752930 cm -0.000000 0.000000 0.000000 scn -15.009519 2.109471 m -15.085540 1.562444 15.590621 1.180617 16.137648 1.256639 c -16.684677 1.332660 17.066502 1.837741 16.990480 2.384768 c -15.009519 2.109471 l -h --0.423099 4.631682 m --0.635487 4.121869 -0.394376 3.536408 0.115438 3.324021 c -0.625251 3.111633 1.210711 3.352744 1.423099 3.862558 c --0.423099 4.631682 l -h -1.000000 8.247120 m -1.000000 8.799404 0.552285 9.247120 0.000000 9.247120 c --0.552285 9.247120 -1.000000 8.799404 -1.000000 8.247120 c -1.000000 8.247120 l -h -0.000000 4.247120 m --1.000000 4.247120 l --1.000000 3.694835 -0.552285 3.247120 0.000000 3.247120 c -0.000000 4.247120 l -h -4.000000 3.247120 m -4.552285 3.247120 5.000000 3.694835 5.000000 4.247120 c -5.000000 4.799405 4.552285 5.247120 4.000000 5.247120 c -4.000000 3.247120 l -h -16.990480 2.384768 m -16.715729 4.361807 15.798570 6.193669 14.380284 7.598174 c -12.972991 6.177073 l -14.079566 5.081251 14.795152 3.651996 15.009519 2.109471 c -16.990480 2.384768 l -h -14.380284 7.598174 m -12.961998 9.002679 11.121269 9.901910 9.141643 10.157345 c -8.885699 8.173789 l -10.430243 7.974494 11.866417 7.272897 12.972991 6.177073 c -14.380284 7.598174 l -h -9.141643 10.157345 m -7.162015 10.412781 5.153316 10.010252 3.424967 9.011765 c -4.425436 7.279984 l -5.773929 8.059025 7.341156 8.373085 8.885699 8.173789 c -9.141643 10.157345 l -h -3.424967 9.011765 m -1.696617 8.013276 0.344502 6.474223 -0.423099 4.631682 c -1.423099 3.862558 l -2.021996 5.300145 3.076944 6.500945 4.425436 7.279984 c -3.424967 9.011765 l -h --1.000000 8.247120 m --1.000000 4.247120 l -1.000000 4.247120 l -1.000000 8.247120 l --1.000000 8.247120 l -h -0.000000 3.247120 m -4.000000 3.247120 l -4.000000 5.247120 l -0.000000 5.247120 l -0.000000 3.247120 l -h -f -n -Q -q -1.000000 0.000000 -0.000000 1.000000 4.000000 1.767822 cm -0.000000 0.000000 0.000000 scn -0.990481 9.369826 m -0.914460 9.916854 0.409379 10.298680 -0.137649 10.222659 c --0.684676 10.146638 -1.066502 9.641557 -0.990481 9.094529 c -0.990481 9.369826 l -h -16.423100 6.847616 m -16.635487 7.357429 16.394375 7.942889 15.884562 8.155277 c -15.374748 8.367664 14.789289 8.126554 14.576900 7.616740 c -16.423100 6.847616 l -h -15.000000 3.232178 m -15.000000 2.679893 15.447715 2.232178 16.000000 2.232178 c -16.552284 2.232178 17.000000 2.679893 17.000000 3.232178 c -15.000000 3.232178 l -h -16.000000 7.232178 m -17.000000 7.232178 l -17.000000 7.784462 16.552284 8.232178 16.000000 8.232178 c -16.000000 7.232178 l -h -12.000000 8.232178 m -11.447715 8.232178 11.000000 7.784462 11.000000 7.232178 c -11.000000 6.679893 11.447715 6.232178 12.000000 6.232178 c -12.000000 8.232178 l -h --0.990481 9.094529 m --0.715729 7.117491 0.201429 5.285628 1.619715 3.881123 c -3.027008 5.302223 l -1.920433 6.398046 1.204848 7.827302 0.990481 9.369826 c --0.990481 9.094529 l -h -1.619715 3.881123 m -3.038001 2.476617 4.878731 1.577388 6.858358 1.321952 c -7.114300 3.305508 l -5.569757 3.504804 4.133582 4.206400 3.027008 5.302223 c -1.619715 3.881123 l -h -6.858358 1.321952 m -8.837985 1.066517 10.846684 1.469046 12.575033 2.467534 c -11.574564 4.199314 l -10.226071 3.420273 8.658844 3.106212 7.114300 3.305508 c -6.858358 1.321952 l -h -12.575033 2.467534 m -14.303383 3.466022 15.655499 5.005074 16.423100 6.847616 c -14.576900 7.616740 l -13.978004 6.179152 12.923057 4.978354 11.574564 4.199314 c -12.575033 2.467534 l -h -17.000000 3.232178 m -17.000000 7.232178 l -15.000000 7.232178 l -15.000000 3.232178 l -17.000000 3.232178 l -h -16.000000 8.232178 m -12.000000 8.232178 l -12.000000 6.232178 l -16.000000 6.232178 l -16.000000 8.232178 l -h -f -n -Q - -endstream -endobj - -3 0 obj - 3597 -endobj - -4 0 obj - << /Annots [] - /Type /Page - /MediaBox [ 0.000000 0.000000 24.000000 24.000000 ] - /Resources 1 0 R - /Contents 2 0 R - /Parent 5 0 R - >> -endobj - -5 0 obj - << /Kids [ 4 0 R ] - /Count 1 - /Type /Pages - >> -endobj - -6 0 obj - << /Type /Catalog - /Pages 5 0 R - >> -endobj - -xref -0 7 -0000000000 65535 f -0000000010 00000 n -0000000034 00000 n -0000003687 00000 n -0000003710 00000 n -0000003883 00000 n -0000003957 00000 n -trailer -<< /ID [ (some) (id) ] - /Root 6 0 R - /Size 7 ->> -startxref -4016 -%%EOF \ No newline at end of file diff --git a/Mastodon/Resources/en.lproj/Localizable.strings b/Mastodon/Resources/en.lproj/Localizable.strings index 3515da67..92e0161a 100644 --- a/Mastodon/Resources/en.lproj/Localizable.strings +++ b/Mastodon/Resources/en.lproj/Localizable.strings @@ -34,7 +34,8 @@ "Common.Controls.Status.ShowPost" = "Show Post"; "Common.Controls.Status.StatusContentWarning" = "content warning"; "Common.Controls.Status.UserReblogged" = "%@ reblogged"; -"Common.Controls.Timeline.LoadMore" = "Load More"; +"Common.Controls.Timeline.Loader.LoadMissingPosts" = "Load missing posts"; +"Common.Controls.Timeline.Loader.LoadingMissingPosts" = "Loading missing posts..."; "Common.Countable.Photo.Multiple" = "photos"; "Common.Countable.Photo.Single" = "photo"; "Scene.Compose.ComposeAction" = "Publish"; diff --git a/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift b/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift index 2dd7a3ad..a1841053 100644 --- a/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift +++ b/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift @@ -268,15 +268,13 @@ extension HomeTimelineViewController: TimelineMiddleLoaderTableViewCellDelegate // make success state same as loading due to snapshot updating delay let isLoading = state is HomeTimelineViewModel.LoadMiddleState.Loading || state is HomeTimelineViewModel.LoadMiddleState.Success - cell.loadMoreButton.isHidden = isLoading if isLoading { - cell.activityIndicatorView.startAnimating() + cell.startAnimating() } else { - cell.activityIndicatorView.stopAnimating() + cell.stopAnimating() } } else { - cell.loadMoreButton.isHidden = false - cell.activityIndicatorView.stopAnimating() + cell.stopAnimating() } } .store(in: &cell.disposeBag) diff --git a/Mastodon/Scene/PublicTimeline/PublicTimelineViewController.swift b/Mastodon/Scene/PublicTimeline/PublicTimelineViewController.swift index 1fc0978e..7b3732dc 100644 --- a/Mastodon/Scene/PublicTimeline/PublicTimelineViewController.swift +++ b/Mastodon/Scene/PublicTimeline/PublicTimelineViewController.swift @@ -165,15 +165,13 @@ extension PublicTimelineViewController: TimelineMiddleLoaderTableViewCellDelegat // make success state same as loading due to snapshot updating delay let isLoading = state is PublicTimelineViewModel.LoadMiddleState.Loading || state is PublicTimelineViewModel.LoadMiddleState.Success - cell.loadMoreButton.isHidden = isLoading if isLoading { - cell.activityIndicatorView.startAnimating() + cell.startAnimating() } else { - cell.activityIndicatorView.stopAnimating() + cell.stopAnimating() } } else { - cell.loadMoreButton.isHidden = false - cell.activityIndicatorView.stopAnimating() + cell.stopAnimating() } } .store(in: &cell.disposeBag) diff --git a/Mastodon/Scene/Share/View/TableviewCell/TimelineBottomLoaderTableViewCell.swift b/Mastodon/Scene/Share/View/TableviewCell/TimelineBottomLoaderTableViewCell.swift index 7fe4c0a7..0f5fe67c 100644 --- a/Mastodon/Scene/Share/View/TableviewCell/TimelineBottomLoaderTableViewCell.swift +++ b/Mastodon/Scene/Share/View/TableviewCell/TimelineBottomLoaderTableViewCell.swift @@ -11,10 +11,7 @@ import Combine final class TimelineBottomLoaderTableViewCell: TimelineLoaderTableViewCell { override func _init() { super._init() - backgroundColor = .clear - - activityIndicatorView.isHidden = false - activityIndicatorView.startAnimating() + startAnimating() } } diff --git a/Mastodon/Scene/Share/View/TableviewCell/TimelineLoaderTableViewCell.swift b/Mastodon/Scene/Share/View/TableviewCell/TimelineLoaderTableViewCell.swift index 6aa19524..19e1dd4e 100644 --- a/Mastodon/Scene/Share/View/TableviewCell/TimelineLoaderTableViewCell.swift +++ b/Mastodon/Scene/Share/View/TableviewCell/TimelineLoaderTableViewCell.swift @@ -10,22 +10,30 @@ import Combine class TimelineLoaderTableViewCell: UITableViewCell { - static let cellHeight: CGFloat = 44 + TimelineLoaderTableViewCell.extraTopPadding + TimelineLoaderTableViewCell.bottomPadding - static let extraTopPadding: CGFloat = 0 // the status cell already has 10pt bottom padding - static let bottomPadding: CGFloat = StatusTableViewCell.bottomPaddingHeight + TimelineLoaderTableViewCell.extraTopPadding // make balance + static let buttonHeight: CGFloat = 62 + static let cellHeight: CGFloat = TimelineLoaderTableViewCell.buttonHeight + 17 + static let extraTopPadding: CGFloat = 10 + var disposeBag = Set() + var stateBindDispose: AnyCancellable? + let loadMoreButton: UIButton = { let button = UIButton(type: .system) - button.titleLabel?.font = .preferredFont(forTextStyle: .headline) - button.setTitle(L10n.Common.Controls.Timeline.loadMore, for: .normal) + button.backgroundColor = Asset.Colors.lightWhite.color return button }() - let activityIndicatorView: UIActivityIndicatorView = { + private let loadMoreLabel: UILabel = { + let label = UILabel() + label.font = .preferredFont(forTextStyle: .body) + return label + }() + + private let activityIndicatorView: UIActivityIndicatorView = { let activityIndicatorView = UIActivityIndicatorView(style: .medium) - activityIndicatorView.tintColor = .white + activityIndicatorView.tintColor = Asset.Colors.lightSecondaryText.color activityIndicatorView.hidesWhenStopped = true return activityIndicatorView }() @@ -44,6 +52,17 @@ class TimelineLoaderTableViewCell: UITableViewCell { super.init(coder: coder) _init() } + func startAnimating() { + activityIndicatorView.startAnimating() + self.loadMoreLabel.textColor = Asset.Colors.lightSecondaryText.color + self.loadMoreLabel.text = L10n.Common.Controls.Timeline.Loader.loadingMissingPosts + } + + func stopAnimating() { + activityIndicatorView.stopAnimating() + self.loadMoreLabel.textColor = Asset.Colors.buttonDefault.color + self.loadMoreLabel.text = L10n.Common.Controls.Timeline.Loader.loadMissingPosts + } func _init() { selectionStyle = .none @@ -52,21 +71,27 @@ class TimelineLoaderTableViewCell: UITableViewCell { loadMoreButton.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(loadMoreButton) NSLayoutConstraint.activate([ - loadMoreButton.topAnchor.constraint(equalTo: contentView.topAnchor, constant: TimelineLoaderTableViewCell.extraTopPadding), - loadMoreButton.leadingAnchor.constraint(equalTo: contentView.readableContentGuide.leadingAnchor), - contentView.readableContentGuide.trailingAnchor.constraint(equalTo: loadMoreButton.trailingAnchor), - contentView.bottomAnchor.constraint(equalTo: loadMoreButton.bottomAnchor, constant: TimelineLoaderTableViewCell.bottomPadding), - loadMoreButton.heightAnchor.constraint(equalToConstant: 44).priority(.defaultHigh), + loadMoreButton.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 7), + loadMoreButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), + contentView.trailingAnchor.constraint(equalTo: loadMoreButton.trailingAnchor), + contentView.bottomAnchor.constraint(equalTo: loadMoreButton.bottomAnchor, constant: 14), + loadMoreButton.heightAnchor.constraint(equalToConstant: TimelineLoaderTableViewCell.buttonHeight).priority(.defaultHigh), + ]) + + loadMoreLabel.translatesAutoresizingMaskIntoConstraints = false + addSubview(loadMoreLabel) + NSLayoutConstraint.activate([ + loadMoreLabel.centerXAnchor.constraint(equalTo: loadMoreButton.centerXAnchor), + loadMoreLabel.centerYAnchor.constraint(equalTo: loadMoreButton.centerYAnchor), ]) activityIndicatorView.translatesAutoresizingMaskIntoConstraints = false addSubview(activityIndicatorView) NSLayoutConstraint.activate([ - activityIndicatorView.centerXAnchor.constraint(equalTo: loadMoreButton.centerXAnchor), activityIndicatorView.centerYAnchor.constraint(equalTo: loadMoreButton.centerYAnchor), + activityIndicatorView.trailingAnchor.constraint(equalTo: loadMoreLabel.leadingAnchor), ]) - loadMoreButton.isHidden = true activityIndicatorView.isHidden = true } diff --git a/Mastodon/Scene/Share/View/TableviewCell/TimelineMiddleLoaderTableViewCell.swift b/Mastodon/Scene/Share/View/TableviewCell/TimelineMiddleLoaderTableViewCell.swift index 16ab241f..952def9b 100644 --- a/Mastodon/Scene/Share/View/TableviewCell/TimelineMiddleLoaderTableViewCell.swift +++ b/Mastodon/Scene/Share/View/TableviewCell/TimelineMiddleLoaderTableViewCell.swift @@ -21,10 +21,6 @@ final class TimelineMiddleLoaderTableViewCell: TimelineLoaderTableViewCell { override func _init() { super._init() - backgroundColor = .clear - - loadMoreButton.isHidden = false - loadMoreButton.setImage(Asset.Arrows.arrowTriangle2Circlepath.image.withRenderingMode(.alwaysTemplate), for: .normal) loadMoreButton.setInsets(forContentPadding: .zero, imageTitlePadding: 4) loadMoreButton.addTarget(self, action: #selector(TimelineMiddleLoaderTableViewCell.loadMoreButtonDidPressed(_:)), for: .touchUpInside) }