forked from zelo72/mastodon-ios
feature: finish domainBlock action and domainUnblick action
This commit is contained in:
parent
ccdc48add1
commit
33401b4e1f
|
@ -26,6 +26,7 @@
|
||||||
</entity>
|
</entity>
|
||||||
<entity name="DomainBlock" representedClassName=".DomainBlock" syncable="YES">
|
<entity name="DomainBlock" representedClassName=".DomainBlock" syncable="YES">
|
||||||
<attribute name="blockedDomain" attributeType="String"/>
|
<attribute name="blockedDomain" attributeType="String"/>
|
||||||
|
<attribute name="createAt" attributeType="Date" usesScalarValueType="NO"/>
|
||||||
<attribute name="domain" attributeType="String"/>
|
<attribute name="domain" attributeType="String"/>
|
||||||
<attribute name="userID" attributeType="String"/>
|
<attribute name="userID" attributeType="String"/>
|
||||||
<uniquenessConstraints>
|
<uniquenessConstraints>
|
||||||
|
@ -264,7 +265,7 @@
|
||||||
<elements>
|
<elements>
|
||||||
<element name="Application" positionX="0" positionY="0" width="128" height="104"/>
|
<element name="Application" positionX="0" positionY="0" width="128" height="104"/>
|
||||||
<element name="Attachment" positionX="0" positionY="0" width="128" height="254"/>
|
<element name="Attachment" positionX="0" positionY="0" width="128" height="254"/>
|
||||||
<element name="DomainBlock" positionX="45" positionY="162" width="128" height="74"/>
|
<element name="DomainBlock" positionX="45" positionY="162" width="128" height="89"/>
|
||||||
<element name="Emoji" positionX="0" positionY="0" width="128" height="149"/>
|
<element name="Emoji" positionX="0" positionY="0" width="128" height="149"/>
|
||||||
<element name="History" positionX="0" positionY="0" width="128" height="119"/>
|
<element name="History" positionX="0" positionY="0" width="128" height="119"/>
|
||||||
<element name="HomeTimelineIndex" positionX="0" positionY="0" width="128" height="134"/>
|
<element name="HomeTimelineIndex" positionX="0" positionY="0" width="128" height="134"/>
|
||||||
|
|
|
@ -61,7 +61,8 @@
|
||||||
"manually_search": "Manually search instead",
|
"manually_search": "Manually search instead",
|
||||||
"skip": "Skip",
|
"skip": "Skip",
|
||||||
"report_user": "Report %s",
|
"report_user": "Report %s",
|
||||||
"block_domain": "Block %s"
|
"block_domain": "Block %s",
|
||||||
|
"unblock_domain": "Unblock %s"
|
||||||
},
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"user_reblogged": "%s reblogged",
|
"user_reblogged": "%s reblogged",
|
||||||
|
@ -91,7 +92,7 @@
|
||||||
"pending": "Pending",
|
"pending": "Pending",
|
||||||
"block": "Block",
|
"block": "Block",
|
||||||
"block_user": "Block %s",
|
"block_user": "Block %s",
|
||||||
"block_domain": "Block %s",
|
"block_domain": "Domain Blocked",
|
||||||
"unblock": "Unblock",
|
"unblock": "Unblock",
|
||||||
"unblock_user": "Unblock %s",
|
"unblock_user": "Unblock %s",
|
||||||
"blocked": "Blocked",
|
"blocked": "Blocked",
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
"repositoryURL": "https://github.com/onevcat/Kingfisher.git",
|
"repositoryURL": "https://github.com/onevcat/Kingfisher.git",
|
||||||
"state": {
|
"state": {
|
||||||
"branch": null,
|
"branch": null,
|
||||||
"revision": "bbc4bc4def7eb05a7ba8e1219f80ee9be327334e",
|
"revision": "15d199e84677303a7004ed2c5ecaa1a90f3863f8",
|
||||||
"version": "6.2.1"
|
"version": "6.2.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -781,24 +781,43 @@ extension StatusSection {
|
||||||
}
|
}
|
||||||
let author = status.authorForUserProvider
|
let author = status.authorForUserProvider
|
||||||
let canReport = authenticationBox.userID != author.id
|
let canReport = authenticationBox.userID != author.id
|
||||||
let canBlockDomain = authenticationBox.domain != author.domain
|
let isInSameDomain = authenticationBox.domain == author.domainFromAcct
|
||||||
let isMuting = (author.mutingBy ?? Set()).map(\.id).contains(authenticationBox.userID)
|
let isMuting = (author.mutingBy ?? Set()).map(\.id).contains(authenticationBox.userID)
|
||||||
let isBlocking = (author.blockingBy ?? Set()).map(\.id).contains(authenticationBox.userID)
|
let isBlocking = (author.blockingBy ?? Set()).map(\.id).contains(authenticationBox.userID)
|
||||||
|
|
||||||
cell.statusView.actionToolbarContainer.moreButton.showsMenuAsPrimaryAction = true
|
cell.statusView.actionToolbarContainer.moreButton.showsMenuAsPrimaryAction = true
|
||||||
cell.statusView.actionToolbarContainer.moreButton.menu = UserProviderFacade.createProfileActionMenu(
|
let managedObjectContext = userProvider.context.backgroundManagedObjectContext
|
||||||
for: author,
|
managedObjectContext.perform {
|
||||||
isMuting: isMuting,
|
let blockedDomain: DomainBlock? = {
|
||||||
isBlocking: isBlocking,
|
let request = DomainBlock.sortedFetchRequest
|
||||||
canReport: canReport,
|
request.predicate = DomainBlock.predicate(domain: authenticationBox.domain, userID: authenticationBox.userID, blockedDomain: author.domainFromAcct)
|
||||||
canBlockDomain: canBlockDomain,
|
request.fetchLimit = 1
|
||||||
provider: userProvider,
|
request.returnsObjectsAsFaults = false
|
||||||
cell: cell,
|
do {
|
||||||
indexPath: indexPath,
|
return try managedObjectContext.fetch(request).first
|
||||||
sourceView: cell.statusView.actionToolbarContainer.moreButton,
|
} catch {
|
||||||
barButtonItem: nil,
|
assertionFailure(error.localizedDescription)
|
||||||
shareUser: nil,
|
return nil
|
||||||
shareStatus: status
|
}
|
||||||
)
|
}()
|
||||||
|
let isDomainBlocking = blockedDomain != nil
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
cell.statusView.actionToolbarContainer.moreButton.menu = UserProviderFacade.createProfileActionMenu(
|
||||||
|
for: author,
|
||||||
|
isMuting: isMuting,
|
||||||
|
isBlocking: isBlocking,
|
||||||
|
canReport: canReport,
|
||||||
|
isInSameDomain: isInSameDomain,
|
||||||
|
isDomainBlocking: isDomainBlocking,
|
||||||
|
provider: userProvider,
|
||||||
|
cell: cell,
|
||||||
|
indexPath: indexPath,
|
||||||
|
sourceView: cell.statusView.actionToolbarContainer.moreButton,
|
||||||
|
barButtonItem: nil,
|
||||||
|
shareUser: nil,
|
||||||
|
shareStatus: status
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,14 +124,16 @@ internal enum L10n {
|
||||||
internal static let takePhoto = L10n.tr("Localizable", "Common.Controls.Actions.TakePhoto")
|
internal static let takePhoto = L10n.tr("Localizable", "Common.Controls.Actions.TakePhoto")
|
||||||
/// Try Again
|
/// Try Again
|
||||||
internal static let tryAgain = L10n.tr("Localizable", "Common.Controls.Actions.TryAgain")
|
internal static let tryAgain = L10n.tr("Localizable", "Common.Controls.Actions.TryAgain")
|
||||||
|
/// Unblock %@
|
||||||
|
internal static func unblockDomain(_ p1: Any) -> String {
|
||||||
|
return L10n.tr("Localizable", "Common.Controls.Actions.UnblockDomain", String(describing: p1))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
internal enum Firendship {
|
internal enum Firendship {
|
||||||
/// Block
|
/// Block
|
||||||
internal static let block = L10n.tr("Localizable", "Common.Controls.Firendship.Block")
|
internal static let block = L10n.tr("Localizable", "Common.Controls.Firendship.Block")
|
||||||
/// Block %@
|
/// Domain Blocked
|
||||||
internal static func blockDomain(_ p1: Any) -> String {
|
internal static let blockDomain = L10n.tr("Localizable", "Common.Controls.Firendship.BlockDomain")
|
||||||
return L10n.tr("Localizable", "Common.Controls.Firendship.BlockDomain", String(describing: p1))
|
|
||||||
}
|
|
||||||
/// Blocked
|
/// Blocked
|
||||||
internal static let blocked = L10n.tr("Localizable", "Common.Controls.Firendship.Blocked")
|
internal static let blocked = L10n.tr("Localizable", "Common.Controls.Firendship.Blocked")
|
||||||
/// Block %@
|
/// Block %@
|
||||||
|
|
|
@ -159,7 +159,8 @@ extension UserProviderFacade {
|
||||||
isMuting: Bool,
|
isMuting: Bool,
|
||||||
isBlocking: Bool,
|
isBlocking: Bool,
|
||||||
canReport: Bool,
|
canReport: Bool,
|
||||||
canBlockDomain: Bool,
|
isInSameDomain: Bool,
|
||||||
|
isDomainBlocking: Bool,
|
||||||
provider: UserProvider,
|
provider: UserProvider,
|
||||||
cell: UITableViewCell?,
|
cell: UITableViewCell?,
|
||||||
indexPath: IndexPath?,
|
indexPath: IndexPath?,
|
||||||
|
@ -248,21 +249,37 @@ extension UserProviderFacade {
|
||||||
children.append(reportAction)
|
children.append(reportAction)
|
||||||
}
|
}
|
||||||
|
|
||||||
if canBlockDomain {
|
if !isInSameDomain {
|
||||||
let blockDomainAction = UIAction(title: L10n.Common.Controls.Actions.blockDomain(mastodonUser.domain), image: UIImage(systemName: "nosign"), identifier: nil, discoverabilityTitle: nil, attributes: [], state: .off) { [weak provider] _ in
|
if isDomainBlocking {
|
||||||
guard let provider = provider else { return }
|
let unblockDomainAction = UIAction(title: L10n.Common.Controls.Actions.unblockDomain(mastodonUser.domainFromAcct), image: UIImage(systemName: "nosign"), identifier: nil, discoverabilityTitle: nil, attributes: [], state: .off) { [weak provider] _ in
|
||||||
let alertController = UIAlertController(title: "", message: L10n.Common.Alerts.BlockDomain.message(mastodonUser.domain), preferredStyle: .alert)
|
guard let provider = provider else { return }
|
||||||
let cancelAction = UIAlertAction(title: L10n.Common.Controls.Actions.cancel, style: .default) { _ in
|
BlockDomainService(userProvider: provider,
|
||||||
|
cell: cell,
|
||||||
|
indexPath: indexPath
|
||||||
|
)
|
||||||
|
.unblockDomain()
|
||||||
|
}
|
||||||
|
children.append(unblockDomainAction)
|
||||||
|
} else {
|
||||||
|
let blockDomainAction = UIAction(title: L10n.Common.Controls.Actions.blockDomain(mastodonUser.domainFromAcct), image: UIImage(systemName: "nosign"), identifier: nil, discoverabilityTitle: nil, attributes: [], state: .off) { [weak provider] _ in
|
||||||
|
guard let provider = provider else { return }
|
||||||
|
let alertController = UIAlertController(title: "", message: L10n.Common.Alerts.BlockDomain.message(mastodonUser.domainFromAcct), preferredStyle: .alert)
|
||||||
|
let cancelAction = UIAlertAction(title: L10n.Common.Controls.Actions.cancel, style: .default) { _ in
|
||||||
|
|
||||||
|
}
|
||||||
|
alertController.addAction(cancelAction)
|
||||||
|
let blockDomainAction = UIAlertAction(title: L10n.Common.Alerts.BlockDomain.blockEntireDomain, style: .destructive) { _ in
|
||||||
|
BlockDomainService(userProvider: provider,
|
||||||
|
cell: cell,
|
||||||
|
indexPath: indexPath
|
||||||
|
)
|
||||||
|
.blockDomain()
|
||||||
|
}
|
||||||
|
alertController.addAction(blockDomainAction)
|
||||||
|
provider.present(alertController, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
alertController.addAction(cancelAction)
|
children.append(blockDomainAction)
|
||||||
let blockDomainAction = UIAlertAction(title: L10n.Common.Alerts.BlockDomain.blockEntireDomain, style: .destructive) { _ in
|
|
||||||
BlockDomainService(context: provider.context).blockDomain(domain: mastodonUser.domain)
|
|
||||||
}
|
|
||||||
alertController.addAction(blockDomainAction)
|
|
||||||
provider.present(alertController, animated: true, completion: nil)
|
|
||||||
}
|
}
|
||||||
children.append(blockDomainAction)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let shareUser = shareUser {
|
if let shareUser = shareUser {
|
||||||
|
|
|
@ -41,8 +41,9 @@ Please check your internet connection.";
|
||||||
"Common.Controls.Actions.Skip" = "Skip";
|
"Common.Controls.Actions.Skip" = "Skip";
|
||||||
"Common.Controls.Actions.TakePhoto" = "Take photo";
|
"Common.Controls.Actions.TakePhoto" = "Take photo";
|
||||||
"Common.Controls.Actions.TryAgain" = "Try Again";
|
"Common.Controls.Actions.TryAgain" = "Try Again";
|
||||||
|
"Common.Controls.Actions.UnblockDomain" = "Unblock %@";
|
||||||
"Common.Controls.Firendship.Block" = "Block";
|
"Common.Controls.Firendship.Block" = "Block";
|
||||||
"Common.Controls.Firendship.BlockDomain" = "Block %@";
|
"Common.Controls.Firendship.BlockDomain" = "Domain Blocked";
|
||||||
"Common.Controls.Firendship.BlockUser" = "Block %@";
|
"Common.Controls.Firendship.BlockUser" = "Block %@";
|
||||||
"Common.Controls.Firendship.Blocked" = "Blocked";
|
"Common.Controls.Firendship.Blocked" = "Blocked";
|
||||||
"Common.Controls.Firendship.EditInfo" = "Edit info";
|
"Common.Controls.Firendship.EditInfo" = "Edit info";
|
||||||
|
|
|
@ -377,14 +377,16 @@ extension ProfileViewController {
|
||||||
guard let currentDomain = self.viewModel.domain.value else { return }
|
guard let currentDomain = self.viewModel.domain.value else { return }
|
||||||
let isMuting = relationshipActionOptionSet.contains(.muting)
|
let isMuting = relationshipActionOptionSet.contains(.muting)
|
||||||
let isBlocking = relationshipActionOptionSet.contains(.blocking)
|
let isBlocking = relationshipActionOptionSet.contains(.blocking)
|
||||||
|
let isDomainBlocking = relationshipActionOptionSet.contains(.domainBlocking)
|
||||||
let needsShareAction = self.viewModel.isMeBarButtonItemsHidden.value
|
let needsShareAction = self.viewModel.isMeBarButtonItemsHidden.value
|
||||||
let canBlockDomain = mastodonUser.domain != currentDomain
|
let isInSameDomain = mastodonUser.domainFromAcct == currentDomain
|
||||||
self.moreMenuBarButtonItem.menu = UserProviderFacade.createProfileActionMenu(
|
self.moreMenuBarButtonItem.menu = UserProviderFacade.createProfileActionMenu(
|
||||||
for: mastodonUser,
|
for: mastodonUser,
|
||||||
isMuting: isMuting,
|
isMuting: isMuting,
|
||||||
isBlocking: isBlocking,
|
isBlocking: isBlocking,
|
||||||
canReport: true,
|
canReport: true,
|
||||||
canBlockDomain: canBlockDomain,
|
isInSameDomain: isInSameDomain,
|
||||||
|
isDomainBlocking: isDomainBlocking,
|
||||||
provider: self,
|
provider: self,
|
||||||
cell: nil,
|
cell: nil,
|
||||||
indexPath: nil,
|
indexPath: nil,
|
||||||
|
|
|
@ -327,6 +327,7 @@ extension ProfileViewModel {
|
||||||
case muting
|
case muting
|
||||||
case blocked
|
case blocked
|
||||||
case blocking
|
case blocking
|
||||||
|
case domainBlocking
|
||||||
case suspended
|
case suspended
|
||||||
case edit
|
case edit
|
||||||
case editing
|
case editing
|
||||||
|
@ -349,6 +350,7 @@ extension ProfileViewModel {
|
||||||
static let muting = RelationshipAction.muting.option
|
static let muting = RelationshipAction.muting.option
|
||||||
static let blocked = RelationshipAction.blocked.option
|
static let blocked = RelationshipAction.blocked.option
|
||||||
static let blocking = RelationshipAction.blocking.option
|
static let blocking = RelationshipAction.blocking.option
|
||||||
|
static let domainBlocking = RelationshipAction.domainBlocking.option
|
||||||
static let suspended = RelationshipAction.suspended.option
|
static let suspended = RelationshipAction.suspended.option
|
||||||
static let edit = RelationshipAction.edit.option
|
static let edit = RelationshipAction.edit.option
|
||||||
static let editing = RelationshipAction.editing.option
|
static let editing = RelationshipAction.editing.option
|
||||||
|
@ -379,6 +381,7 @@ extension ProfileViewModel {
|
||||||
case .muting: return L10n.Common.Controls.Firendship.muted
|
case .muting: return L10n.Common.Controls.Firendship.muted
|
||||||
case .blocked: return L10n.Common.Controls.Firendship.follow // blocked by user
|
case .blocked: return L10n.Common.Controls.Firendship.follow // blocked by user
|
||||||
case .blocking: return L10n.Common.Controls.Firendship.blocked
|
case .blocking: return L10n.Common.Controls.Firendship.blocked
|
||||||
|
case .domainBlocking: return L10n.Common.Controls.Firendship.blockDomain
|
||||||
case .suspended: return L10n.Common.Controls.Firendship.follow
|
case .suspended: return L10n.Common.Controls.Firendship.follow
|
||||||
case .edit: return L10n.Common.Controls.Firendship.editInfo
|
case .edit: return L10n.Common.Controls.Firendship.editInfo
|
||||||
case .editing: return L10n.Common.Controls.Actions.done
|
case .editing: return L10n.Common.Controls.Actions.done
|
||||||
|
@ -400,6 +403,7 @@ extension ProfileViewModel {
|
||||||
case .muting: return Asset.Colors.Background.alertYellow.color
|
case .muting: return Asset.Colors.Background.alertYellow.color
|
||||||
case .blocked: return Asset.Colors.Button.normal.color
|
case .blocked: return Asset.Colors.Button.normal.color
|
||||||
case .blocking: return Asset.Colors.Background.danger.color
|
case .blocking: return Asset.Colors.Background.danger.color
|
||||||
|
case .domainBlocking: return Asset.Colors.Button.normal.color
|
||||||
case .suspended: return Asset.Colors.Button.normal.color
|
case .suspended: return Asset.Colors.Button.normal.color
|
||||||
case .edit: return Asset.Colors.Button.normal.color
|
case .edit: return Asset.Colors.Button.normal.color
|
||||||
case .editing: return Asset.Colors.Button.normal.color
|
case .editing: return Asset.Colors.Button.normal.color
|
||||||
|
|
|
@ -5,16 +5,15 @@
|
||||||
// Created by sxiaojian on 2021/4/29.
|
// Created by sxiaojian on 2021/4/29.
|
||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import Combine
|
import Combine
|
||||||
|
import CommonOSLog
|
||||||
import CoreData
|
import CoreData
|
||||||
import CoreDataStack
|
import CoreDataStack
|
||||||
import CommonOSLog
|
|
||||||
import DateToolsSwift
|
import DateToolsSwift
|
||||||
|
import Foundation
|
||||||
import MastodonSDK
|
import MastodonSDK
|
||||||
|
|
||||||
extension APIService {
|
extension APIService {
|
||||||
|
|
||||||
func getDomainblocks(
|
func getDomainblocks(
|
||||||
domain: String,
|
domain: String,
|
||||||
limit: Int = onceRequestDomainBlocksMaxCount,
|
limit: Int = onceRequestDomainBlocksMaxCount,
|
||||||
|
@ -32,10 +31,10 @@ extension APIService {
|
||||||
query: query
|
query: query
|
||||||
)
|
)
|
||||||
.flatMap { response -> AnyPublisher<Mastodon.Response.Content<[String]>, Error> in
|
.flatMap { response -> AnyPublisher<Mastodon.Response.Content<[String]>, Error> in
|
||||||
return self.backgroundManagedObjectContext.performChanges {
|
self.backgroundManagedObjectContext.performChanges {
|
||||||
response.value.forEach { domain in
|
response.value.forEach { domain in
|
||||||
// use constrain to avoid repeated save
|
// use constrain to avoid repeated save
|
||||||
let _ = DomainBlock.insert(
|
_ = DomainBlock.insert(
|
||||||
into: self.backgroundManagedObjectContext,
|
into: self.backgroundManagedObjectContext,
|
||||||
blockedDomain: domain,
|
blockedDomain: domain,
|
||||||
domain: authorizationBox.domain,
|
domain: authorizationBox.domain,
|
||||||
|
@ -58,28 +57,33 @@ extension APIService {
|
||||||
}
|
}
|
||||||
|
|
||||||
func blockDomain(
|
func blockDomain(
|
||||||
domain: String,
|
user: MastodonUser,
|
||||||
authorizationBox: AuthenticationService.MastodonAuthenticationBox
|
authorizationBox: AuthenticationService.MastodonAuthenticationBox
|
||||||
) -> AnyPublisher<Mastodon.Response.Content<String>, Error> {
|
) -> AnyPublisher<Mastodon.Response.Content<Mastodon.Entity.Empty>, Error> {
|
||||||
let authorization = authorizationBox.userAuthorization
|
let authorization = authorizationBox.userAuthorization
|
||||||
|
|
||||||
return Mastodon.API.DomainBlock.blockDomain(
|
return Mastodon.API.DomainBlock.blockDomain(
|
||||||
domain: authorizationBox.domain,
|
domain: authorizationBox.domain,
|
||||||
blockDomain: domain,
|
blockDomain: user.domainFromAcct,
|
||||||
session: session,
|
session: session,
|
||||||
authorization: authorization
|
authorization: authorization
|
||||||
)
|
)
|
||||||
.flatMap { response -> AnyPublisher<Mastodon.Response.Content<String>, Error> in
|
.flatMap { response -> AnyPublisher<Mastodon.Response.Content<Mastodon.Entity.Empty>, Error> in
|
||||||
return self.backgroundManagedObjectContext.performChanges {
|
self.backgroundManagedObjectContext.performChanges {
|
||||||
let _ = DomainBlock.insert(
|
let requestMastodonUserRequest = MastodonUser.sortedFetchRequest
|
||||||
|
requestMastodonUserRequest.predicate = MastodonUser.predicate(domain: authorizationBox.domain, id: authorizationBox.userID)
|
||||||
|
requestMastodonUserRequest.fetchLimit = 1
|
||||||
|
guard let requestMastodonUser = self.backgroundManagedObjectContext.safeFetch(requestMastodonUserRequest).first else { return }
|
||||||
|
_ = DomainBlock.insert(
|
||||||
into: self.backgroundManagedObjectContext,
|
into: self.backgroundManagedObjectContext,
|
||||||
blockedDomain: domain,
|
blockedDomain: user.domainFromAcct,
|
||||||
domain: authorizationBox.domain,
|
domain: authorizationBox.domain,
|
||||||
userID: authorizationBox.userID
|
userID: authorizationBox.userID
|
||||||
)
|
)
|
||||||
|
user.update(isDomainBlocking: true, by: requestMastodonUser)
|
||||||
}
|
}
|
||||||
.setFailureType(to: Error.self)
|
.setFailureType(to: Error.self)
|
||||||
.tryMap { result -> Mastodon.Response.Content<String> in
|
.tryMap { result -> Mastodon.Response.Content<Mastodon.Entity.Empty> in
|
||||||
switch result {
|
switch result {
|
||||||
case .success:
|
case .success:
|
||||||
return response
|
return response
|
||||||
|
@ -93,28 +97,42 @@ extension APIService {
|
||||||
}
|
}
|
||||||
|
|
||||||
func unblockDomain(
|
func unblockDomain(
|
||||||
domain: String,
|
user: MastodonUser,
|
||||||
authorizationBox: AuthenticationService.MastodonAuthenticationBox
|
authorizationBox: AuthenticationService.MastodonAuthenticationBox
|
||||||
) -> AnyPublisher<Mastodon.Response.Content<String>, Error> {
|
) -> AnyPublisher<Mastodon.Response.Content<Mastodon.Entity.Empty>, Error> {
|
||||||
let authorization = authorizationBox.userAuthorization
|
let authorization = authorizationBox.userAuthorization
|
||||||
|
|
||||||
return Mastodon.API.DomainBlock.unblockDomain(
|
return Mastodon.API.DomainBlock.unblockDomain(
|
||||||
domain: authorizationBox.domain,
|
domain: authorizationBox.domain,
|
||||||
blockDomain: domain,
|
blockDomain: user.domainFromAcct,
|
||||||
session: session,
|
session: session,
|
||||||
authorization: authorization
|
authorization: authorization
|
||||||
)
|
)
|
||||||
.flatMap { response -> AnyPublisher<Mastodon.Response.Content<String>, Error> in
|
.flatMap { response -> AnyPublisher<Mastodon.Response.Content<Mastodon.Entity.Empty>, Error> in
|
||||||
return self.backgroundManagedObjectContext.performChanges {
|
self.backgroundManagedObjectContext.performChanges {
|
||||||
// let _ = DomainBlock.insert(
|
let blockedDomain: DomainBlock? = {
|
||||||
// into: self.backgroundManagedObjectContext,
|
let request = DomainBlock.sortedFetchRequest
|
||||||
// blockedDomain: domain,
|
request.predicate = DomainBlock.predicate(domain: authorizationBox.domain, userID: authorizationBox.userID, blockedDomain: user.domainFromAcct)
|
||||||
// domain: authorizationBox.domain,
|
request.fetchLimit = 1
|
||||||
// userID: authorizationBox.userID
|
request.returnsObjectsAsFaults = false
|
||||||
// )
|
do {
|
||||||
|
return try self.backgroundManagedObjectContext.fetch(request).first
|
||||||
|
} catch {
|
||||||
|
assertionFailure(error.localizedDescription)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if let blockedDomain = blockedDomain {
|
||||||
|
self.backgroundManagedObjectContext.delete(blockedDomain)
|
||||||
|
}
|
||||||
|
let requestMastodonUserRequest = MastodonUser.sortedFetchRequest
|
||||||
|
requestMastodonUserRequest.predicate = MastodonUser.predicate(domain: authorizationBox.domain, id: authorizationBox.userID)
|
||||||
|
requestMastodonUserRequest.fetchLimit = 1
|
||||||
|
guard let requestMastodonUser = self.backgroundManagedObjectContext.safeFetch(requestMastodonUserRequest).first else { return }
|
||||||
|
user.update(isDomainBlocking: false, by: requestMastodonUser)
|
||||||
}
|
}
|
||||||
.setFailureType(to: Error.self)
|
.setFailureType(to: Error.self)
|
||||||
.tryMap { result -> Mastodon.Response.Content<String> in
|
.tryMap { result -> Mastodon.Response.Content<Mastodon.Entity.Empty> in
|
||||||
switch result {
|
switch result {
|
||||||
case .success:
|
case .success:
|
||||||
return response
|
return response
|
||||||
|
|
|
@ -8,15 +8,95 @@
|
||||||
import CoreData
|
import CoreData
|
||||||
import CoreDataStack
|
import CoreDataStack
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import Combine
|
||||||
|
import MastodonSDK
|
||||||
|
import OSLog
|
||||||
|
import UIKit
|
||||||
|
|
||||||
final class BlockDomainService {
|
final class BlockDomainService {
|
||||||
let context: AppContext
|
let userProvider: UserProvider
|
||||||
|
let cell: UITableViewCell?
|
||||||
init(context: AppContext) {
|
let indexPath: IndexPath?
|
||||||
self.context = context
|
init(userProvider: UserProvider,
|
||||||
|
cell: UITableViewCell?,
|
||||||
|
indexPath: IndexPath?
|
||||||
|
) {
|
||||||
|
self.userProvider = userProvider
|
||||||
|
self.cell = cell
|
||||||
|
self.indexPath = indexPath
|
||||||
}
|
}
|
||||||
|
|
||||||
func blockDomain(domain: String) {
|
func blockDomain() {
|
||||||
|
guard let activeMastodonAuthenticationBox = self.userProvider.context.authenticationService.activeMastodonAuthenticationBox.value else { return }
|
||||||
|
guard let context = self.userProvider.context else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var mastodonUser: AnyPublisher<MastodonUser?, Never>
|
||||||
|
if let cell = self.cell, let indexPath = self.indexPath {
|
||||||
|
mastodonUser = userProvider.mastodonUser(for: cell, indexPath: indexPath).eraseToAnyPublisher()
|
||||||
|
} else {
|
||||||
|
mastodonUser = userProvider.mastodonUser().eraseToAnyPublisher()
|
||||||
|
}
|
||||||
|
mastodonUser
|
||||||
|
.compactMap { mastodonUser -> AnyPublisher<Mastodon.Response.Content<Mastodon.Entity.Empty>, Error>? in
|
||||||
|
guard let mastodonUser = mastodonUser else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return context.apiService.blockDomain(user: mastodonUser, authorizationBox: activeMastodonAuthenticationBox)
|
||||||
|
}
|
||||||
|
.switchToLatest()
|
||||||
|
.flatMap { response -> AnyPublisher<Mastodon.Response.Content<[String]>, Error> in
|
||||||
|
return context.apiService.getDomainblocks(domain: activeMastodonAuthenticationBox.domain, authorizationBox: activeMastodonAuthenticationBox)
|
||||||
|
}
|
||||||
|
.sink { completion in
|
||||||
|
switch completion {
|
||||||
|
case .finished:
|
||||||
|
break
|
||||||
|
case .failure(let error):
|
||||||
|
print(error)
|
||||||
|
}
|
||||||
|
} receiveValue: { response in
|
||||||
|
print(response)
|
||||||
|
}
|
||||||
|
.store(in: &userProvider.disposeBag)
|
||||||
|
}
|
||||||
|
|
||||||
|
func unblockDomain() {
|
||||||
|
guard let activeMastodonAuthenticationBox = self.userProvider.context.authenticationService.activeMastodonAuthenticationBox.value else { return }
|
||||||
|
guard let context = self.userProvider.context else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var mastodonUser: AnyPublisher<MastodonUser?, Never>
|
||||||
|
if let cell = self.cell, let indexPath = self.indexPath {
|
||||||
|
mastodonUser = userProvider.mastodonUser(for: cell, indexPath: indexPath).eraseToAnyPublisher()
|
||||||
|
} else {
|
||||||
|
mastodonUser = userProvider.mastodonUser().eraseToAnyPublisher()
|
||||||
|
}
|
||||||
|
mastodonUser
|
||||||
|
.compactMap { mastodonUser -> AnyPublisher<Mastodon.Response.Content<Mastodon.Entity.Empty>, Error>? in
|
||||||
|
guard let mastodonUser = mastodonUser else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return context.apiService.unblockDomain(user: mastodonUser, authorizationBox: activeMastodonAuthenticationBox)
|
||||||
|
}
|
||||||
|
.switchToLatest()
|
||||||
|
.flatMap { response -> AnyPublisher<Mastodon.Response.Content<[String]>, Error> in
|
||||||
|
return context.apiService.getDomainblocks(domain: activeMastodonAuthenticationBox.domain, authorizationBox: activeMastodonAuthenticationBox)
|
||||||
|
}
|
||||||
|
.sink { completion in
|
||||||
|
switch completion {
|
||||||
|
case .finished:
|
||||||
|
break
|
||||||
|
case .failure(let error):
|
||||||
|
print(error)
|
||||||
|
}
|
||||||
|
} receiveValue: { response in
|
||||||
|
print(response)
|
||||||
|
}
|
||||||
|
.store(in: &userProvider.disposeBag)
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", (#file as NSString).lastPathComponent, #line, #function)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ extension Mastodon.API.DomainBlock {
|
||||||
blockDomain:String,
|
blockDomain:String,
|
||||||
session: URLSession,
|
session: URLSession,
|
||||||
authorization: Mastodon.API.OAuth.Authorization
|
authorization: Mastodon.API.OAuth.Authorization
|
||||||
) -> AnyPublisher<Mastodon.Response.Content<String>, Error> {
|
) -> AnyPublisher<Mastodon.Response.Content<Mastodon.Entity.Empty>, Error> {
|
||||||
let query = Mastodon.API.DomainBlock.BlockQuery(domain: blockDomain)
|
let query = Mastodon.API.DomainBlock.BlockQuery(domain: blockDomain)
|
||||||
let request = Mastodon.API.post(
|
let request = Mastodon.API.post(
|
||||||
url: domainBlockEndpointURL(domain: domain),
|
url: domainBlockEndpointURL(domain: domain),
|
||||||
|
@ -63,7 +63,7 @@ extension Mastodon.API.DomainBlock {
|
||||||
)
|
)
|
||||||
return session.dataTaskPublisher(for: request)
|
return session.dataTaskPublisher(for: request)
|
||||||
.tryMap { data, response in
|
.tryMap { data, response in
|
||||||
let value = try Mastodon.API.decode(type: String.self, from: data, response: response)
|
let value = try Mastodon.API.decode(type: Mastodon.Entity.Empty.self, from: data, response: response)
|
||||||
return Mastodon.Response.Content(value: value, response: response)
|
return Mastodon.Response.Content(value: value, response: response)
|
||||||
}
|
}
|
||||||
.eraseToAnyPublisher()
|
.eraseToAnyPublisher()
|
||||||
|
@ -84,7 +84,7 @@ extension Mastodon.API.DomainBlock {
|
||||||
blockDomain:String,
|
blockDomain:String,
|
||||||
session: URLSession,
|
session: URLSession,
|
||||||
authorization: Mastodon.API.OAuth.Authorization
|
authorization: Mastodon.API.OAuth.Authorization
|
||||||
) -> AnyPublisher<Mastodon.Response.Content<String>, Error> {
|
) -> AnyPublisher<Mastodon.Response.Content<Mastodon.Entity.Empty>, Error> {
|
||||||
let query = Mastodon.API.DomainBlock.BlockQuery(domain: blockDomain)
|
let query = Mastodon.API.DomainBlock.BlockQuery(domain: blockDomain)
|
||||||
let request = Mastodon.API.delete(
|
let request = Mastodon.API.delete(
|
||||||
url: domainBlockEndpointURL(domain: domain),
|
url: domainBlockEndpointURL(domain: domain),
|
||||||
|
@ -93,7 +93,7 @@ extension Mastodon.API.DomainBlock {
|
||||||
)
|
)
|
||||||
return session.dataTaskPublisher(for: request)
|
return session.dataTaskPublisher(for: request)
|
||||||
.tryMap { data, response in
|
.tryMap { data, response in
|
||||||
let value = try Mastodon.API.decode(type: String.self, from: data, response: response)
|
let value = try Mastodon.API.decode(type: Mastodon.Entity.Empty.self, from: data, response: response)
|
||||||
return Mastodon.Response.Content(value: value, response: response)
|
return Mastodon.Response.Content(value: value, response: response)
|
||||||
}
|
}
|
||||||
.eraseToAnyPublisher()
|
.eraseToAnyPublisher()
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
//
|
||||||
|
// File.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by sxiaojian on 2021/4/30.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension Mastodon.Entity {
|
||||||
|
public struct Empty: Codable {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue