Address PR Feedback (IOS-176)

This commit is contained in:
Marcus Kida 2023-12-28 13:47:07 +01:00
parent 405b175bdf
commit bf433e332f
No known key found for this signature in database
GPG Key ID: 19FF64E08013CA40
20 changed files with 65 additions and 75 deletions

View File

@ -569,7 +569,10 @@ public extension SceneCoordinator {
@MainActor @MainActor
func showLoading(on viewController: UIViewController?) { func showLoading(on viewController: UIViewController?) {
guard let viewController else { return } guard let viewController else { return }
/// Don't add HUD twice
guard MBProgressHUD.forView(viewController.view) == nil else { return }
MBProgressHUD.showAdded(to: viewController.view, animated: true) MBProgressHUD.showAdded(to: viewController.view, animated: true)
} }

View File

@ -50,7 +50,6 @@ extension DataSourceFacade {
await responseToURLAction( await responseToURLAction(
provider: provider, provider: provider,
status: status,
url: url url: url
) )
case .hashtag(_, let hashtag, _): case .hashtag(_, let hashtag, _):

View File

@ -12,19 +12,21 @@ import MastodonSDK
extension DataSourceFacade { extension DataSourceFacade {
@MainActor
static func coordinateToProfileScene( static func coordinateToProfileScene(
provider: DataSourceProvider & AuthContextProvider, provider: DataSourceProvider & AuthContextProvider,
target: StatusTarget, target: StatusTarget,
status: MastodonStatus status: MastodonStatus
) async { ) async {
let acct: String = { let acct: String
switch target { switch target {
case .status: case .status:
return status.reblog?.entity.account.acct ?? status.entity.account.acct acct = status.reblog?.entity.account.acct ?? status.entity.account.acct
case .reblog: case .reblog:
return status.entity.account.acct acct = status.entity.account.acct
} }
}()
provider.coordinator.showLoading()
let _redirectRecord = try? await Mastodon.API.Account.lookupAccount( let _redirectRecord = try? await Mastodon.API.Account.lookupAccount(
session: .shared, session: .shared,
@ -35,6 +37,7 @@ extension DataSourceFacade {
guard let redirectRecord = _redirectRecord else { guard let redirectRecord = _redirectRecord else {
assertionFailure() assertionFailure()
provider.coordinator.hideLoading()
return return
} }
await coordinateToProfileScene( await coordinateToProfileScene(
@ -110,12 +113,9 @@ extension DataSourceFacade {
return return
} }
let managedObjectContext = provider.context.managedObjectContext let mentions = status.entity.mentions ?? []
let mentions = try? await managedObjectContext.perform {
return status.entity.mentions ?? []
}
guard let mention = mentions?.first(where: { $0.url == href }) else { guard let mention = mentions.first(where: { $0.url == href }) else {
_ = provider.coordinator.present( _ = provider.coordinator.present(
scene: .safari(url: url), scene: .safari(url: url),
from: provider, from: provider,

View File

@ -14,7 +14,6 @@ import MastodonSDK
extension DataSourceFacade { extension DataSourceFacade {
static func responseToURLAction( static func responseToURLAction(
provider: DataSourceProvider & AuthContextProvider, provider: DataSourceProvider & AuthContextProvider,
status: MastodonStatus,
url: URL url: URL
) async { ) async {
let domain = provider.authContext.mastodonAuthenticationBox.domain let domain = provider.authContext.mastodonAuthenticationBox.domain

View File

@ -182,9 +182,15 @@ extension NotificationTableViewCellDelegate where Self: DataSourceProvider & Med
let _mediaTransitionContext: NotificationMediaTransitionContext? = { let _mediaTransitionContext: NotificationMediaTransitionContext? = {
guard let status = record.status?.reblog ?? record.status else { return nil } guard let status = record.status?.reblog ?? record.status else { return nil }
let needsToBeToggled: Bool = {
guard let sensitive = status.entity.sensitive else {
return false
}
return status.isSensitiveToggled ? !sensitive : sensitive
}()
return NotificationMediaTransitionContext( return NotificationMediaTransitionContext(
status: status, status: status,
needsToggleMediaSensitive: status.isSensitiveToggled ? !(status.entity.sensitive == true) : (status.entity.sensitive == true) needsToggleMediaSensitive: needsToBeToggled
) )
}() }()

View File

@ -148,7 +148,6 @@ extension StatusTableViewCellDelegate where Self: DataSourceProvider & AuthConte
await DataSourceFacade.responseToURLAction( await DataSourceFacade.responseToURLAction(
provider: self, provider: self,
status: status,
url: url url: url
) )
} }
@ -173,7 +172,6 @@ extension StatusTableViewCellDelegate where Self: DataSourceProvider & AuthConte
await DataSourceFacade.responseToURLAction( await DataSourceFacade.responseToURLAction(
provider: self, provider: self,
status: status,
url: url url: url
) )
} }

View File

@ -65,10 +65,7 @@ extension StatusTableViewControllerNavigateableCore where Self: DataSourceProvid
case .status(let record): case .status(let record):
return record return record
case .notification(let record): case .notification(let record):
guard let statusRecord = record.status else { return record.status
return nil
}
return statusRecord
default: default:
return nil return nil
} }

View File

@ -40,9 +40,7 @@ extension UITableViewDelegate where Self: DataSourceProvider & AuthContextProvid
provider: self, provider: self,
tag: tag tag: tag
) )
case .notification(let notification): case .notification(let notification):
let managedObjectContext = context.managedObjectContext
let _status: MastodonStatus? = notification.status let _status: MastodonStatus? = notification.status
if let status = _status { if let status = _status {
await DataSourceFacade.coordinateToStatusThreadScene( await DataSourceFacade.coordinateToStatusThreadScene(

View File

@ -22,15 +22,12 @@ extension HomeTimelineViewController: DataSourceProvider {
switch item { switch item {
case .feed(let feed): case .feed(let feed):
let item: DataSourceItem? = { guard feed.kind == .home else { return nil }
guard feed.kind == .home else { return nil } if let status = feed.status {
if let status = feed.status { return .status(record: status)
return .status(record: status) } else {
} else { return nil
return nil }
}
}()
return item
default: default:
return nil return nil
} }

View File

@ -52,10 +52,7 @@ extension HomeTimelineViewModel.LoadOldestState {
} }
Task { Task {
let _maxID: Mastodon.Entity.Status.ID? = { let _maxID = lastFeedRecord.status?.id
guard let status = lastFeedRecord.status else { return nil }
return status.id
}()
guard let maxID = _maxID else { guard let maxID = _maxID else {
await self.enter(state: Fail.self) await self.enter(state: Fail.self)

View File

@ -42,7 +42,7 @@ extension NotificationTimelineViewController: DataSourceProvider {
} }
func delete(status: MastodonStatus) { func delete(status: MastodonStatus) {
viewModel.feedFetchedResultsController viewModel.feedFetchedResultsController.delete(status: status)
} }
@MainActor @MainActor

View File

@ -111,18 +111,6 @@ extension NotificationTimelineViewModel {
// load timeline gap // load timeline gap
func loadMore(item: NotificationItem) async { func loadMore(item: NotificationItem) async {
// guard case let .feedLoader(record) = item else { return }
// guard let maxID = record.notification?.id else { return }
// // fetch data
// if let notifications = try? await context.apiService.notifications(
// maxID: maxID,
// scope: scope,
// authenticationBox: authContext.mastodonAuthenticationBox
// ) {
// self.feedFetchedResultsController.records += notifications.value.map { MastodonFeed.fromNotification($0, kind: record.kind) }
// }
switch scope { switch scope {
case .everything: case .everything:
feedFetchedResultsController.loadNext(kind: .notificationAll) feedFetchedResultsController.loadNext(kind: .notificationAll)

View File

@ -9,6 +9,7 @@ import UIKit
import MastodonSDK import MastodonSDK
extension ReportStatusTableViewCell { extension ReportStatusTableViewCell {
// todo: refactor / remove this
final class ViewModel { final class ViewModel {
let value: MastodonStatus let value: MastodonStatus

View File

@ -13,6 +13,12 @@ public protocol UserIdentifier {
var userID: Mastodon.Entity.Account.ID { get } var userID: Mastodon.Entity.Account.ID { get }
} }
public extension UserIdentifier {
var uniqueUserDomainIdentifier: String {
"\(userID)@\(domain)"
}
}
public struct MastodonUserIdentifier: UserIdentifier { public struct MastodonUserIdentifier: UserIdentifier {
public let domain: String public let domain: String
public var userID: Mastodon.Entity.Account.ID public var userID: Mastodon.Entity.Account.ID

View File

@ -14,20 +14,16 @@ public enum Persistence {
case notificationsMentions(UserIdentifier) case notificationsMentions(UserIdentifier)
case notificationsAll(UserIdentifier) case notificationsAll(UserIdentifier)
private func uniqueUserDomainIdentifier(for userIdentifier: UserIdentifier) -> String {
"\(userIdentifier.userID)@\(userIdentifier.domain)"
}
private var filename: String { private var filename: String {
switch self { switch self {
case .searchHistory: case .searchHistory:
return "search_history" // todo: @zeitschlag should this be user-scoped as well? return "search_history" // todo: @zeitschlag should this be user-scoped as well?
case let .homeTimeline(userIdentifier): case let .homeTimeline(userIdentifier):
return "home_timeline_\(uniqueUserDomainIdentifier(for: userIdentifier))" return "home_timeline_\(userIdentifier.uniqueUserDomainIdentifier)"
case let .notificationsMentions(userIdentifier): case let .notificationsMentions(userIdentifier):
return "notifications_mentions_\(uniqueUserDomainIdentifier(for: userIdentifier))" return "notifications_mentions_\(userIdentifier.uniqueUserDomainIdentifier)"
case let .notificationsAll(userIdentifier): case let .notificationsAll(userIdentifier):
return "notifications_all_\(uniqueUserDomainIdentifier(for: userIdentifier))" return "notifications_all_\(userIdentifier.uniqueUserDomainIdentifier)"
} }
} }

View File

@ -50,8 +50,8 @@ extension APIService {
for entity in response.value { for entity in response.value {
guard let poll = entity.poll else { continue } guard let poll = entity.poll else { continue }
_ = Persistence.Poll.createOrMerge( _ = Persistence.Poll.createOrMerge(
in: managedObjectContext, in: managedObjectContext,
context: .init(domain: domain, entity: poll, me: me, networkDate: response.networkDate) context: .init(domain: domain, entity: poll, me: me, networkDate: response.networkDate)
) )
} }
} }

View File

@ -49,8 +49,8 @@ extension APIService {
for entity in response.value { for entity in response.value {
guard let poll = entity.poll else { continue } guard let poll = entity.poll else { continue }
_ = Persistence.Poll.createOrMerge( _ = Persistence.Poll.createOrMerge(
in: managedObjectContext, in: managedObjectContext,
context: .init(domain: domain, entity: poll, me: me, networkDate: response.networkDate) context: .init(domain: domain, entity: poll, me: me, networkDate: response.networkDate)
) )
} }
} }

View File

@ -35,8 +35,8 @@ extension APIService {
for entity in response.value { for entity in response.value {
guard let poll = entity.poll else { continue } guard let poll = entity.poll else { continue }
_ = Persistence.Poll.createOrMerge( _ = Persistence.Poll.createOrMerge(
in: managedObjectContext, in: managedObjectContext,
context: .init(domain: domain, entity: poll, me: me, networkDate: response.networkDate) context: .init(domain: domain, entity: poll, me: me, networkDate: response.networkDate)
) )
} }
} }

View File

@ -344,9 +344,12 @@ private extension Mastodon.Entity.Card {
if !aspectRatio.isFinite { if !aspectRatio.isFinite {
aspectRatio = 1 aspectRatio = 1
} }
return (abs(aspectRatio - 1) < 0.05 || image == nil) && html == nil
? .compact if (abs(aspectRatio - 1) < 0.05 || image == nil) && html == nil {
: .large(aspectRatio: aspectRatio) return .compact
} else {
return .large(aspectRatio: aspectRatio)
}
} }
} }

View File

@ -193,7 +193,6 @@ extension StatusView {
} }
.store(in: &disposeBag) .store(in: &disposeBag)
} // end if let } // end if let
// } // end else B2.
} // end else B. } // end else B.
} else { } else {
@ -389,14 +388,17 @@ extension StatusView {
private func configurePoll(status: MastodonStatus) { private func configurePoll(status: MastodonStatus) {
let status = status.reblog ?? status let status = status.reblog ?? status
let predicate = Poll.predicate(domain: viewModel.authContext?.mastodonAuthenticationBox.domain ?? "", id: status.entity.poll?.id ?? "")
guard guard
let context = viewModel.context?.managedObjectContext, let context = viewModel.context?.managedObjectContext,
let poll = Poll.findOrFetch(in: context, matching: predicate) let domain = viewModel.authContext?.mastodonAuthenticationBox.domain,
else { return } let pollId = status.entity.poll?.id
else {
return
}
let predicate = Poll.predicate(domain: domain, id: pollId)
guard let poll = Poll.findOrFetch(in: context, matching: predicate) else { return }
viewModel.managedObjects.insert(poll) viewModel.managedObjects.insert(poll)