Share post as image close #885
This commit is contained in:
parent
dd2ebe5506
commit
ccc504fc6f
|
@ -7,6 +7,8 @@ import Lists
|
|||
import Status
|
||||
import SwiftUI
|
||||
import Timeline
|
||||
import LinkPresentation
|
||||
import Models
|
||||
|
||||
@MainActor
|
||||
extension View {
|
||||
|
@ -44,7 +46,7 @@ extension View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func withSheetDestinations(sheetDestinations: Binding<SheetDestinations?>) -> some View {
|
||||
sheet(item: sheetDestinations) { destination in
|
||||
switch destination {
|
||||
|
@ -92,10 +94,12 @@ extension View {
|
|||
case let .report(status):
|
||||
ReportView(status: status)
|
||||
.withEnvironments()
|
||||
case let .shareImage(image, status):
|
||||
ActivityView(image: image, status: status)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func withEnvironments() -> some View {
|
||||
environmentObject(CurrentAccount.shared)
|
||||
.environmentObject(UserPreferences.shared)
|
||||
|
@ -106,3 +110,42 @@ extension View {
|
|||
.environmentObject(AppAccountsManager.shared.currentClient)
|
||||
}
|
||||
}
|
||||
|
||||
struct ActivityView: UIViewControllerRepresentable {
|
||||
let image: UIImage
|
||||
let status: Status
|
||||
|
||||
class LinkDelegate: NSObject, UIActivityItemSource {
|
||||
let image: UIImage
|
||||
let status: Status
|
||||
|
||||
init(image: UIImage, status: Status) {
|
||||
self.image = image
|
||||
self.status = status
|
||||
}
|
||||
|
||||
func activityViewControllerLinkMetadata(_ activityViewController: UIActivityViewController) -> LPLinkMetadata? {
|
||||
let imageProvider = NSItemProvider(object: image)
|
||||
let metadata = LPLinkMetadata()
|
||||
metadata.imageProvider = imageProvider
|
||||
metadata.title = status.reblog?.content.asRawText ?? status.content.asRawText
|
||||
return metadata
|
||||
}
|
||||
|
||||
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
|
||||
image
|
||||
}
|
||||
|
||||
func activityViewController(_ activityViewController: UIActivityViewController,
|
||||
itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
|
||||
nil
|
||||
}
|
||||
}
|
||||
|
||||
func makeUIViewController(context: UIViewControllerRepresentableContext<ActivityView>) -> UIActivityViewController {
|
||||
return UIActivityViewController(activityItems: [image, LinkDelegate(image: image, status: status)],
|
||||
applicationActivities: nil)
|
||||
}
|
||||
|
||||
func updateUIViewController(_ uiViewController: UIActivityViewController, context: UIViewControllerRepresentableContext<ActivityView>) {}
|
||||
}
|
||||
|
|
|
@ -372,6 +372,9 @@
|
|||
"status.action.reply" = "Адказаць";
|
||||
"status.action.section.your-post" = "Ваш допіс";
|
||||
"status.action.share" = "Падзяліцца гэтым допісам";
|
||||
"status.action.share-link" = "Share post link";
|
||||
"status.action.share-image" = "Share post as image";
|
||||
"status.action.share-title" = "Share";
|
||||
"status.action.unbookmark" = "Скасаваць закладку";
|
||||
"status.action.unboost" = "Адмяніць павышэнне";
|
||||
"status.action.unfavorite" = "Выдаліць з улюбенага";
|
||||
|
|
|
@ -382,6 +382,9 @@
|
|||
"status.action.reply" = "Respon";
|
||||
"status.action.section.your-post" = "La vostra publicació";
|
||||
"status.action.share" = "Comparteix la publicació";
|
||||
"status.action.share-link" = "Share post link";
|
||||
"status.action.share-image" = "Share post as image";
|
||||
"status.action.share-title" = "Share";
|
||||
"status.action.unbookmark" = "Elimina dels marcadors";
|
||||
"status.action.unboost" = "Desfés l'impulsa";
|
||||
"status.action.unfavorite" = "Desfés el preferit";
|
||||
|
|
|
@ -379,6 +379,9 @@
|
|||
"status.action.reply" = "Antworten";
|
||||
"status.action.section.your-post" = "Dein Beitrag";
|
||||
"status.action.share" = "Diesen Beitrag teilen";
|
||||
"status.action.share-link" = "Share post link";
|
||||
"status.action.share-image" = "Share post as image";
|
||||
"status.action.share-title" = "Share";
|
||||
"status.action.unbookmark" = "Lesezeichen entfernen";
|
||||
"status.action.unboost" = "Boost entfernen";
|
||||
"status.action.unfavorite" = "Favorit entfernen";
|
||||
|
|
|
@ -385,6 +385,9 @@
|
|||
"status.action.reply" = "Reply";
|
||||
"status.action.section.your-post" = "Your post";
|
||||
"status.action.share" = "Share this post";
|
||||
"status.action.share-link" = "Share post link";
|
||||
"status.action.share-image" = "Share post as image";
|
||||
"status.action.share-title" = "Share";
|
||||
"status.action.unbookmark" = "Unbookmark";
|
||||
"status.action.unboost" = "Unboost";
|
||||
"status.action.unfavorite" = "Unfavourite";
|
||||
|
|
|
@ -384,6 +384,9 @@
|
|||
"status.action.reply" = "Reply";
|
||||
"status.action.section.your-post" = "Your post";
|
||||
"status.action.share" = "Share this post";
|
||||
"status.action.share-link" = "Share post link";
|
||||
"status.action.share-image" = "Share post as image";
|
||||
"status.action.share-title" = "Share";
|
||||
"status.action.unbookmark" = "Unbookmark";
|
||||
"status.action.unboost" = "Unboost";
|
||||
"status.action.unfavorite" = "Unfavorite";
|
||||
|
|
|
@ -384,6 +384,9 @@
|
|||
"status.action.reply" = "Responder";
|
||||
"status.action.section.your-post" = "Tus publicaciones";
|
||||
"status.action.share" = "Compartir esta publicación";
|
||||
"status.action.share-link" = "Share post link";
|
||||
"status.action.share-image" = "Share post as image";
|
||||
"status.action.share-title" = "Share";
|
||||
"status.action.unbookmark" = "Quitar de marcadores";
|
||||
"status.action.unboost" = "Deshacer Retoot";
|
||||
"status.action.unfavorite" = "Eliminar de favoritos";
|
||||
|
|
|
@ -377,6 +377,9 @@
|
|||
"status.action.reply" = "Erantzun";
|
||||
"status.action.section.your-post" = "Zure bidalketa";
|
||||
"status.action.share" = "Partekatu bidalketa";
|
||||
"status.action.share-link" = "Share post link";
|
||||
"status.action.share-image" = "Share post as image";
|
||||
"status.action.share-title" = "Share";
|
||||
"status.action.unbookmark" = "Kendu laster-marka";
|
||||
"status.action.unboost" = "Kendu bultzada";
|
||||
"status.action.unfavorite" = "Kendu gogokoa";
|
||||
|
|
|
@ -379,6 +379,9 @@
|
|||
"status.action.reply" = "Répondre";
|
||||
"status.action.section.your-post" = "Votre publication";
|
||||
"status.action.share" = "Partager cette publication";
|
||||
"status.action.share-link" = "Partager le lien";
|
||||
"status.action.share-image" = "Partager comme image";
|
||||
"status.action.share-title" = "Partager";
|
||||
"status.action.unbookmark" = "Démarquer";
|
||||
"status.action.unboost" = "Annuler la promotion";
|
||||
"status.action.unfavorite" = "Retirer des favoris";
|
||||
|
|
|
@ -384,6 +384,9 @@
|
|||
"status.action.reply" = "Rispondi";
|
||||
"status.action.section.your-post" = "I tuoi post";
|
||||
"status.action.share" = "Condividi questo post";
|
||||
"status.action.share-link" = "Share post link";
|
||||
"status.action.share-image" = "Share post as image";
|
||||
"status.action.share-title" = "Share";
|
||||
"status.action.unbookmark" = "Rimuovi il segnalibro";
|
||||
"status.action.unboost" = "Rimuovi la condivisione";
|
||||
"status.action.unfavorite" = "Rimuovi l'apprezzamento";
|
||||
|
|
|
@ -383,6 +383,9 @@
|
|||
"status.action.reply" = "リプライ";
|
||||
"status.action.section.your-post" = "あなたの投稿";
|
||||
"status.action.share" = "投稿を共有する";
|
||||
"status.action.share-link" = "Share post link";
|
||||
"status.action.share-image" = "Share post as image";
|
||||
"status.action.share-title" = "Share";
|
||||
"status.action.unbookmark" = "ブックマークを外す";
|
||||
"status.action.unboost" = "ブーストをやめる";
|
||||
"status.action.unfavorite" = "お気に入りから外す";
|
||||
|
|
|
@ -385,6 +385,9 @@
|
|||
"status.action.reply" = "댓글";
|
||||
"status.action.section.your-post" = "내 글";
|
||||
"status.action.share" = "공유";
|
||||
"status.action.share-link" = "Share post link";
|
||||
"status.action.share-image" = "Share post as image";
|
||||
"status.action.share-title" = "Share";
|
||||
"status.action.unbookmark" = "보관함에서 제거";
|
||||
"status.action.unboost" = "부스트 취소";
|
||||
"status.action.unfavorite" = "좋아요 취소";
|
||||
|
|
|
@ -383,6 +383,9 @@
|
|||
"status.action.reply" = "Svar";
|
||||
"status.action.section.your-post" = "Ditt innlegg";
|
||||
"status.action.share" = "Del dette innlegget";
|
||||
"status.action.share-link" = "Share post link";
|
||||
"status.action.share-image" = "Share post as image";
|
||||
"status.action.share-title" = "Share";
|
||||
"status.action.unbookmark" = "Fjern bokmerke";
|
||||
"status.action.unboost" = "Opphev forsterkningen";
|
||||
"status.action.unfavorite" = "Ikke favoritt";
|
||||
|
|
|
@ -377,6 +377,9 @@
|
|||
"status.action.reply" = "Antwoord";
|
||||
"status.action.section.your-post" = "Jouw post";
|
||||
"status.action.share" = "Deel deze post";
|
||||
"status.action.share-link" = "Share post link";
|
||||
"status.action.share-image" = "Share post as image";
|
||||
"status.action.share-title" = "Share";
|
||||
"status.action.unbookmark" = "Verwijder bladwijzer";
|
||||
"status.action.unboost" = "Maak boost ongedaan";
|
||||
"status.action.unfavorite" = "Verwijder favoriet";
|
||||
|
|
|
@ -379,6 +379,9 @@
|
|||
"status.action.reply" = "Odpowiedz";
|
||||
"status.action.section.your-post" = "Twój post";
|
||||
"status.action.share" = "Udostępnij ten post";
|
||||
"status.action.share-link" = "Share post link";
|
||||
"status.action.share-image" = "Share post as image";
|
||||
"status.action.share-title" = "Share";
|
||||
"status.action.unbookmark" = "Usuń zakładkę";
|
||||
"status.action.unboost" = "Cofnij podbicie";
|
||||
"status.action.unfavorite" = "Usuń z polubionych";
|
||||
|
|
|
@ -383,6 +383,9 @@
|
|||
"status.action.reply" = "Responder";
|
||||
"status.action.section.your-post" = "Sua postagem";
|
||||
"status.action.share" = "Compartilhe esta postagem";
|
||||
"status.action.share-link" = "Share post link";
|
||||
"status.action.share-image" = "Share post as image";
|
||||
"status.action.share-title" = "Share";
|
||||
"status.action.unbookmark" = "Remover dos salvos";
|
||||
"status.action.unboost" = "Unboost";
|
||||
"status.action.unfavorite" = "Desfavoritar";
|
||||
|
|
|
@ -379,6 +379,9 @@
|
|||
"status.action.reply" = "Cevapla";
|
||||
"status.action.section.your-post" = "Senin gönderin";
|
||||
"status.action.share" = "Bu gönderiyi paylaş";
|
||||
"status.action.share-link" = "Share post link";
|
||||
"status.action.share-image" = "Share post as image";
|
||||
"status.action.share-title" = "Share";
|
||||
"status.action.unbookmark" = "Yer İmini Kaldır";
|
||||
"status.action.unboost" = "Yükseltmeyi Kaldır";
|
||||
"status.action.unfavorite" = "Favoriyi Kaldır";
|
||||
|
|
|
@ -384,6 +384,9 @@
|
|||
"status.action.reply" = "回复";
|
||||
"status.action.section.your-post" = "你的嘟文";
|
||||
"status.action.share" = "分享嘟文";
|
||||
"status.action.share-link" = "Share post link";
|
||||
"status.action.share-image" = "Share post as image";
|
||||
"status.action.share-title" = "Share";
|
||||
"status.action.unbookmark" = "取消书签";
|
||||
"status.action.unboost" = "取消转发";
|
||||
"status.action.unfavorite" = "取消收藏";
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import NukeUI
|
||||
import Nuke
|
||||
import Shimmer
|
||||
import SwiftUI
|
||||
|
||||
public struct AvatarView: View {
|
||||
@Environment(\.isInCaptureMode) private var isInCaptureMode: Bool
|
||||
@Environment(\.redactionReasons) private var reasons
|
||||
@EnvironmentObject private var theme: Theme
|
||||
|
||||
|
@ -54,16 +56,24 @@ public struct AvatarView: View {
|
|||
.fill(.gray)
|
||||
.frame(width: size.size.width, height: size.size.height)
|
||||
} else {
|
||||
LazyImage(url: url) { state in
|
||||
if let image = state.image {
|
||||
image
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
} else {
|
||||
placeholderView
|
||||
if isInCaptureMode, let image = Nuke.ImagePipeline.shared.cache.cachedImage(for: .init(url: url))?.image {
|
||||
Image(uiImage: image)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: size.size.width, height: size.size.height)
|
||||
} else {
|
||||
LazyImage(url: url) { state in
|
||||
if let image = state.image {
|
||||
image
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
} else {
|
||||
placeholderView
|
||||
}
|
||||
}
|
||||
.animation(nil)
|
||||
.frame(width: size.size.width, height: size.size.height)
|
||||
}
|
||||
.frame(width: size.size.width, height: size.size.height)
|
||||
}
|
||||
}
|
||||
.clipShape(clipShape)
|
||||
|
|
|
@ -13,6 +13,10 @@ private struct IsCompact: EnvironmentKey {
|
|||
static let defaultValue: Bool = false
|
||||
}
|
||||
|
||||
private struct IsInCaptureMode: EnvironmentKey {
|
||||
static let defaultValue: Bool = false
|
||||
}
|
||||
|
||||
public extension EnvironmentValues {
|
||||
var isSecondaryColumn: Bool {
|
||||
get { self[SecondaryColumnKey.self] }
|
||||
|
@ -28,4 +32,9 @@ public extension EnvironmentValues {
|
|||
get { self[IsCompact.self] }
|
||||
set { self[IsCompact.self] = newValue }
|
||||
}
|
||||
|
||||
var isInCaptureMode: Bool {
|
||||
get { self[IsInCaptureMode.self] }
|
||||
set { self[IsInCaptureMode.self] = newValue }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ public enum SheetDestinations: Identifiable {
|
|||
case settings
|
||||
case accountPushNotficationsSettings
|
||||
case report(status: Status)
|
||||
case shareImage(image: UIImage, status: Status)
|
||||
|
||||
public var id: String {
|
||||
switch self {
|
||||
|
@ -52,6 +53,8 @@ public enum SheetDestinations: Identifiable {
|
|||
return "statusEditHistory"
|
||||
case .report:
|
||||
return "report"
|
||||
case .shareImage:
|
||||
return "shareImage"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
import DesignSystem
|
||||
import Models
|
||||
import Nuke
|
||||
import NukeUI
|
||||
import Shimmer
|
||||
import SwiftUI
|
||||
|
||||
public struct StatusRowCardView: View {
|
||||
@EnvironmentObject private var theme: Theme
|
||||
@Environment(\.openURL) private var openURL
|
||||
@Environment(\.isInCaptureMode) private var isInCaptureMode: Bool
|
||||
|
||||
@EnvironmentObject private var theme: Theme
|
||||
let card: Card
|
||||
|
||||
public init(card: Card) {
|
||||
|
@ -16,8 +19,10 @@ public struct StatusRowCardView: View {
|
|||
public var body: some View {
|
||||
if let title = card.title, let url = URL(string: card.url) {
|
||||
VStack(alignment: .leading) {
|
||||
if let imageURL = card.image {
|
||||
if let imageURL = card.image, !isInCaptureMode {
|
||||
GeometryReader { proxy in
|
||||
let processors: [ImageProcessing] = [.resize(size: .init(width: proxy.frame(in: .local).width,
|
||||
height: 200))]
|
||||
LazyImage(url: imageURL) { state in
|
||||
if let image = state.image {
|
||||
image
|
||||
|
@ -32,6 +37,7 @@ public struct StatusRowCardView: View {
|
|||
.frame(height: 200)
|
||||
}
|
||||
}
|
||||
.processors(processors)
|
||||
}
|
||||
.frame(height: 200)
|
||||
}
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
import Env
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import DesignSystem
|
||||
import Network
|
||||
|
||||
struct StatusRowContextMenu: View {
|
||||
@Environment(\.displayScale) var displayScale
|
||||
|
||||
@EnvironmentObject private var sceneDelegate: SceneDelegate
|
||||
@EnvironmentObject private var preferences: UserPreferences
|
||||
@EnvironmentObject private var account: CurrentAccount
|
||||
@EnvironmentObject private var currentInstance: CurrentInstance
|
||||
|
||||
@ObservedObject var viewModel: StatusRowViewModel
|
||||
|
||||
|
||||
var body: some View {
|
||||
if !viewModel.isRemote {
|
||||
Button { Task {
|
||||
|
@ -56,13 +61,45 @@ struct StatusRowContextMenu: View {
|
|||
|
||||
Divider()
|
||||
|
||||
if let urlString = viewModel.status.reblog?.url ?? viewModel.status.url,
|
||||
let url = URL(string: urlString)
|
||||
{
|
||||
ShareLink(item: url,
|
||||
subject: Text(viewModel.status.reblog?.account.safeDisplayName ?? viewModel.status.account.safeDisplayName),
|
||||
message: Text(viewModel.status.reblog?.content.asRawText ?? viewModel.status.content.asRawText)) {
|
||||
Label("status.action.share", systemImage: "square.and.arrow.up")
|
||||
Menu("status.action.share-title") {
|
||||
if let urlString = viewModel.status.reblog?.url ?? viewModel.status.url,
|
||||
let url = URL(string: urlString)
|
||||
{
|
||||
ShareLink(item: url,
|
||||
subject: Text(viewModel.status.reblog?.account.safeDisplayName ?? viewModel.status.account.safeDisplayName),
|
||||
message: Text(viewModel.status.reblog?.content.asRawText ?? viewModel.status.content.asRawText)) {
|
||||
Label("status.action.share", systemImage: "square.and.arrow.up")
|
||||
}
|
||||
|
||||
ShareLink(item: url) {
|
||||
Label("status.action.share-link", systemImage: "link")
|
||||
}
|
||||
|
||||
Button {
|
||||
let view = HStack {
|
||||
StatusRowView(viewModel: viewModel)
|
||||
.padding(16)
|
||||
}
|
||||
.environment(\.isInCaptureMode, true)
|
||||
.environmentObject(Theme.shared)
|
||||
.environmentObject(preferences)
|
||||
.environmentObject(account)
|
||||
.environmentObject(currentInstance)
|
||||
.environmentObject(SceneDelegate())
|
||||
.environmentObject(QuickLook())
|
||||
.environmentObject(viewModel.client)
|
||||
.preferredColorScheme(Theme.shared.selectedScheme == .dark ? .dark : .light)
|
||||
.background(Theme.shared.primaryBackgroundColor)
|
||||
.cornerRadius(4)
|
||||
.frame(width: sceneDelegate.windowWidth)
|
||||
let renderer = ImageRenderer(content: view)
|
||||
renderer.scale = displayScale
|
||||
if let image = renderer.uiImage {
|
||||
viewModel.routerPath.presentedSheet = .shareImage(image: image, status: viewModel.status)
|
||||
}
|
||||
} label: {
|
||||
Label("status.action.share-image", systemImage: "photo")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,3 +181,13 @@ struct StatusRowContextMenu: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ActivityView: UIViewControllerRepresentable {
|
||||
let image: Image
|
||||
|
||||
func makeUIViewController(context: UIViewControllerRepresentableContext<ActivityView>) -> UIActivityViewController {
|
||||
return UIActivityViewController(activityItems: [image], applicationActivities: nil)
|
||||
}
|
||||
|
||||
func updateUIViewController(_ uiViewController: UIActivityViewController, context: UIViewControllerRepresentableContext<ActivityView>) {}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import Models
|
|||
import SwiftUI
|
||||
|
||||
struct StatusRowHeaderView: View {
|
||||
@Environment(\.isInCaptureMode) private var isInCaptureMode: Bool
|
||||
@EnvironmentObject private var theme: Theme
|
||||
|
||||
let status: AnyStatus
|
||||
|
@ -17,8 +18,10 @@ struct StatusRowHeaderView: View {
|
|||
}
|
||||
.buttonStyle(.plain)
|
||||
Spacer()
|
||||
threadIcon
|
||||
contextMenuButton
|
||||
if !isInCaptureMode {
|
||||
threadIcon
|
||||
contextMenuButton
|
||||
}
|
||||
}
|
||||
.accessibilityElement()
|
||||
.accessibilityLabel(Text("\(status.account.displayName)"))
|
||||
|
|
|
@ -7,8 +7,9 @@ import SwiftUI
|
|||
|
||||
public struct StatusRowMediaPreviewView: View {
|
||||
@Environment(\.openURL) private var openURL
|
||||
@Environment(\.isSecondaryColumn) private var isSecondaryColumn
|
||||
@Environment(\.isSecondaryColumn) private var isSecondaryColumn: Bool
|
||||
@Environment(\.extraLeadingInset) private var extraLeadingInset: CGFloat
|
||||
@Environment(\.isInCaptureMode) private var isInCaptureMode: Bool
|
||||
|
||||
@EnvironmentObject var sceneDelegate: SceneDelegate
|
||||
@EnvironmentObject private var preferences: UserPreferences
|
||||
|
@ -150,24 +151,36 @@ public struct StatusRowMediaPreviewView: View {
|
|||
let size: CGSize = size(for: attachment) ?? .init(width: imageMaxHeight, height: imageMaxHeight)
|
||||
let newSize = imageSize(from: size,
|
||||
newWidth: availableWidth - appLayoutWidth)
|
||||
let processors: [ImageProcessing] = [.resize(size: .init(width: newSize.width, height: newSize.height))]
|
||||
switch attachment.supportedType {
|
||||
case .image:
|
||||
LazyImage(url: attachment.url) { state in
|
||||
if let image = state.image {
|
||||
image
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: newSize.width, height: newSize.height)
|
||||
.clipped()
|
||||
.cornerRadius(4)
|
||||
} else {
|
||||
RoundedRectangle(cornerRadius: 4)
|
||||
.fill(Color.gray)
|
||||
.frame(width: newSize.width, height: newSize.height)
|
||||
if isInCaptureMode,
|
||||
let image = Nuke.ImagePipeline.shared.cache.cachedImage(for: .init(url: attachment.url,
|
||||
processors: processors))?.image {
|
||||
Image(uiImage: image)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: newSize.width, height: newSize.height)
|
||||
.clipped()
|
||||
.cornerRadius(4)
|
||||
} else {
|
||||
LazyImage(url: attachment.url) { state in
|
||||
if let image = state.image {
|
||||
image
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: newSize.width, height: newSize.height)
|
||||
.clipped()
|
||||
.cornerRadius(4)
|
||||
} else {
|
||||
RoundedRectangle(cornerRadius: 4)
|
||||
.fill(Color.gray)
|
||||
.frame(width: newSize.width, height: newSize.height)
|
||||
}
|
||||
}
|
||||
.processors([.resize(size: .init(width: newSize.width, height: newSize.height))])
|
||||
.frame(width: newSize.width, height: newSize.height)
|
||||
}
|
||||
.processors([.resize(size: .init(width: newSize.width, height: newSize.height))])
|
||||
.frame(width: newSize.width, height: newSize.height)
|
||||
|
||||
case .gifv, .video, .audio:
|
||||
if let url = attachment.url {
|
||||
|
@ -177,10 +190,10 @@ public struct StatusRowMediaPreviewView: View {
|
|||
case .none:
|
||||
EmptyView()
|
||||
}
|
||||
if sensitive {
|
||||
if !isInCaptureMode, sensitive {
|
||||
cornerSensitiveButton
|
||||
}
|
||||
if let alt = attachment.description, !alt.isEmpty, !isNotifications, preferences.showAltTextForMedia {
|
||||
if !isInCaptureMode, let alt = attachment.description, !alt.isEmpty, !isNotifications, preferences.showAltTextForMedia {
|
||||
Group {
|
||||
Button {
|
||||
altTextDisplayed = alt
|
||||
|
@ -207,28 +220,44 @@ public struct StatusRowMediaPreviewView: View {
|
|||
switch type {
|
||||
case .image:
|
||||
let width = isNotifications ? imageMaxHeight : proxy.frame(in: .local).width
|
||||
let processors: [ImageProcessing] = [.resize(size: .init(width: width, height: imageMaxHeight))]
|
||||
ZStack(alignment: .bottomTrailing) {
|
||||
LazyImage(url: attachment.previewUrl ?? attachment.url) { state in
|
||||
if let image = state.image {
|
||||
image
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(maxWidth: width)
|
||||
.frame(maxHeight: imageMaxHeight)
|
||||
.clipped()
|
||||
.cornerRadius(4)
|
||||
} else if state.isLoading {
|
||||
RoundedRectangle(cornerRadius: 4)
|
||||
.fill(Color.gray)
|
||||
.frame(maxHeight: imageMaxHeight)
|
||||
.frame(maxWidth: width)
|
||||
if isInCaptureMode,
|
||||
let image = Nuke.ImagePipeline.shared.cache.cachedImage(for: .init(url: attachment.previewUrl ?? attachment.url, processors: processors))?.image {
|
||||
Image(uiImage: image)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(maxWidth: width)
|
||||
.frame(maxHeight: imageMaxHeight)
|
||||
.clipped()
|
||||
.cornerRadius(4)
|
||||
} else {
|
||||
LazyImage(url: attachment.previewUrl ?? attachment.url) { state in
|
||||
if let image = state.image {
|
||||
image
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(maxWidth: width)
|
||||
.frame(maxHeight: imageMaxHeight)
|
||||
.clipped()
|
||||
.cornerRadius(4)
|
||||
} else if state.isLoading {
|
||||
RoundedRectangle(cornerRadius: 4)
|
||||
.fill(Color.gray)
|
||||
.frame(maxHeight: imageMaxHeight)
|
||||
.frame(maxWidth: width)
|
||||
}
|
||||
}
|
||||
.processors(processors)
|
||||
}
|
||||
.processors([.resize(size: .init(width: width, height: imageMaxHeight))])
|
||||
if sensitive {
|
||||
if sensitive, !isInCaptureMode {
|
||||
cornerSensitiveButton
|
||||
}
|
||||
if let alt = attachment.description, !alt.isEmpty, !isNotifications, preferences.showAltTextForMedia {
|
||||
if !isInCaptureMode,
|
||||
let alt = attachment.description,
|
||||
!alt.isEmpty,
|
||||
!isNotifications,
|
||||
preferences.showAltTextForMedia {
|
||||
Button {
|
||||
altTextDisplayed = alt
|
||||
isAltAlertDisplayed = true
|
||||
|
|
Loading…
Reference in New Issue