138 lines
5.0 KiB
Swift
138 lines
5.0 KiB
Swift
//
|
|
// https://mczachurski.dev
|
|
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
|
// Licensed under the Apache License 2.0.
|
|
//
|
|
|
|
import Foundation
|
|
import SwiftUI
|
|
import ClientKit
|
|
import ServicesKit
|
|
|
|
public extension View {
|
|
func imageContextMenu(statusModel: StatusModel, attachmentModel: AttachmentModel, uiImage: UIImage?) -> some View {
|
|
modifier(ImageContextMenu(id: statusModel.id, url: statusModel.url, altText: attachmentModel.description, uiImage: uiImage))
|
|
}
|
|
|
|
func imageContextMenu(statusData: StatusData, attachmentData: AttachmentData, uiImage: UIImage?) -> some View {
|
|
modifier(ImageContextMenu(id: statusData.id, url: statusData.url, altText: attachmentData.text, uiImage: uiImage))
|
|
}
|
|
}
|
|
|
|
private struct ImageContextMenu: ViewModifier {
|
|
@EnvironmentObject var client: Client
|
|
@EnvironmentObject var routerPath: RouterPath
|
|
|
|
private let id: String
|
|
private let url: URL?
|
|
private let altText: String?
|
|
private let uiImage: UIImage?
|
|
|
|
init(id: String, url: URL?, altText: String?, uiImage: UIImage?) {
|
|
self.id = id
|
|
self.url = url
|
|
self.altText = altText
|
|
self.uiImage = uiImage
|
|
}
|
|
|
|
func body(content: Content) -> some View {
|
|
ZStack(alignment: .trailing) {
|
|
content
|
|
.contextMenu {
|
|
Button {
|
|
Task {
|
|
await self.reboost()
|
|
}
|
|
} label: {
|
|
Label("status.title.reboost", image: "custom.rocket")
|
|
}
|
|
|
|
Button {
|
|
Task {
|
|
await self.favourite()
|
|
}
|
|
} label: {
|
|
Label("status.title.favourite", systemImage: "star")
|
|
}
|
|
|
|
Button {
|
|
Task {
|
|
await self.bookmark()
|
|
}
|
|
} label: {
|
|
Label("status.title.bookmark", systemImage: "bookmark")
|
|
}
|
|
|
|
Divider()
|
|
|
|
if let url = self.url {
|
|
Link(destination: url) {
|
|
Label("status.title.openInBrowser", systemImage: "safari")
|
|
}
|
|
|
|
ShareLink(item: url) {
|
|
Label("status.title.shareStatus", systemImage: "square.and.arrow.up")
|
|
}
|
|
}
|
|
|
|
Divider()
|
|
|
|
if let altText, altText.count > 0 {
|
|
Button {
|
|
self.routerPath.presentedAlert = .alternativeText(text: altText)
|
|
} label: {
|
|
Label("status.title.showMediaDescription", systemImage: "eye.trianglebadge.exclamationmark")
|
|
}
|
|
}
|
|
|
|
if let uiImage {
|
|
Button {
|
|
Task {
|
|
self.routerPath.presentedSheet = .shareImage(image: uiImage)
|
|
}
|
|
} label: {
|
|
Label("status.title.shareImage", systemImage: "photo")
|
|
}
|
|
|
|
Button {
|
|
let imageSaver = ImageSaver {
|
|
self.routerPath.presentedAlert = .savePhotoSuccess
|
|
}
|
|
|
|
imageSaver.writeToPhotoAlbum(image: uiImage)
|
|
} label: {
|
|
Label("status.title.saveImage", systemImage: "square.and.arrow.down")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private func reboost() async {
|
|
do {
|
|
_ = try await self.client.statuses?.boost(statusId: self.id)
|
|
ToastrService.shared.showSuccess(NSLocalizedString("status.title.reboosted", comment: "Reboosted"), imageName: "custom.rocket.fill")
|
|
} catch {
|
|
ErrorService.shared.handle(error, message: "status.error.reboostFailed", showToastr: true)
|
|
}
|
|
}
|
|
|
|
private func favourite() async {
|
|
do {
|
|
_ = try await self.client.statuses?.favourite(statusId: self.id)
|
|
ToastrService.shared.showSuccess(NSLocalizedString("status.title.favourited", comment: "Favourited"), imageSystemName: "star.fill")
|
|
} catch {
|
|
ErrorService.shared.handle(error, message: "status.error.favouriteFailed", showToastr: true)
|
|
}
|
|
}
|
|
|
|
private func bookmark() async {
|
|
do {
|
|
_ = try await self.client.statuses?.bookmark(statusId: self.id)
|
|
ToastrService.shared.showSuccess(NSLocalizedString("status.title.bookmarked", comment: "Bookmarked"), imageSystemName: "bookmark.fill")
|
|
} catch {
|
|
ErrorService.shared.handle(error, message: "status.error.bookmarkFailed", showToastr: true)
|
|
}
|
|
}
|
|
}
|