mirror of
https://github.com/metabolist/metatext.git
synced 2024-11-24 17:20:59 +00:00
wip
This commit is contained in:
parent
94cbbb2f04
commit
e6e1816e11
14 changed files with 240 additions and 58 deletions
|
@ -5,9 +5,28 @@ import UIKit
|
|||
import ViewModels
|
||||
|
||||
final class CompositionAttachmentsDataSource: UICollectionViewDiffableDataSource<Int, Attachment> {
|
||||
// init(collectionView: UICollectionView, composition: Composition) {
|
||||
// super.init(collectionView: collectionView) { collectionView, indexPath, attachment in
|
||||
//
|
||||
// }
|
||||
// }
|
||||
private let updateQueue =
|
||||
DispatchQueue(label: "com.metabolist.metatext.composition-attachments-data-source.update-queue")
|
||||
|
||||
init(collectionView: UICollectionView, viewModelProvider: @escaping (IndexPath) -> CompositionAttachmentViewModel) {
|
||||
let registration = UICollectionView.CellRegistration
|
||||
<CompositionAttachmentCollectionViewCell, CompositionAttachmentViewModel> {
|
||||
$0.viewModel = $2
|
||||
}
|
||||
|
||||
super.init(collectionView: collectionView) { collectionView, indexPath, _ in
|
||||
collectionView.dequeueConfiguredReusableCell(
|
||||
using: registration,
|
||||
for: indexPath,
|
||||
item: viewModelProvider(indexPath))
|
||||
}
|
||||
}
|
||||
|
||||
override func apply(_ snapshot: NSDiffableDataSourceSnapshot<Int, Attachment>,
|
||||
animatingDifferences: Bool = true,
|
||||
completion: (() -> Void)? = nil) {
|
||||
updateQueue.async {
|
||||
super.apply(snapshot, animatingDifferences: animatingDifferences, completion: completion)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,9 +15,15 @@ public enum StatusEndpoint {
|
|||
|
||||
public extension StatusEndpoint {
|
||||
struct Components {
|
||||
public var text: String?
|
||||
public let inReplyToId: Status.Id?
|
||||
public let text: String
|
||||
public let mediaIds: [Attachment.Id]
|
||||
|
||||
public init() {}
|
||||
public init(inReplyToId: Status.Id?, text: String, mediaIds: [Attachment.Id]) {
|
||||
self.inReplyToId = inReplyToId
|
||||
self.text = text
|
||||
self.mediaIds = mediaIds
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,7 +31,15 @@ extension StatusEndpoint.Components {
|
|||
var jsonBody: [String: Any]? {
|
||||
var params = [String: Any]()
|
||||
|
||||
params["status"] = text
|
||||
if !text.isEmpty {
|
||||
params["status"] = text
|
||||
}
|
||||
|
||||
if !mediaIds.isEmpty {
|
||||
params["media_ids"] = mediaIds
|
||||
}
|
||||
|
||||
params["in_reply_to_id"] = inReplyToId
|
||||
|
||||
return params
|
||||
}
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
D065966725899E910096AC5D /* CompositionAttachmentsDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D065965A25899DAE0096AC5D /* CompositionAttachmentsDataSource.swift */; };
|
||||
D06B492324D4611300642749 /* KingfisherSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = D06B492224D4611300642749 /* KingfisherSwiftUI */; };
|
||||
D06BC5E625202AD90079541D /* ProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D06BC5E525202AD90079541D /* ProfileViewController.swift */; };
|
||||
D0804133258D902900AD6139 /* CompositionAttachmentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0804132258D902900AD6139 /* CompositionAttachmentView.swift */; };
|
||||
D0804134258D902900AD6139 /* CompositionAttachmentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0804132258D902900AD6139 /* CompositionAttachmentView.swift */; };
|
||||
D080413E258D904400AD6139 /* CompositionAttachmentContentConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D080413D258D904400AD6139 /* CompositionAttachmentContentConfiguration.swift */; };
|
||||
D080413F258D904400AD6139 /* CompositionAttachmentContentConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D080413D258D904400AD6139 /* CompositionAttachmentContentConfiguration.swift */; };
|
||||
D08B8D3D253F929E00B1EBEF /* ImageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08B8D3C253F929E00B1EBEF /* ImageViewController.swift */; };
|
||||
D08B8D42253F92B600B1EBEF /* ImagePageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08B8D41253F92B600B1EBEF /* ImagePageViewController.swift */; };
|
||||
D08B8D4A253FC36500B1EBEF /* ImageNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08B8D49253FC36500B1EBEF /* ImageNavigationController.swift */; };
|
||||
|
@ -191,6 +195,8 @@
|
|||
D0666A2124C677B400F3F04B /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D0666A2524C677B400F3F04B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
D06BC5E525202AD90079541D /* ProfileViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileViewController.swift; sourceTree = "<group>"; };
|
||||
D0804132258D902900AD6139 /* CompositionAttachmentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompositionAttachmentView.swift; sourceTree = "<group>"; };
|
||||
D080413D258D904400AD6139 /* CompositionAttachmentContentConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompositionAttachmentContentConfiguration.swift; sourceTree = "<group>"; };
|
||||
D085C3BB25008DEC008A6C5E /* DB */ = {isa = PBXFileReference; lastKnownFileType = folder; path = DB; sourceTree = "<group>"; };
|
||||
D08B8D3C253F929E00B1EBEF /* ImageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewController.swift; sourceTree = "<group>"; };
|
||||
D08B8D41253F92B600B1EBEF /* ImagePageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePageViewController.swift; sourceTree = "<group>"; };
|
||||
|
@ -444,6 +450,8 @@
|
|||
D0C7D42424F76169001EBDBB /* AddIdentityView.swift */,
|
||||
D0CE9F86258B076900E3A6B6 /* AttachmentUploadView.swift */,
|
||||
D065966025899E890096AC5D /* CompositionAttachmentCollectionViewCell.swift */,
|
||||
D080413D258D904400AD6139 /* CompositionAttachmentContentConfiguration.swift */,
|
||||
D0804132258D902900AD6139 /* CompositionAttachmentView.swift */,
|
||||
D08E52E2257D747400FA2C5F /* CompositionContentConfiguration.swift */,
|
||||
D0E9F9A9258450B300EF503D /* CompositionInputAccessoryView.swift */,
|
||||
D08E52DB257D742B00FA2C5F /* CompositionListCell.swift */,
|
||||
|
@ -767,6 +775,7 @@
|
|||
D0C7D49C24F7616A001EBDBB /* RootView.swift in Sources */,
|
||||
D0F0B126251A90F400942152 /* AccountListCell.swift in Sources */,
|
||||
D0B32F50250B373600311912 /* RegistrationView.swift in Sources */,
|
||||
D0804133258D902900AD6139 /* CompositionAttachmentView.swift in Sources */,
|
||||
D08B8D612540DE3B00B1EBEF /* ZoomDismissalInteractionController.swift in Sources */,
|
||||
D036AA07254B6118009094DF /* NotificationView.swift in Sources */,
|
||||
D08E52EE257D757100FA2C5F /* CompositionView.swift in Sources */,
|
||||
|
@ -791,6 +800,7 @@
|
|||
D01F41D924F880C400D55A2D /* TouchFallthroughTextView.swift in Sources */,
|
||||
D0C7D4D624F7616A001EBDBB /* NSMutableAttributedString+Extensions.swift in Sources */,
|
||||
D0E9F9AA258450B300EF503D /* CompositionInputAccessoryView.swift in Sources */,
|
||||
D080413E258D904400AD6139 /* CompositionAttachmentContentConfiguration.swift in Sources */,
|
||||
D0625E59250F092900502611 /* StatusListCell.swift in Sources */,
|
||||
D0E569DB2529319100FA1D72 /* LoadMoreView.swift in Sources */,
|
||||
D0C7D49D24F7616A001EBDBB /* PostingReadingPreferencesView.swift in Sources */,
|
||||
|
@ -867,11 +877,13 @@
|
|||
D0E7AD4225870C79005F5E2D /* UIVIewController+Extensions.swift in Sources */,
|
||||
D08E52EF257D757100FA2C5F /* CompositionView.swift in Sources */,
|
||||
D0CE9F88258B076900E3A6B6 /* AttachmentUploadView.swift in Sources */,
|
||||
D080413F258D904400AD6139 /* CompositionAttachmentContentConfiguration.swift in Sources */,
|
||||
D0F2D5452581ABAB00986197 /* KingfisherOptionsInfo+Extensions.swift in Sources */,
|
||||
D08E52C7257C7AEE00FA2C5F /* ShareErrorViewController.swift in Sources */,
|
||||
D08E52F8257D78BE00FA2C5F /* ViewConstants.swift in Sources */,
|
||||
D0F2D4D6257EED6100986197 /* NewStatusDataSource.swift in Sources */,
|
||||
D065966725899E910096AC5D /* CompositionAttachmentsDataSource.swift in Sources */,
|
||||
D0804134258D902900AD6139 /* CompositionAttachmentView.swift in Sources */,
|
||||
D08E52FD257D78CB00FA2C5F /* UIColor+Extensions.swift in Sources */,
|
||||
D08E52E4257D747400FA2C5F /* CompositionContentConfiguration.swift in Sources */,
|
||||
D065966225899E890096AC5D /* CompositionAttachmentCollectionViewCell.swift in Sources */,
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import MastodonAPI
|
||||
|
||||
public typealias StatusComponents = StatusEndpoint.Components
|
|
@ -212,30 +212,9 @@ public extension IdentityService {
|
|||
progress: progress)
|
||||
}
|
||||
|
||||
// func post(compositions: [Composition]) -> AnyPublisher<Never, Error> {
|
||||
// fatalError()
|
||||
// guard let composition = compositions.first else { fatalError() }
|
||||
|
||||
// guard let attachment = composition.attachments.first else { fatalError() }
|
||||
// return mastodonAPIClient.request(AttachmentEndpoint.create(
|
||||
// data: attachment.data,
|
||||
// mimeType: attachment.mimeType,
|
||||
// description: attachment.description,
|
||||
// focus: attachment.focus))
|
||||
// .print()
|
||||
// .ignoreOutput()
|
||||
// .eraseToAnyPublisher()
|
||||
|
||||
// var components = StatusEndpoint.Components()
|
||||
//
|
||||
// if !composition.text.isEmpty {
|
||||
// components.text = composition.text
|
||||
// }
|
||||
//
|
||||
// return mastodonAPIClient.request(StatusEndpoint.post(components))
|
||||
// .ignoreOutput()
|
||||
// .eraseToAnyPublisher()
|
||||
// }
|
||||
func post(statusComponents: StatusComponents) -> AnyPublisher<Status.Id, Error> {
|
||||
mastodonAPIClient.request(StatusEndpoint.post(statusComponents)).map(\.id).eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func service(timeline: Timeline) -> TimelineService {
|
||||
TimelineService(timeline: timeline, mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase)
|
||||
|
|
|
@ -6,7 +6,7 @@ import Mastodon
|
|||
import ServiceLayer
|
||||
|
||||
public final class CompositionAttachmentViewModel: ObservableObject {
|
||||
public var attachment: Attachment
|
||||
public let attachment: Attachment
|
||||
|
||||
init(attachment: Attachment) {
|
||||
self.attachment = attachment
|
||||
|
|
|
@ -7,8 +7,9 @@ import ServiceLayer
|
|||
|
||||
public final class CompositionViewModel: ObservableObject {
|
||||
public let id = Id()
|
||||
public var isPosted = false
|
||||
@Published public var text = ""
|
||||
@Published public private(set) var attachments = [Attachment]()
|
||||
@Published public private(set) var attachmentViewModels = [CompositionAttachmentViewModel]()
|
||||
@Published public private(set) var isPostable = false
|
||||
@Published public private(set) var identification: Identification
|
||||
@Published public private(set) var attachmentUpload: AttachmentUpload?
|
||||
|
@ -35,10 +36,11 @@ public extension CompositionViewModel {
|
|||
case error(Error)
|
||||
}
|
||||
|
||||
struct AttachmentUpload {
|
||||
public let progress: Progress
|
||||
public let data: Data
|
||||
public let mimeType: String
|
||||
func components(inReplyToId: Status.Id?) -> StatusComponents {
|
||||
StatusComponents(
|
||||
inReplyToId: inReplyToId,
|
||||
text: text,
|
||||
mediaIds: attachmentViewModels.map(\.attachment.id))
|
||||
}
|
||||
|
||||
func presentMediaPicker() {
|
||||
|
@ -63,17 +65,20 @@ public extension CompositionViewModel {
|
|||
return self.identification.service.uploadAttachment(data: data, mimeType: mimeType, progress: progress)
|
||||
}
|
||||
.print()
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] in
|
||||
DispatchQueue.main.async {
|
||||
self?.attachmentUpload = nil
|
||||
}
|
||||
self?.attachmentUpload = nil
|
||||
|
||||
if case let .failure(error) = $0 {
|
||||
self?.eventsSubject.send(.error(error))
|
||||
}
|
||||
} receiveValue: { [weak self] in
|
||||
self?.attachments.append($0)
|
||||
self?.attachmentViewModels.append(CompositionAttachmentViewModel(attachment: $0))
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
func attachmentViewModel(indexPath: IndexPath) -> CompositionAttachmentViewModel {
|
||||
attachmentViewModels[indexPath.item]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct AttachmentUpload: Hashable {
|
||||
public let progress: Progress
|
||||
public let data: Data
|
||||
public let mimeType: String
|
||||
}
|
|
@ -67,14 +67,9 @@ public extension NewStatusViewModel {
|
|||
}
|
||||
|
||||
func post() {
|
||||
// identification.service.post(compositions: compositionViewModels.map(\.composition))
|
||||
// .receive(on: DispatchQueue.main)
|
||||
// .handleEvents(
|
||||
// receiveSubscription: { [weak self] _ in self?.loading = true },
|
||||
// receiveCompletion: { [weak self] _ in self?.loading = false })
|
||||
// .assignErrorsToAlertItem(to: \.alertItem, on: self)
|
||||
// .sink { _ in }
|
||||
// .store(in: &cancellables)
|
||||
guard let unposted = compositionViewModels.first(where: { !$0.isPosted }) else { return }
|
||||
|
||||
post(viewModel: unposted, inReplyToId: nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,4 +99,30 @@ private extension NewStatusViewModel {
|
|||
eventsSubject.send(event)
|
||||
}
|
||||
}
|
||||
|
||||
func post(viewModel: CompositionViewModel, inReplyToId: Status.Id?) {
|
||||
loading = true
|
||||
identification.service.post(statusComponents: viewModel.components(inReplyToId: inReplyToId))
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] in
|
||||
guard let self = self else { return }
|
||||
|
||||
switch $0 {
|
||||
case .finished:
|
||||
self.loading = self.compositionViewModels.allSatisfy(\.isPosted)
|
||||
case let .failure(error):
|
||||
self.alertItem = AlertItem(error: error)
|
||||
self.loading = false
|
||||
}
|
||||
} receiveValue: { [weak self] in
|
||||
guard let self = self else { return }
|
||||
|
||||
viewModel.isPosted = true
|
||||
|
||||
if let unposted = self.compositionViewModels.first(where: { !$0.isPosted }) {
|
||||
self.post(viewModel: unposted, inReplyToId: $0)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ final class AttachmentUploadView: UIView {
|
|||
let progressView = UIProgressView(progressViewStyle: .default)
|
||||
private var progressCancellable: AnyCancellable?
|
||||
|
||||
var attachmentUpload: CompositionViewModel.AttachmentUpload? {
|
||||
var attachmentUpload: AttachmentUpload? {
|
||||
didSet {
|
||||
if let attachmentUpload = attachmentUpload {
|
||||
progressCancellable = attachmentUpload.progress.publisher(for: \.fractionCompleted)
|
||||
|
|
|
@ -1,7 +1,15 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import UIKit
|
||||
import ViewModels
|
||||
|
||||
class CompositionAttachmentCollectionViewCell: UICollectionViewCell {
|
||||
|
||||
var viewModel: CompositionAttachmentViewModel?
|
||||
|
||||
override func updateConfiguration(using state: UICellConfigurationState) {
|
||||
guard let viewModel = viewModel else { return }
|
||||
|
||||
contentConfiguration = CompositionAttachmentContentConfiguration(viewModel: viewModel).updated(for: state)
|
||||
backgroundConfiguration = UIBackgroundConfiguration.clear().updated(for: state)
|
||||
}
|
||||
}
|
||||
|
|
18
Views/CompositionAttachmentContentConfiguration.swift
Normal file
18
Views/CompositionAttachmentContentConfiguration.swift
Normal file
|
@ -0,0 +1,18 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import UIKit
|
||||
import ViewModels
|
||||
|
||||
struct CompositionAttachmentContentConfiguration {
|
||||
let viewModel: CompositionAttachmentViewModel
|
||||
}
|
||||
|
||||
extension CompositionAttachmentContentConfiguration: UIContentConfiguration {
|
||||
func makeContentView() -> UIView & UIContentView {
|
||||
CompositionAttachmentView(configuration: self)
|
||||
}
|
||||
|
||||
func updated(for state: UIConfigurationState) -> CompositionAttachmentContentConfiguration {
|
||||
self
|
||||
}
|
||||
}
|
59
Views/CompositionAttachmentView.swift
Normal file
59
Views/CompositionAttachmentView.swift
Normal file
|
@ -0,0 +1,59 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import Kingfisher
|
||||
import UIKit
|
||||
import ViewModels
|
||||
|
||||
class CompositionAttachmentView: UIView {
|
||||
let imageView = UIImageView()
|
||||
private var compositionAttachmentConfiguration: CompositionAttachmentContentConfiguration
|
||||
|
||||
init(configuration: CompositionAttachmentContentConfiguration) {
|
||||
self.compositionAttachmentConfiguration = configuration
|
||||
|
||||
super.init(frame: .zero)
|
||||
|
||||
initialSetup()
|
||||
applyCompositionAttachmentConfiguration()
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
||||
extension CompositionAttachmentView: UIContentView {
|
||||
var configuration: UIContentConfiguration {
|
||||
get { compositionAttachmentConfiguration }
|
||||
set {
|
||||
guard let compositionAttachmentConfiguration = newValue as? CompositionAttachmentContentConfiguration
|
||||
else { return }
|
||||
|
||||
self.compositionAttachmentConfiguration = compositionAttachmentConfiguration
|
||||
|
||||
applyCompositionAttachmentConfiguration()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension CompositionAttachmentView {
|
||||
func initialSetup() {
|
||||
addSubview(imageView)
|
||||
imageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
imageView.contentMode = .scaleAspectFill
|
||||
imageView.layer.cornerRadius = .defaultCornerRadius
|
||||
imageView.clipsToBounds = true
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
imageView.leadingAnchor.constraint(equalTo: leadingAnchor),
|
||||
imageView.topAnchor.constraint(equalTo: topAnchor),
|
||||
imageView.trailingAnchor.constraint(equalTo: trailingAnchor),
|
||||
imageView.bottomAnchor.constraint(equalTo: bottomAnchor)
|
||||
])
|
||||
}
|
||||
|
||||
func applyCompositionAttachmentConfiguration() {
|
||||
imageView.kf.setImage(with: compositionAttachmentConfiguration.viewModel.attachment.previewUrl)
|
||||
}
|
||||
}
|
|
@ -4,18 +4,41 @@ import Combine
|
|||
import Kingfisher
|
||||
import UIKit
|
||||
|
||||
class CompositionView: UIView {
|
||||
final class CompositionView: UIView {
|
||||
let avatarImageView = UIImageView()
|
||||
let textView = UITextView()
|
||||
let attachmentUploadView = AttachmentUploadView()
|
||||
// let attachmentsCollectionView = UICollectionView()
|
||||
let attachmentsCollectionView: UICollectionView
|
||||
|
||||
private var compositionConfiguration: CompositionContentConfiguration
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
private lazy var attachmentsDataSource: CompositionAttachmentsDataSource = {
|
||||
CompositionAttachmentsDataSource(
|
||||
collectionView: attachmentsCollectionView,
|
||||
viewModelProvider: compositionConfiguration.viewModel.attachmentViewModel(indexPath:))
|
||||
}()
|
||||
|
||||
init(configuration: CompositionContentConfiguration) {
|
||||
self.compositionConfiguration = configuration
|
||||
|
||||
let itemSize = NSCollectionLayoutSize(
|
||||
widthDimension: .fractionalWidth(0.2),
|
||||
heightDimension: .fractionalHeight(1.0))
|
||||
let item = NSCollectionLayoutItem(layoutSize: itemSize)
|
||||
let groupSize = NSCollectionLayoutSize(
|
||||
widthDimension: .fractionalWidth(1.0),
|
||||
heightDimension: .fractionalWidth(0.2))
|
||||
let group = NSCollectionLayoutGroup.horizontal(
|
||||
layoutSize: groupSize,
|
||||
subitems: [item])
|
||||
|
||||
group.interItemSpacing = .fixed(.defaultSpacing)
|
||||
|
||||
let section = NSCollectionLayoutSection(group: group)
|
||||
let attachmentsLayout = UICollectionViewCompositionalLayout(section: section)
|
||||
attachmentsCollectionView = UICollectionView(frame: .zero, collectionViewLayout: attachmentsLayout)
|
||||
|
||||
super.init(frame: .zero)
|
||||
|
||||
initialSetup()
|
||||
|
@ -48,7 +71,7 @@ extension CompositionView: UITextViewDelegate {
|
|||
}
|
||||
|
||||
private extension CompositionView {
|
||||
static let attachmentsCollectionViewHeight: CGFloat = 100
|
||||
static let attachmentUploadViewHeight: CGFloat = 100
|
||||
|
||||
func initialSetup() {
|
||||
addSubview(avatarImageView)
|
||||
|
@ -71,7 +94,8 @@ private extension CompositionView {
|
|||
textView.inputAccessoryView?.sizeToFit()
|
||||
textView.delegate = self
|
||||
|
||||
// stackView.addArrangedSubview(attachmentsCollectionView)
|
||||
stackView.addArrangedSubview(attachmentsCollectionView)
|
||||
attachmentsCollectionView.dataSource = attachmentsDataSource
|
||||
|
||||
stackView.addArrangedSubview(attachmentUploadView)
|
||||
|
||||
|
@ -85,8 +109,10 @@ private extension CompositionView {
|
|||
stackView.topAnchor.constraint(equalTo: readableContentGuide.topAnchor),
|
||||
stackView.trailingAnchor.constraint(equalTo: readableContentGuide.trailingAnchor),
|
||||
stackView.bottomAnchor.constraint(equalTo: readableContentGuide.bottomAnchor),
|
||||
// attachmentsCollectionView.heightAnchor.constraint(equalToConstant: Self.attachmentsCollectionViewHeight)
|
||||
attachmentUploadView.heightAnchor.constraint(equalToConstant: Self.attachmentsCollectionViewHeight)
|
||||
attachmentsCollectionView.heightAnchor.constraint(
|
||||
equalTo: attachmentsCollectionView.widthAnchor,
|
||||
multiplier: 1 / 4),
|
||||
attachmentUploadView.heightAnchor.constraint(equalToConstant: Self.attachmentUploadViewHeight)
|
||||
]
|
||||
|
||||
for constraint in constraints {
|
||||
|
@ -99,6 +125,13 @@ private extension CompositionView {
|
|||
.sink { [weak self] in self?.avatarImageView.kf.setImage(with: $0) }
|
||||
.store(in: &cancellables)
|
||||
|
||||
compositionConfiguration.viewModel.$attachmentViewModels
|
||||
.sink { [weak self] in
|
||||
self?.attachmentsDataSource.apply([$0.map(\.attachment)].snapshot())
|
||||
self?.attachmentsCollectionView.isHidden = $0.isEmpty
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
compositionConfiguration.viewModel.$attachmentUpload
|
||||
.sink { [weak self] in self?.attachmentUploadView.attachmentUpload = $0 }
|
||||
.store(in: &cancellables)
|
||||
|
|
Loading…
Reference in a new issue