Delete status.

This commit is contained in:
Marcin Czachursk 2023-02-18 20:59:21 +01:00
parent 66844a29b2
commit 8b800e10f0
7 changed files with 168 additions and 60 deletions

View File

@ -76,6 +76,26 @@ public extension MastodonClientAuthenticated {
return try await downloadJson(Status.self, request: request)
}
func pin(statusId: EntityId) async throws -> Status {
let request = try Self.request(
for: baseURL,
target: Mastodon.Statuses.pin(statusId),
withBearerToken: token
)
return try await downloadJson(Status.self, request: request)
}
func unpin(statusId: EntityId) async throws -> Status {
let request = try Self.request(
for: baseURL,
target: Mastodon.Statuses.unpin(statusId),
withBearerToken: token
)
return try await downloadJson(Status.self, request: request)
}
func new(statusComponents: Mastodon.Statuses.Components) async throws -> Status {
let request = try Self.request(
@ -85,4 +105,13 @@ public extension MastodonClientAuthenticated {
return try await downloadJson(Status.self, request: request)
}
func delete(statusId: EntityId) async throws {
let request = try Self.request(
for: baseURL,
target: Mastodon.Statuses.delete(statusId),
withBearerToken: token)
try await send(request: request)
}
}

View File

@ -97,6 +97,19 @@ public class MastodonClientAuthenticated: MastodonClientProtocol {
self.urlSession = urlSession
}
public func send(request: URLRequest) async throws {
let (data, response) = try await urlSession.data(for: request)
guard (response as? HTTPURLResponse)?.status?.responseType == .success else {
#if DEBUG
let json = String(data: data, encoding: .utf8)!
print(json)
#endif
throw NetworkError.notSuccessResponse(response)
}
}
public func downloadJson<T>(_ type: T.Type, request: URLRequest) async throws -> T where T: Decodable {
let (data, response) = try await urlSession.data(for: request)

View File

@ -14,19 +14,21 @@ extension Mastodon {
case pub = "public"
}
case status(String)
case context(String)
case card(String)
case status(EntityId)
case context(EntityId)
case card(EntityId)
case rebloggedBy(EntityId, MaxId?, SinceId?, MinId?, Limit?, Page?)
case favouritedBy(EntityId, MaxId?, SinceId?, MinId?, Limit?, Page?)
case new(Components)
case delete(String)
case reblog(String)
case unreblog(String)
case favourite(String)
case unfavourite(String)
case bookmark(String)
case unbookmark(String)
case delete(EntityId)
case reblog(EntityId)
case unreblog(EntityId)
case favourite(EntityId)
case unfavourite(EntityId)
case bookmark(EntityId)
case unbookmark(EntityId)
case pin(EntityId)
case unpin(EntityId)
}
}
@ -134,6 +136,10 @@ extension Mastodon.Statuses: TargetType {
return "\(apiPath)/\(id)/bookmark"
case .unbookmark(let id):
return "\(apiPath)/\(id)/unbookmark"
case .pin(let id):
return "\(apiPath)/\(id)/pin"
case .unpin(let id):
return "\(apiPath)/\(id)/unpin"
}
}
@ -146,7 +152,9 @@ extension Mastodon.Statuses: TargetType {
.favourite(_),
.unfavourite(_),
.bookmark(_),
.unbookmark(_):
.unbookmark(_),
.pin(_),
.unpin(_):
return .post
case .delete(_):
return .delete

View File

@ -23,6 +23,14 @@ extension Client {
return try await mastodonClient.unfavourite(statusId: statusId)
}
func pin(statusId: String) async throws -> Status? {
return try await mastodonClient.pin(statusId: statusId)
}
func unpin(statusId: String) async throws -> Status? {
return try await mastodonClient.unpin(statusId: statusId)
}
func boost(statusId: String) async throws -> Status? {
return try await mastodonClient.boost(statusId: statusId)
}
@ -43,6 +51,10 @@ extension Client {
return try await mastodonClient.new(statusComponents: status)
}
func delete(statusId: String) async throws {
try await mastodonClient.delete(statusId: statusId)
}
func comments(to statusId: String) async throws -> [CommentModel] {
var commentViewModels: [CommentModel] = []

View File

@ -48,7 +48,7 @@ struct ComposeView: View {
ScrollView {
VStack (alignment: .leading){
if self.isSensitive {
TextField("Content warning", text: $spoilerText)
TextField("Write content warning", text: $spoilerText)
.padding(8)
.focused($focusedField, equals: .spoilerText)
.keyboardType(.default)

View File

@ -108,9 +108,11 @@ struct StatusView: View {
.foregroundColor(.lightGrayColor)
.font(.footnote)
InteractionRow(statusViewModel: statusViewModel)
.foregroundColor(.accentColor)
.padding(8)
InteractionRow(statusViewModel: statusViewModel) {
self.dismiss()
}
.foregroundColor(.accentColor)
.padding(8)
}
.padding(8)
@ -172,7 +174,7 @@ struct StatusView: View {
if response.statusCode() == HTTPStatusCode.notFound, let accountId = self.applicationState.account?.id {
StatusDataHandler.shared.remove(accountId: accountId, statusId: self.statusId)
ErrorService.shared.handle(NetworkError.notSuccessResponse(response), message: "Status not existing anymore.", showToastr: true)
dismiss()
self.dismiss()
}
}
catch {

View File

@ -9,6 +9,8 @@ import MastodonKit
import Drops
struct InteractionRow: View {
typealias DeleteAction = () -> Void
@EnvironmentObject var applicationState: ApplicationState
@EnvironmentObject var client: Client
@EnvironmentObject var routerPath: RouterPath
@ -22,6 +24,13 @@ struct InteractionRow: View {
@State private var favouritesCount = 0
@State private var bookmarked = false
private let delete: DeleteAction?
public init(statusViewModel: StatusModel, delete: DeleteAction? = nil) {
self.statusViewModel = statusViewModel
self.delete = delete
}
var body: some View {
HStack (alignment: .top) {
ActionButton {
@ -37,23 +46,7 @@ struct InteractionRow: View {
Spacer()
ActionButton {
do {
let status = self.reblogged
? try await self.client.statuses?.unboost(statusId: self.statusViewModel.id)
: try await self.client.statuses?.boost(statusId: self.statusViewModel.id)
if let status {
self.reblogsCount = status.reblogsCount == self.reblogsCount
? status.reblogsCount + 1
: status.reblogsCount
self.reblogged = status.reblogged
}
ToastrService.shared.showSuccess("Reboosted", imageSystemName: "paperplane.fill")
} catch {
ErrorService.shared.handle(error, message: "Reboost action failed.", showToastr: true)
}
await self.reboost()
} label: {
HStack(alignment: .center) {
Image(systemName: self.reblogged ? "paperplane.fill" : "paperplane")
@ -65,23 +58,7 @@ struct InteractionRow: View {
Spacer()
ActionButton {
do {
let status = self.favourited
? try await self.client.statuses?.unfavourite(statusId: self.statusViewModel.id)
: try await self.client.statuses?.favourite(statusId: self.statusViewModel.id)
if let status {
self.favouritesCount = status.favouritesCount == self.favouritesCount
? status.favouritesCount + 1
: status.favouritesCount
self.favourited = status.favourited
}
ToastrService.shared.showSuccess("Favourited", imageSystemName: "hand.thumbsup.fill")
} catch {
ErrorService.shared.handle(error, message: "Favourite action failed.", showToastr: true)
}
await self.favourite()
} label: {
HStack(alignment: .center) {
Image(systemName: self.favourited ? "hand.thumbsup.fill" : "hand.thumbsup")
@ -93,16 +70,7 @@ struct InteractionRow: View {
Spacer()
ActionButton {
do {
_ = self.bookmarked
? try await self.client.statuses?.unbookmark(statusId: self.statusViewModel.id)
: try await self.client.statuses?.bookmark(statusId: self.statusViewModel.id)
self.bookmarked.toggle()
ToastrService.shared.showSuccess("Bookmarked", imageSystemName: "bookmark.fill")
} catch {
ErrorService.shared.handle(error, message: "Bookmark action failed.", showToastr: true)
}
await self.bookmark()
} label: {
Image(systemName: self.bookmarked ? "bookmark.fill" : "bookmark")
}
@ -129,6 +97,16 @@ struct InteractionRow: View {
Label("Share post", systemImage: "square.and.arrow.up")
}
}
if self.statusViewModel.account.id == self.applicationState.account?.id {
Section(header: Text("Your post")) {
Button(role: .destructive) {
self.deleteStatus()
} label: {
Label("Delete", systemImage: "trash")
}
}
}
} label: {
Image(systemName: "gear")
}
@ -148,4 +126,70 @@ struct InteractionRow: View {
self.favouritesCount = self.statusViewModel.favouritesCount
self.bookmarked = self.statusViewModel.bookmarked
}
private func reboost() async {
do {
let status = self.reblogged
? try await self.client.statuses?.unboost(statusId: self.statusViewModel.id)
: try await self.client.statuses?.boost(statusId: self.statusViewModel.id)
if let status {
self.reblogsCount = status.reblogsCount == self.reblogsCount
? status.reblogsCount + 1
: status.reblogsCount
self.reblogged = status.reblogged
}
ToastrService.shared.showSuccess(self.reblogged ? "Reboosted" : "Unreboosted", imageSystemName: "paperplane.fill")
} catch {
ErrorService.shared.handle(error, message: "Reboost action failed.", showToastr: true)
}
}
private func favourite() async {
do {
let status = self.favourited
? try await self.client.statuses?.unfavourite(statusId: self.statusViewModel.id)
: try await self.client.statuses?.favourite(statusId: self.statusViewModel.id)
if let status {
self.favouritesCount = status.favouritesCount == self.favouritesCount
? status.favouritesCount + 1
: status.favouritesCount
self.favourited = status.favourited
}
ToastrService.shared.showSuccess(self.favourited ? "Favourited" : "Unfavourited", imageSystemName: "hand.thumbsup.fill")
} catch {
ErrorService.shared.handle(error, message: "Favourite action failed.", showToastr: true)
}
}
private func bookmark() async {
do {
_ = self.bookmarked
? try await self.client.statuses?.unbookmark(statusId: self.statusViewModel.id)
: try await self.client.statuses?.bookmark(statusId: self.statusViewModel.id)
self.bookmarked.toggle()
ToastrService.shared.showSuccess(self.bookmarked ? "Bookmarked" : "Unbookmarked", imageSystemName: "bookmark.fill")
} catch {
ErrorService.shared.handle(error, message: "Bookmark action failed.", showToastr: true)
}
}
private func deleteStatus() {
Task {
do {
try await self.client.statuses?.delete(statusId: self.statusViewModel.id)
ToastrService.shared.showSuccess("Post deleted", imageSystemName: "checkmark.circle.fill")
self.delete?()
} catch {
ErrorService.shared.handle(error, message: "Delete action failed.", showToastr: true)
}
}
}
}