feature: Update timeline gap appearance

This commit is contained in:
sunxiaojian 2021-03-16 19:28:52 +08:00
parent c8bcfd1526
commit 8fc39edd85
13 changed files with 59 additions and 254 deletions

View File

@ -60,7 +60,10 @@
} }
}, },
"timeline": { "timeline": {
"load_more": "Load More" "loader": {
"load_missing_posts": "Load missing posts",
"loading_missing_posts": "Loading missing posts..."
}
} }
}, },
"countable": { "countable": {

View File

@ -77,7 +77,7 @@ extension StatusSection {
return cell return cell
case .bottomLoader: case .bottomLoader:
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self), for: indexPath) as! TimelineBottomLoaderTableViewCell let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self), for: indexPath) as! TimelineBottomLoaderTableViewCell
cell.activityIndicatorView.startAnimating() cell.startAnimating()
return cell return cell
} }
} }

View File

@ -22,9 +22,6 @@ internal typealias AssetImageTypeAlias = ImageAsset.Image
// swiftlint:disable identifier_name line_length nesting type_body_length type_name // swiftlint:disable identifier_name line_length nesting type_body_length type_name
internal enum Asset { internal enum Asset {
internal static let accentColor = ColorAsset(name: "AccentColor") 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 enum Asset {
internal static let mastodonTextLogo = ImageAsset(name: "Asset/mastodon.text.logo") internal static let mastodonTextLogo = ImageAsset(name: "Asset/mastodon.text.logo")
} }

View File

@ -120,8 +120,12 @@ internal enum L10n {
} }
} }
internal enum Timeline { internal enum Timeline {
/// Load More internal enum Loader {
internal static let loadMore = L10n.tr("Localizable", "Common.Controls.Timeline.LoadMore") /// 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 { internal enum Countable {

View File

@ -1,9 +0,0 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"provides-namespace" : true
}
}

View File

@ -1,12 +0,0 @@
{
"images" : [
{
"filename" : "arrow.triangle.2.circlepath.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -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

View File

@ -34,7 +34,8 @@
"Common.Controls.Status.ShowPost" = "Show Post"; "Common.Controls.Status.ShowPost" = "Show Post";
"Common.Controls.Status.StatusContentWarning" = "content warning"; "Common.Controls.Status.StatusContentWarning" = "content warning";
"Common.Controls.Status.UserReblogged" = "%@ reblogged"; "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.Multiple" = "photos";
"Common.Countable.Photo.Single" = "photo"; "Common.Countable.Photo.Single" = "photo";
"Scene.Compose.ComposeAction" = "Publish"; "Scene.Compose.ComposeAction" = "Publish";

View File

@ -268,15 +268,13 @@ extension HomeTimelineViewController: TimelineMiddleLoaderTableViewCellDelegate
// make success state same as loading due to snapshot updating delay // make success state same as loading due to snapshot updating delay
let isLoading = state is HomeTimelineViewModel.LoadMiddleState.Loading || state is HomeTimelineViewModel.LoadMiddleState.Success let isLoading = state is HomeTimelineViewModel.LoadMiddleState.Loading || state is HomeTimelineViewModel.LoadMiddleState.Success
cell.loadMoreButton.isHidden = isLoading
if isLoading { if isLoading {
cell.activityIndicatorView.startAnimating() cell.startAnimating()
} else { } else {
cell.activityIndicatorView.stopAnimating() cell.stopAnimating()
} }
} else { } else {
cell.loadMoreButton.isHidden = false cell.stopAnimating()
cell.activityIndicatorView.stopAnimating()
} }
} }
.store(in: &cell.disposeBag) .store(in: &cell.disposeBag)

View File

@ -165,15 +165,13 @@ extension PublicTimelineViewController: TimelineMiddleLoaderTableViewCellDelegat
// make success state same as loading due to snapshot updating delay // make success state same as loading due to snapshot updating delay
let isLoading = state is PublicTimelineViewModel.LoadMiddleState.Loading || state is PublicTimelineViewModel.LoadMiddleState.Success let isLoading = state is PublicTimelineViewModel.LoadMiddleState.Loading || state is PublicTimelineViewModel.LoadMiddleState.Success
cell.loadMoreButton.isHidden = isLoading
if isLoading { if isLoading {
cell.activityIndicatorView.startAnimating() cell.startAnimating()
} else { } else {
cell.activityIndicatorView.stopAnimating() cell.stopAnimating()
} }
} else { } else {
cell.loadMoreButton.isHidden = false cell.stopAnimating()
cell.activityIndicatorView.stopAnimating()
} }
} }
.store(in: &cell.disposeBag) .store(in: &cell.disposeBag)

View File

