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 */; };
|
D6D4DDDA212518A200E1C4BB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D6D4DDD8212518A200E1C4BB /* LaunchScreen.storyboard */; };
|
||||||
D6D4DDE5212518A200E1C4BB /* TuskerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D4DDE4212518A200E1C4BB /* TuskerTests.swift */; };
|
D6D4DDE5212518A200E1C4BB /* TuskerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D4DDE4212518A200E1C4BB /* TuskerTests.swift */; };
|
||||||
D6D4DDF0212518A200E1C4BB /* TuskerUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D4DDEF212518A200E1C4BB /* TuskerUITests.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 */; };
|
D6DD353D22F28CD000A9563A /* ContentWarningCopyMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DD353C22F28CD000A9563A /* ContentWarningCopyMode.swift */; };
|
||||||
D6DD353F22F502EC00A9563A /* Preferences+Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DD353E22F502EC00A9563A /* Preferences+Notification.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 */; };
|
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; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
D6DEA0DC268400C300FE896A /* ConfirmLoadMoreTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmLoadMoreTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
|
@ -1170,6 +1172,7 @@
|
||||||
D662AEF1263A4BE10082A153 /* ComposePollView.swift */,
|
D662AEF1263A4BE10082A153 /* ComposePollView.swift */,
|
||||||
D622757324EDF1CD00B82A16 /* ComposeAttachmentsList.swift */,
|
D622757324EDF1CD00B82A16 /* ComposeAttachmentsList.swift */,
|
||||||
D622757924EE21D900B82A16 /* ComposeAttachmentRow.swift */,
|
D622757924EE21D900B82A16 /* ComposeAttachmentRow.swift */,
|
||||||
|
D6DD2A3E273C1F4900386A6C /* ComposeAttachmentImage.swift */,
|
||||||
D622757724EE133700B82A16 /* ComposeAssetPicker.swift */,
|
D622757724EE133700B82A16 /* ComposeAssetPicker.swift */,
|
||||||
D62275A524F1C81800B82A16 /* ComposeReplyView.swift */,
|
D62275A524F1C81800B82A16 /* ComposeReplyView.swift */,
|
||||||
D62275A724F1CA2800B82A16 /* ComposeReplyContentView.swift */,
|
D62275A724F1CA2800B82A16 /* ComposeReplyContentView.swift */,
|
||||||
|
@ -2187,6 +2190,7 @@
|
||||||
D6BED174212667E900F02DA0 /* TimelineStatusTableViewCell.swift in Sources */,
|
D6BED174212667E900F02DA0 /* TimelineStatusTableViewCell.swift in Sources */,
|
||||||
D69693F42585941A00F4E116 /* UIWindowSceneDelegate+Close.swift in Sources */,
|
D69693F42585941A00F4E116 /* UIWindowSceneDelegate+Close.swift in Sources */,
|
||||||
D6C143DA253510F4007DC240 /* ComposeEmojiTextField.swift in Sources */,
|
D6C143DA253510F4007DC240 /* ComposeEmojiTextField.swift in Sources */,
|
||||||
|
D6DD2A3F273C1F4900386A6C /* ComposeAttachmentImage.swift in Sources */,
|
||||||
0427033822B30F5F000D31B6 /* BehaviorPrefsView.swift in Sources */,
|
0427033822B30F5F000D31B6 /* BehaviorPrefsView.swift in Sources */,
|
||||||
D627943923A553B600D38C68 /* UnbookmarkStatusActivity.swift in Sources */,
|
D627943923A553B600D38C68 /* UnbookmarkStatusActivity.swift in Sources */,
|
||||||
D64D0AAD2128D88B005A6F37 /* LocalData.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
|
@EnvironmentObject var uiState: ComposeUIState
|
||||||
@State private var mode: Mode = .allowEntry
|
@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 isShowingTextRecognitionFailedAlert = false
|
||||||
@State private var textRecognitionErrorMessage: String? = nil
|
@State private var textRecognitionErrorMessage: String? = nil
|
||||||
|
|
||||||
@Environment(\.colorScheme) private var colorScheme: ColorScheme
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack(alignment: .center, spacing: 4) {
|
HStack(alignment: .center, spacing: 4) {
|
||||||
imageView
|
ComposeAttachmentImage(attachment: attachment, fullSize: false)
|
||||||
.frame(width: 80, height: 80)
|
.frame(width: 80, height: 80)
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
.contextMenu {
|
.contextMenu {
|
||||||
|
@ -71,7 +66,6 @@ struct ComposeAttachmentRow: View {
|
||||||
// .foregroundColor(.blue)
|
// .foregroundColor(.blue)
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
.onAppear(perform: self.loadImage)
|
|
||||||
.onReceive(attachment.$attachmentDescription) { (newDesc) in
|
.onReceive(attachment.$attachmentDescription) { (newDesc) in
|
||||||
if newDesc.isEmpty {
|
if newDesc.isEmpty {
|
||||||
uiState.attachmentsMissingDescriptions.insert(attachment.id)
|
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() {
|
private func removeAttachment() {
|
||||||
withAnimation {
|
withAnimation {
|
||||||
draft.attachments.removeAll { $0.id == attachment.id }
|
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 {
|
//struct ComposeAttachmentsList_Previews: PreviewProvider {
|
||||||
// static var previews: some View {
|
// static var previews: some View {
|
||||||
// ComposeAttachmentsList()
|
// ComposeAttachmentsList()
|
||||||
|
|
Loading…
Reference in New Issue