Add user profile actions.

This commit is contained in:
Marcin Czachursk 2023-01-22 15:56:35 +01:00
parent ae74c36350
commit 41520491e9
5 changed files with 186 additions and 28 deletions

View File

@ -15,7 +15,7 @@ extension NetworkError: LocalizedError {
switch self {
case .notSuccessResponse(let response):
let statusCode = response.statusCode()
return NSLocalizedString("Network request returned not success status code: '\(statusCode?.localizedDescription ?? "unknown")'.", comment: "It's error returned from remote server.")
return NSLocalizedString("Network request returned not success status code: '\(statusCode?.localizedDescription ?? "unknown")'. Request URL: '\(response.url?.string ?? "unknown")'.", comment: "It's error returned from remote server.")
}
}
}

View File

@ -74,6 +74,46 @@ public extension MastodonClientAuthenticated {
return try await downloadJson(Relationship.self, request: request)
}
func mute(for accountId: String) async throws -> Relationship {
let request = try Self.request(
for: baseURL,
target: Mastodon.Account.mute(accountId),
withBearerToken: token
)
return try await downloadJson(Relationship.self, request: request)
}
func unmute(for accountId: String) async throws -> Relationship {
let request = try Self.request(
for: baseURL,
target: Mastodon.Account.unmute(accountId),
withBearerToken: token
)
return try await downloadJson(Relationship.self, request: request)
}
func block(for accountId: String) async throws -> Relationship {
let request = try Self.request(
for: baseURL,
target: Mastodon.Account.block(accountId),
withBearerToken: token
)
return try await downloadJson(Relationship.self, request: request)
}
func unblock(for accountId: String) async throws -> Relationship {
let request = try Self.request(
for: baseURL,
target: Mastodon.Account.unblock(accountId),
withBearerToken: token
)
return try await downloadJson(Relationship.self, request: request)
}
func getFollowers(for accountId: String, page: Int = 1) async throws -> [Account] {
let request = try Self.request(
for: baseURL,

View File

@ -69,6 +69,42 @@ public class AccountService {
return try await client.unfollow(for: accountId)
}
public func mute(forAccountId accountId: String, andContext accountData: AccountData?) async throws -> Relationship? {
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
return nil
}
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
return try await client.mute(for: accountId)
}
public func unmute(forAccountId accountId: String, andContext accountData: AccountData?) async throws -> Relationship? {
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
return nil
}
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
return try await client.unmute(for: accountId)
}
public func block(forAccountId accountId: String, andContext accountData: AccountData?) async throws -> Relationship? {
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
return nil
}
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
return try await client.block(for: accountId)
}
public func unblock(forAccountId accountId: String, andContext accountData: AccountData?) async throws -> Relationship? {
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
return nil
}
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
return try await client.unblock(for: accountId)
}
public func getFollowers(forAccountId accountId: String, andContext accountData: AccountData?, page: Int) async throws -> [Account] {
guard let accessToken = accountData?.accessToken, let serverUrl = accountData?.serverUrl else {
return []

View File

@ -108,13 +108,11 @@ struct InteractionRow: View {
Image(systemName: self.bookmarked ? "bookmark.fill" : "bookmark")
}
Spacer()
ActionButton {
// TODO: Share.
ToastrService.shared.showError(subtitle: "Sending new status failed!")
} label: {
Image(systemName: "square.and.arrow.up")
if let url = statusViewModel.url {
Spacer()
ShareLink(item: url) {
Image(systemName: "square.and.arrow.up")
}
}
}
.font(.title3)
@ -133,11 +131,3 @@ struct InteractionRow: View {
self.bookmarked = self.statusViewModel.bookmarked
}
}
struct InteractionRow_Previews: PreviewProvider {
static var previews: some View {
Text("")
// InteractionRow(status: Status(id: "", content: "", application: Application(name: "")))
// .previewLayout(.fixed(width: 300, height: 70))
}
}

View File

@ -69,18 +69,7 @@ struct UserProfileHeader: View {
Spacer()
if self.applicationState.accountData?.id != self.account.id {
ActionButton {
await onRelationshipButtonTap()
} label: {
HStack {
Image(systemName: relationship?.following == true ? "person.badge.minus" : "person.badge.plus")
Text(relationship?.following == true ? "Unfollow" : (relationship?.followedBy == true ? "Follow back" : "Follow"))
}
}
.buttonStyle(.borderedProminent)
.tint(relationship?.following == true ? .dangerColor : .accentColor)
}
self.actionButtons()
}
if let note = account.note, !note.isEmpty {
@ -97,6 +86,65 @@ struct UserProfileHeader: View {
.padding()
}
@ViewBuilder
private func actionButtons() -> some View {
if self.applicationState.accountData?.id != self.account.id {
ActionButton {
await onRelationshipButtonTap()
} label: {
HStack {
Image(systemName: relationship?.following == true ? "person.badge.minus" : "person.badge.plus")
Text(relationship?.following == true ? "Unfollow" : (relationship?.followedBy == true ? "Follow back" : "Follow"))
}
}
.buttonStyle(.borderedProminent)
.tint(relationship?.following == true ? .dangerColor : .accentColor)
Menu (content: {
if let accountUrl = account.url {
Link(destination: accountUrl) {
Label("Open link to profile", systemImage: "safari")
}
ShareLink(item: accountUrl) {
Label("Share", systemImage: "square.and.arrow.up")
}
Divider()
}
Button {
Task {
await onMuteAccount()
}
} label: {
if self.relationship?.muting == true {
Label("Unute", systemImage: "message.and.waveform.fill")
} else {
Label("Mute", systemImage: "message.and.waveform")
}
}
Button {
Task {
await onBlockAccount()
}
} label: {
if self.relationship?.blocking == true {
Label("Unblock", systemImage: "hand.raised.fill")
} else {
Label("Block", systemImage: "hand.raised")
}
}
}, label: {
Image(systemName: "ellipsis.circle")
})
.buttonStyle(.borderedProminent)
.tint(Color.secondaryLabel)
}
}
private func onRelationshipButtonTap() async {
do {
if self.relationship?.following == true {
@ -118,5 +166,49 @@ struct UserProfileHeader: View {
ErrorService.shared.handle(error, message: "Relationship action failed.", showToastr: true)
}
}
private func onMuteAccount() async {
do {
if self.relationship?.muting == true {
if let relationship = try await AccountService.shared.unmute(
forAccountId: self.account.id,
andContext: self.applicationState.accountData
) {
self.relationship = relationship
}
} else {
if let relationship = try await AccountService.shared.mute(
forAccountId: self.account.id,
andContext: self.applicationState.accountData
) {
self.relationship = relationship
}
}
} catch {
ErrorService.shared.handle(error, message: "Muting/unmuting action failed.", showToastr: true)
}
}
private func onBlockAccount() async {
do {
if self.relationship?.blocking == true {
if let relationship = try await AccountService.shared.unblock(
forAccountId: self.account.id,
andContext: self.applicationState.accountData
) {
self.relationship = relationship
}
} else {
if let relationship = try await AccountService.shared.block(
forAccountId: self.account.id,
andContext: self.applicationState.accountData
) {
self.relationship = relationship
}
}
} catch {
ErrorService.shared.handle(error, message: "Block/unblock action failed.", showToastr: true)
}
}
}