Address PR Feedback (IOS-176)
This commit is contained in:
parent
405b175bdf
commit
bf433e332f
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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, _):
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
)
|
)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -42,7 +42,7 @@ extension NotificationTimelineViewController: DataSourceProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
func delete(status: MastodonStatus) {
|
func delete(status: MastodonStatus) {
|
||||||
viewModel.feedFetchedResultsController
|
viewModel.feedFetchedResultsController.delete(status: status)
|
||||||
}
|
}
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue