forked from shadowfacts/Tusker
Extract compose image into separate view
This commit is contained in:
parent
948c792e5d
commit
30ef9cc6d0
|
@ -308,6 +308,7 @@
|
|||
D6D4DDDA212518A200E1C4BB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D6D4DDD8212518A200E1C4BB /* LaunchScreen.storyboard */; };
|
||||
D6D4DDE5212518A200E1C4BB /* TuskerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D4DDE4212518A200E1C4BB /* TuskerTests.swift */; };
|
||||
D6D4DDF0212518A200E1C4BB /* TuskerUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D4DDEF212518A200E1C4BB /* TuskerUITests.swift */; };
|
||||
D6DD2A3F273C1F4900386A6C /* ComposeAttachmentImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DD2A3E273C1F4900386A6C /* ComposeAttachmentImage.swift */; };
|
||||
D6DD353D22F28CD000A9563A /* ContentWarningCopyMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DD353C22F28CD000A9563A /* ContentWarningCopyMode.swift */; };
|
||||
D6DD353F22F502EC00A9563A /* Preferences+Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DD353E22F502EC00A9563A /* Preferences+Notification.swift */; };
|
||||
D6DEA0DE268400C300FE896A /* ConfirmLoadMoreTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DEA0DC268400C300FE896A /* ConfirmLoadMoreTableViewCell.swift */; };
|
||||
|
@ -719,6 +720,7 @@
|
|||
D6D4DDEB212518A200E1C4BB /* TuskerUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TuskerUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D6D4DDEF212518A200E1C4BB /* TuskerUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TuskerUITests.swift; sourceTree = "<group>"; };
|
||||
D6D4DDF1212518A200E1C4BB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
D6DD2A3E273C1F4900386A6C /* ComposeAttachmentImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeAttachmentImage.swift; sourceTree = "<group>"; };
|
||||
D6DD353C22F28CD000A9563A /* ContentWarningCopyMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentWarningCopyMode.swift; sourceTree = "<group>"; };
|
||||
D6DD353E22F502EC00A9563A /* Preferences+Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Preferences+Notification.swift"; sourceTree = "<group>"; };
|
||||
D6DEA0DC268400C300FE896A /* ConfirmLoadMoreTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmLoadMoreTableViewCell.swift; sourceTree = "<group>"; };
|
||||
|
@ -1170,6 +1172,7 @@
|
|||
D662AEF1263A4BE10082A153 /* ComposePollView.swift */,
|
||||
D622757324EDF1CD00B82A16 /* ComposeAttachmentsList.swift */,
|
||||
D622757924EE21D900B82A16 /* ComposeAttachmentRow.swift */,
|
||||
D6DD2A3E273C1F4900386A6C /* ComposeAttachmentImage.swift */,
|
||||
D622757724EE133700B82A16 /* ComposeAssetPicker.swift */,
|
||||
D62275A524F1C81800B82A16 /* ComposeReplyView.swift */,
|
||||
D62275A724F1CA2800B82A16 /* ComposeReplyContentView.swift */,
|
||||
|
@ -2187,6 +2190,7 @@
|
|||
D6BED174212667E900F02DA0 /* TimelineStatusTableViewCell.swift in Sources */,
|
||||
D69693F42585941A00F4E116 /* UIWindowSceneDelegate+Close.swift in Sources */,
|
||||
D6C143DA253510F4007DC240 /* ComposeEmojiTextField.swift in Sources */,
|
||||
D6DD2A3F273C1F4900386A6C /* ComposeAttachmentImage.swift in Sources */,
|
||||
0427033822B30F5F000D31B6 /* BehaviorPrefsView.swift in Sources */,
|
||||
D627943923A553B600D38C68 /* UnbookmarkStatusActivity.swift in Sources */,
|
||||
D64D0AAD2128D88B005A6F37 /* LocalData.swift in Sources */,
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
//
|
||||
// ComposeAttachmentImage.swift
|
||||
// Tusker
|
||||
//
|
||||
// Created by Shadowfacts on 11/10/21.
|
||||
// Copyright © 2021 Shadowfacts. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Photos
|
||||
|
||||
struct ComposeAttachmentImage: View {
|
||||
let attachment: CompositionAttachment
|
||||
let fullSize: Bool
|
||||
|
||||
@State private var image: UIImage? = nil
|
||||
@State private var imageContentMode: ContentMode = .fill
|
||||
@State private var imageBackgroundColor: Color = .black
|
||||
|
||||
@Environment(\.colorScheme) private var colorScheme: ColorScheme
|
||||
|
||||
var body: some View {
|
||||
if let image = image {
|
||||
Image(uiImage: image)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: imageContentMode)
|
||||
.background(imageBackgroundColor)
|
||||
} else {
|
||||
Image(systemName: placeholderImageName)
|
||||
.onAppear(perform: self.loadImage)
|
||||
}
|
||||
}
|
||||
|
||||
private var placeholderImageName: String {
|
||||
switch colorScheme {
|
||||
case .light:
|
||||
return "photo"
|
||||
case .dark:
|
||||
return "photo.fill"
|
||||
@unknown default:
|
||||
return "photo"
|
||||
}
|
||||
}
|
||||
|
||||
private func loadImage() {
|
||||
switch attachment.data {
|
||||
case let .image(image):
|
||||
self.image = image
|
||||
case let .asset(asset):
|
||||
let size: CGSize
|
||||
if fullSize {
|
||||
size = PHImageManagerMaximumSize
|
||||
} else {
|
||||
// currently only used as thumbnail in ComposeAttachmentRow
|
||||
size = CGSize(width: 80, height: 80)
|
||||
}
|
||||
PHImageManager.default().requestImage(for: asset, targetSize: size, contentMode: .aspectFill, options: nil) { (image, _) in
|
||||
DispatchQueue.main.async {
|
||||
self.image = image
|
||||
}
|
||||
}
|
||||
case let .video(url):
|
||||
let asset = AVURLAsset(url: url)
|
||||
let imageGenerator = AVAssetImageGenerator(asset: asset)
|
||||
if let cgImage = try? imageGenerator.copyCGImage(at: .zero, actualTime: nil) {
|
||||
self.image = UIImage(cgImage: cgImage)
|
||||
}
|
||||
case let .drawing(drawing):
|
||||
image = drawing.imageInLightMode(from: drawing.bounds)
|
||||
imageContentMode = .fit
|
||||
imageBackgroundColor = .white
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ComposeAttachmentImage_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ComposeAttachmentImage(attachment: CompositionAttachment(data: .image(UIImage())), fullSize: false)
|
||||
}
|
||||
}
|
|
@ -18,17 +18,12 @@ struct ComposeAttachmentRow: View {
|
|||
|
||||
@EnvironmentObject var uiState: ComposeUIState
|
||||
@State private var mode: Mode = .allowEntry
|
||||
@State private var image: UIImage? = nil
|
||||
@State private var imageContentMode: ContentMode = .fill
|
||||
@State private var imageBackgroundColor: Color = .black
|
||||
@State private var isShowingTextRecognitionFailedAlert = false
|
||||
@State private var textRecognitionErrorMessage: String? = nil
|
||||
|
||||
@Environment(\.colorScheme) private var colorScheme: ColorScheme
|
||||
|
||||
var body: some View {
|
||||
HStack(alignment: .center, spacing: 4) {
|
||||
imageView
|
||||
ComposeAttachmentImage(attachment: attachment, fullSize: false)
|
||||
.frame(width: 80, height: 80)
|
||||
.cornerRadius(8)
|
||||
.contextMenu {
|
||||
|
@ -71,7 +66,6 @@ struct ComposeAttachmentRow: View {
|
|||
// .foregroundColor(.blue)
|
||||
// }
|
||||
}
|
||||
.onAppear(perform: self.loadImage)
|
||||
.onReceive(attachment.$attachmentDescription) { (newDesc) in
|
||||
if newDesc.isEmpty {
|
||||
uiState.attachmentsMissingDescriptions.insert(attachment.id)
|
||||
|
@ -88,53 +82,6 @@ struct ComposeAttachmentRow: View {
|
|||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var imageView: some View {
|
||||
if let image = image {
|
||||
Image(uiImage: image)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: imageContentMode)
|
||||
.background(imageBackgroundColor)
|
||||
} else {
|
||||
Image(systemName: placeholderImageName)
|
||||
}
|
||||
}
|
||||
|
||||
private var placeholderImageName: String {
|
||||
switch colorScheme {
|
||||
case .dark:
|
||||
return "photo.fill"
|
||||
case .light:
|
||||
return "photo"
|
||||
@unknown default:
|
||||
return "photo"
|
||||
}
|
||||
}
|
||||
|
||||
private func loadImage() {
|
||||
switch attachment.data {
|
||||
case let .image(image):
|
||||
self.image = image
|
||||
case let .asset(asset):
|
||||
let size = CGSize(width: 80, height: 80)
|
||||
PHImageManager.default().requestImage(for: asset, targetSize: size, contentMode: .aspectFill, options: nil) { (image, _) in
|
||||
DispatchQueue.main.async {
|
||||
self.image = image
|
||||
}
|
||||
}
|
||||
case let .video(url):
|
||||
let asset = AVURLAsset(url: url)
|
||||
let imageGenerator = AVAssetImageGenerator(asset: asset)
|
||||
if let cgImage = try? imageGenerator.copyCGImage(at: .zero, actualTime: nil) {
|
||||
self.image = UIImage(cgImage: cgImage)
|
||||
}
|
||||
case let .drawing(drawing):
|
||||
image = drawing.imageInLightMode(from: drawing.bounds)
|
||||
imageContentMode = .fit
|
||||
imageBackgroundColor = .white
|
||||
}
|
||||
}
|
||||
|
||||
private func removeAttachment() {
|
||||
withAnimation {
|
||||
draft.attachments.removeAll { $0.id == attachment.id }
|
||||
|
|
|
@ -185,6 +185,17 @@ struct ComposeAttachmentsList: View {
|
|||
}
|
||||
}
|
||||
|
||||
fileprivate extension View {
|
||||
@ViewBuilder
|
||||
func onDragWithPreviewIfAvailable<V>(_ data: @escaping () -> NSItemProvider, preview: () -> V) -> some View where V : View {
|
||||
if #available(iOS 15.0, *) {
|
||||
self.onDrag(data, preview: preview)
|
||||
} else {
|
||||
self.onDrag(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//struct ComposeAttachmentsList_Previews: PreviewProvider {
|
||||
// static var previews: some View {
|
||||
// ComposeAttachmentsList()
|
||||
|
|
Loading…
Reference in New Issue