Compare commits

...

3 Commits

3 changed files with 20 additions and 19 deletions

View File

@ -156,7 +156,7 @@ class SegmentedPageViewController<Page: SegmentedPageViewControllerPage>: UIView
// MARK: TabbedPageViewController // MARK: TabbedPageViewController
func selectNextPage() { func selectNextPage() {
guard currentIndex < pageControllers.count - 1 else { return } guard currentIndex < pages.count - 1 else { return }
selectPage(pages[currentIndex + 1], animated: true) selectPage(pages[currentIndex + 1], animated: true)
} }

View File

@ -84,8 +84,11 @@ class TimelineLikeController<Item> {
guard state == .notLoadedInitial || state == .idle else { guard state == .notLoadedInitial || state == .idle else {
return return
} }
state = .restoringInitial let token = LoadAttemptToken()
state = .restoringInitial(token, hasAddedLoadingIndicator: false)
let loadingIndicator = DeferredLoadingIndicator(owner: self, state: state, addedIndicatorState: .restoringInitial(token, hasAddedLoadingIndicator: true))
await doRestore() await doRestore()
await loadingIndicator.end()
state = .idle state = .idle
} }
@ -198,7 +201,7 @@ class TimelineLikeController<Item> {
enum State: Equatable, CustomDebugStringConvertible { enum State: Equatable, CustomDebugStringConvertible {
case notLoadedInitial case notLoadedInitial
case idle case idle
case restoringInitial case restoringInitial(LoadAttemptToken, hasAddedLoadingIndicator: Bool)
case loadingInitial(LoadAttemptToken, hasAddedLoadingIndicator: Bool) case loadingInitial(LoadAttemptToken, hasAddedLoadingIndicator: Bool)
case loadingNewer(LoadAttemptToken) case loadingNewer(LoadAttemptToken)
case loadingOlder(LoadAttemptToken, hasAddedLoadingIndicator: Bool) case loadingOlder(LoadAttemptToken, hasAddedLoadingIndicator: Bool)
@ -210,8 +213,8 @@ class TimelineLikeController<Item> {
return "notLoadedInitial" return "notLoadedInitial"
case .idle: case .idle:
return "idle" return "idle"
case .restoringInitial: case .restoringInitial(let token, let hasAddedLoadingIndicator):
return "restoringInitial" return "restoringInitial(\(ObjectIdentifier(token)), hasAddedLoadingIndicator: \(hasAddedLoadingIndicator))"
case .loadingInitial(let token, let hasAddedLoadingIndicator): case .loadingInitial(let token, let hasAddedLoadingIndicator):
return "loadingInitial(\(ObjectIdentifier(token)), hasAddedLoadingIndicator: \(hasAddedLoadingIndicator))" return "loadingInitial(\(ObjectIdentifier(token)), hasAddedLoadingIndicator: \(hasAddedLoadingIndicator))"
case .loadingNewer(let token): case .loadingNewer(let token):
@ -234,13 +237,13 @@ class TimelineLikeController<Item> {
} }
case .idle: case .idle:
switch to { switch to {
case .restoringInitial, .loadingInitial(_, _), .loadingNewer(_), .loadingOlder(_, _), .loadingGap(_, _): case .restoringInitial(_, _), .loadingInitial(_, _), .loadingNewer(_), .loadingOlder(_, _), .loadingGap(_, _):
return true return true
default: default:
return false return false
} }
case .restoringInitial: case .restoringInitial(let token, let hasAddedLoadingIndicator):
return to == .idle return to == .idle || (!hasAddedLoadingIndicator && to == .restoringInitial(token, hasAddedLoadingIndicator: true))
case .loadingInitial(let token, let hasAddedLoadingIndicator): case .loadingInitial(let token, let hasAddedLoadingIndicator):
return to == .notLoadedInitial || to == .idle || (!hasAddedLoadingIndicator && to == .loadingInitial(token, hasAddedLoadingIndicator: true)) return to == .notLoadedInitial || to == .idle || (!hasAddedLoadingIndicator && to == .loadingInitial(token, hasAddedLoadingIndicator: true))
case .loadingNewer(_): case .loadingNewer(_):
@ -256,14 +259,14 @@ class TimelineLikeController<Item> {
switch event { switch event {
case .addLoadingIndicator: case .addLoadingIndicator:
switch self { switch self {
case .loadingInitial(_, _), .loadingOlder(_, _): case .restoringInitial(_, _), .loadingInitial(_, _), .loadingOlder(_, _):
return true return true
default: default:
return false return false
} }
case .removeLoadingIndicator: case .removeLoadingIndicator:
switch self { switch self {
case .loadingInitial(_, hasAddedLoadingIndicator: true), .loadingOlder(_, hasAddedLoadingIndicator: true): case .restoringInitial(_, hasAddedLoadingIndicator: true), .loadingInitial(_, hasAddedLoadingIndicator: true), .loadingOlder(_, hasAddedLoadingIndicator: true):
return true return true
default: default:
return false return false
@ -344,6 +347,7 @@ class TimelineLikeController<Item> {
} }
} }
@MainActor
class DeferredLoadingIndicator { class DeferredLoadingIndicator {
private let owner: TimelineLikeController<Item> private let owner: TimelineLikeController<Item>
private let addedIndicatorState: State private let addedIndicatorState: State
@ -352,19 +356,18 @@ class TimelineLikeController<Item> {
init(owner: TimelineLikeController<Item>, state: State, addedIndicatorState: State) { init(owner: TimelineLikeController<Item>, state: State, addedIndicatorState: State) {
self.owner = owner self.owner = owner
self.addedIndicatorState = addedIndicatorState self.addedIndicatorState = addedIndicatorState
self.task = Task { self.task = Task { @MainActor in
try await Task.sleep(nanoseconds: 150 * NSEC_PER_MSEC) try await Task.sleep(nanoseconds: 150 * NSEC_PER_MSEC)
guard await state == owner.state else { guard state == owner.state else {
return return
} }
await owner.emit(event: .addLoadingIndicator) await owner.emit(event: .addLoadingIndicator)
await owner.transition(to: addedIndicatorState) owner.transition(to: addedIndicatorState)
} }
} }
func end() async { func end() async {
let state = await owner.state if owner.state == addedIndicatorState {
if state == addedIndicatorState {
await owner.emit(event: .removeLoadingIndicator) await owner.emit(event: .removeLoadingIndicator)
} else { } else {
task.cancel() task.cancel()

View File

@ -43,9 +43,6 @@ class StatusCardView: UIView {
} }
private func commonInit() { private func commonInit() {
// self.clipsToBounds = true
// self.layer.borderWidth = 0.5
// self.layer.borderColor = UIColor.lightGray.cgColor
self.layer.shadowColor = UIColor.black.cgColor self.layer.shadowColor = UIColor.black.cgColor
self.layer.shadowRadius = 5 self.layer.shadowRadius = 5
self.layer.shadowOpacity = 0.2 self.layer.shadowOpacity = 0.2
@ -57,11 +54,12 @@ class StatusCardView: UIView {
titleLabel.font = UIFont(descriptor: UIFontDescriptor.preferredFontDescriptor(withTextStyle: .subheadline).withSymbolicTraits(.traitBold)!, size: 0) titleLabel.font = UIFont(descriptor: UIFontDescriptor.preferredFontDescriptor(withTextStyle: .subheadline).withSymbolicTraits(.traitBold)!, size: 0)
titleLabel.adjustsFontForContentSizeCategory = true titleLabel.adjustsFontForContentSizeCategory = true
titleLabel.numberOfLines = 2 titleLabel.numberOfLines = 2
titleLabel.setContentHuggingPriority(.defaultHigh, for: .vertical)
descriptionLabel = UILabel() descriptionLabel = UILabel()
descriptionLabel.font = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: .caption1), size: 0) descriptionLabel.font = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: .caption1), size: 0)
descriptionLabel.adjustsFontForContentSizeCategory = true descriptionLabel.adjustsFontForContentSizeCategory = true
descriptionLabel.numberOfLines = 2 descriptionLabel.numberOfLines = 3
descriptionLabel.setContentCompressionResistancePriority(.defaultLow, for: .vertical) descriptionLabel.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
domainLabel = UILabel() domainLabel = UILabel()