@ -11,10 +11,7 @@ import Combine
final class TimelineBottomLoaderTableViewCell: TimelineLoaderTableViewCell { final class TimelineBottomLoaderTableViewCell: TimelineLoaderTableViewCell {
override func _init() { override func _init() {
super._init() super._init()
backgroundColor = .clear startAnimating()
activityIndicatorView.isHidden = false
activityIndicatorView.startAnimating()
} }
} }

View File

@ -10,22 +10,30 @@ import Combine
class TimelineLoaderTableViewCell: UITableViewCell { class TimelineLoaderTableViewCell: UITableViewCell {
static let cellHeight: CGFloat = 44 + TimelineLoaderTableViewCell.extraTopPadding + TimelineLoaderTableViewCell.bottomPadding static let buttonHeight: CGFloat = 62
static let extraTopPadding: CGFloat = 0 // the status cell already has 10pt bottom padding static let cellHeight: CGFloat = TimelineLoaderTableViewCell.buttonHeight + 17
static let bottomPadding: CGFloat = StatusTableViewCell.bottomPaddingHeight + TimelineLoaderTableViewCell.extraTopPadding // make balance static let extraTopPadding: CGFloat = 10
var disposeBag = Set<AnyCancellable>() var disposeBag = Set<AnyCancellable>()
var stateBindDispose: AnyCancellable?
let loadMoreButton: UIButton = { let loadMoreButton: UIButton = {
let button = UIButton(type: .system) let button = UIButton(type: .system)
button.titleLabel?.font = .preferredFont(forTextStyle: .headline) button.backgroundColor = Asset.Colors.lightWhite.color
button.setTitle(L10n.Common.Controls.Timeline.loadMore, for: .normal)
return button 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) let activityIndicatorView = UIActivityIndicatorView(style: .medium)
activityIndicatorView.tintColor = .white activityIndicatorView.tintColor = Asset.Colors.lightSecondaryText.color
activityIndicatorView.hidesWhenStopped = true activityIndicatorView.hidesWhenStopped = true
return activityIndicatorView return activityIndicatorView
}() }()
@ -44,6 +52,17 @@ class TimelineLoaderTableViewCell: UITableViewCell {
super.init(coder: coder) super.init(coder: coder)
_init() _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() { func _init() {
selectionStyle = .none selectionStyle = .none
@ -52,21 +71,27 @@ class TimelineLoaderTableViewCell: UITableViewCell {
loadMoreButton.translatesAutoresizingMaskIntoConstraints = false loadMoreButton.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(loadMoreButton) contentView.addSubview(loadMoreButton)
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
loadMoreButton.topAnchor.constraint(equalTo: contentView.topAnchor, constant: TimelineLoaderTableViewCell.extraTopPadding), loadMoreButton.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 7),
loadMoreButton.leadingAnchor.constraint(equalTo: contentView.readableContentGuide.leadingAnchor), loadMoreButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
contentView.readableContentGuide.trailingAnchor.constraint(equalTo: loadMoreButton.trailingAnchor), contentView.trailingAnchor.constraint(equalTo: loadMoreButton.trailingAnchor),
contentView.bottomAnchor.constraint(equalTo: loadMoreButton.bottomAnchor, constant: TimelineLoaderTableViewCell.bottomPadding), contentView.bottomAnchor.constraint(equalTo: loadMoreButton.bottomAnchor, constant: 14),
loadMoreButton.heightAnchor.constraint(equalToConstant: 44).priority(.defaultHigh), 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 activityIndicatorView.translatesAutoresizingMaskIntoConstraints = false
addSubview(activityIndicatorView) addSubview(activityIndicatorView)
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
activityIndicatorView.centerXAnchor.constraint(equalTo: loadMoreButton.centerXAnchor),
activityIndicatorView.centerYAnchor.constraint(equalTo: loadMoreButton.centerYAnchor), activityIndicatorView.centerYAnchor.constraint(equalTo: loadMoreButton.centerYAnchor),
activityIndicatorView.trailingAnchor.constraint(equalTo: loadMoreLabel.leadingAnchor),
]) ])
loadMoreButton.isHidden = true
activityIndicatorView.isHidden = true activityIndicatorView.isHidden = true
} }

View File

@ -21,10 +21,6 @@ final class TimelineMiddleLoaderTableViewCell: TimelineLoaderTableViewCell {
override func _init() { override func _init() {
super._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.setInsets(forContentPadding: .zero, imageTitlePadding: 4)
loadMoreButton.addTarget(self, action: #selector(TimelineMiddleLoaderTableViewCell.loadMoreButtonDidPressed(_:)), for: .touchUpInside) loadMoreButton.addTarget(self, action: #selector(TimelineMiddleLoaderTableViewCell.loadMoreButtonDidPressed(_:)), for: .touchUpInside)
} }