feat: add image attachments reorder support for status compose scene
This commit is contained in:
parent
36b42ba3e7
commit
b296b21ef0
@ -179,8 +179,8 @@
|
|||||||
DB72602725E36A6F00235243 /* MastodonServerRulesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB72602625E36A6F00235243 /* MastodonServerRulesViewModel.swift */; };
|
DB72602725E36A6F00235243 /* MastodonServerRulesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB72602625E36A6F00235243 /* MastodonServerRulesViewModel.swift */; };
|
||||||
DB789A0B25F9F2950071ACA0 /* ComposeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB789A0A25F9F2950071ACA0 /* ComposeViewController.swift */; };
|
DB789A0B25F9F2950071ACA0 /* ComposeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB789A0A25F9F2950071ACA0 /* ComposeViewController.swift */; };
|
||||||
DB789A1225F9F2CC0071ACA0 /* ComposeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB789A1125F9F2CC0071ACA0 /* ComposeViewModel.swift */; };
|
DB789A1225F9F2CC0071ACA0 /* ComposeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB789A1125F9F2CC0071ACA0 /* ComposeViewModel.swift */; };
|
||||||
DB789A1C25F9F76A0071ACA0 /* ComposeStatusContentTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB789A1B25F9F76A0071ACA0 /* ComposeStatusContentTableViewCell.swift */; };
|
DB789A1C25F9F76A0071ACA0 /* ComposeStatusContentCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB789A1B25F9F76A0071ACA0 /* ComposeStatusContentCollectionViewCell.swift */; };
|
||||||
DB789A2B25F9F7AB0071ACA0 /* ComposeRepliedToTootContentTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB789A2A25F9F7AB0071ACA0 /* ComposeRepliedToTootContentTableViewCell.swift */; };
|
DB789A2B25F9F7AB0071ACA0 /* ComposeRepliedToTootContentCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB789A2A25F9F7AB0071ACA0 /* ComposeRepliedToTootContentCollectionViewCell.swift */; };
|
||||||
DB8190C62601FF0400020C08 /* AttachmentContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8190C52601FF0400020C08 /* AttachmentContainerView.swift */; };
|
DB8190C62601FF0400020C08 /* AttachmentContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8190C52601FF0400020C08 /* AttachmentContainerView.swift */; };
|
||||||
DB89B9F725C10FD0008580ED /* CoreDataStack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DB89B9EE25C10FD0008580ED /* CoreDataStack.framework */; };
|
DB89B9F725C10FD0008580ED /* CoreDataStack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DB89B9EE25C10FD0008580ED /* CoreDataStack.framework */; };
|
||||||
DB89B9FE25C10FD0008580ED /* CoreDataStackTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB89B9FD25C10FD0008580ED /* CoreDataStackTests.swift */; };
|
DB89B9FE25C10FD0008580ED /* CoreDataStackTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB89B9FD25C10FD0008580ED /* CoreDataStackTests.swift */; };
|
||||||
@ -468,8 +468,8 @@
|
|||||||
DB72602625E36A6F00235243 /* MastodonServerRulesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonServerRulesViewModel.swift; sourceTree = "<group>"; };
|
DB72602625E36A6F00235243 /* MastodonServerRulesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonServerRulesViewModel.swift; sourceTree = "<group>"; };
|
||||||
DB789A0A25F9F2950071ACA0 /* ComposeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeViewController.swift; sourceTree = "<group>"; };
|
DB789A0A25F9F2950071ACA0 /* ComposeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeViewController.swift; sourceTree = "<group>"; };
|
||||||
DB789A1125F9F2CC0071ACA0 /* ComposeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeViewModel.swift; sourceTree = "<group>"; };
|
DB789A1125F9F2CC0071ACA0 /* ComposeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeViewModel.swift; sourceTree = "<group>"; };
|
||||||
DB789A1B25F9F76A0071ACA0 /* ComposeStatusContentTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeStatusContentTableViewCell.swift; sourceTree = "<group>"; };
|
DB789A1B25F9F76A0071ACA0 /* ComposeStatusContentCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeStatusContentCollectionViewCell.swift; sourceTree = "<group>"; };
|
||||||
DB789A2A25F9F7AB0071ACA0 /* ComposeRepliedToTootContentTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeRepliedToTootContentTableViewCell.swift; sourceTree = "<group>"; };
|
DB789A2A25F9F7AB0071ACA0 /* ComposeRepliedToTootContentCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeRepliedToTootContentCollectionViewCell.swift; sourceTree = "<group>"; };
|
||||||
DB8190C52601FF0400020C08 /* AttachmentContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentContainerView.swift; sourceTree = "<group>"; };
|
DB8190C52601FF0400020C08 /* AttachmentContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentContainerView.swift; sourceTree = "<group>"; };
|
||||||
DB89B9EE25C10FD0008580ED /* CoreDataStack.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CoreDataStack.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
DB89B9EE25C10FD0008580ED /* CoreDataStack.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CoreDataStack.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
DB89B9F025C10FD0008580ED /* CoreDataStack.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CoreDataStack.h; sourceTree = "<group>"; };
|
DB89B9F025C10FD0008580ED /* CoreDataStack.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CoreDataStack.h; sourceTree = "<group>"; };
|
||||||
@ -1122,7 +1122,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
DB55D32225FB4D320002F825 /* View */,
|
DB55D32225FB4D320002F825 /* View */,
|
||||||
DB789A2125F9F76D0071ACA0 /* TableViewCell */,
|
DB789A2125F9F76D0071ACA0 /* CollectionViewCell */,
|
||||||
DB789A0A25F9F2950071ACA0 /* ComposeViewController.swift */,
|
DB789A0A25F9F2950071ACA0 /* ComposeViewController.swift */,
|
||||||
DB789A1125F9F2CC0071ACA0 /* ComposeViewModel.swift */,
|
DB789A1125F9F2CC0071ACA0 /* ComposeViewModel.swift */,
|
||||||
DB9A488926034D40008B817C /* ComposeViewModel+PublishState.swift */,
|
DB9A488926034D40008B817C /* ComposeViewModel+PublishState.swift */,
|
||||||
@ -1131,14 +1131,14 @@
|
|||||||
path = Compose;
|
path = Compose;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
DB789A2125F9F76D0071ACA0 /* TableViewCell */ = {
|
DB789A2125F9F76D0071ACA0 /* CollectionViewCell */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
DB789A2A25F9F7AB0071ACA0 /* ComposeRepliedToTootContentTableViewCell.swift */,
|
DB789A2A25F9F7AB0071ACA0 /* ComposeRepliedToTootContentCollectionViewCell.swift */,
|
||||||
DB789A1B25F9F76A0071ACA0 /* ComposeStatusContentTableViewCell.swift */,
|
DB789A1B25F9F76A0071ACA0 /* ComposeStatusContentCollectionViewCell.swift */,
|
||||||
DB6B351D2601FAEE00DC1E11 /* ComposeStatusAttachmentTableViewCell.swift */,
|
DB6B351D2601FAEE00DC1E11 /* ComposeStatusAttachmentTableViewCell.swift */,
|
||||||
);
|
);
|
||||||
path = TableViewCell;
|
path = CollectionViewCell;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
DB89B9EF25C10FD0008580ED /* CoreDataStack */ = {
|
DB89B9EF25C10FD0008580ED /* CoreDataStack */ = {
|
||||||
@ -1842,7 +1842,7 @@
|
|||||||
DB47229725F9EFAD00DA7F53 /* NSManagedObjectContext.swift in Sources */,
|
DB47229725F9EFAD00DA7F53 /* NSManagedObjectContext.swift in Sources */,
|
||||||
2D42FF7E25C82218004A627A /* ActionToolBarContainer.swift in Sources */,
|
2D42FF7E25C82218004A627A /* ActionToolBarContainer.swift in Sources */,
|
||||||
DB0140A125C40C0600F9F3CF /* MastodonPinBasedAuthenticationViewController.swift in Sources */,
|
DB0140A125C40C0600F9F3CF /* MastodonPinBasedAuthenticationViewController.swift in Sources */,
|
||||||
DB789A1C25F9F76A0071ACA0 /* ComposeStatusContentTableViewCell.swift in Sources */,
|
DB789A1C25F9F76A0071ACA0 /* ComposeStatusContentCollectionViewCell.swift in Sources */,
|
||||||
DB1FD43625F26899004CFCFC /* MastodonPickServerViewModel+LoadIndexedServerState.swift in Sources */,
|
DB1FD43625F26899004CFCFC /* MastodonPickServerViewModel+LoadIndexedServerState.swift in Sources */,
|
||||||
DB9A488426034BD7008B817C /* APIService+Status.swift in Sources */,
|
DB9A488426034BD7008B817C /* APIService+Status.swift in Sources */,
|
||||||
2D939AE825EE1CF80076FA61 /* MastodonRegisterViewController+Avatar.swift in Sources */,
|
2D939AE825EE1CF80076FA61 /* MastodonRegisterViewController+Avatar.swift in Sources */,
|
||||||
@ -1922,7 +1922,7 @@
|
|||||||
5DF1057925F88A1D00D6C0D4 /* PlayerContainerView.swift in Sources */,
|
5DF1057925F88A1D00D6C0D4 /* PlayerContainerView.swift in Sources */,
|
||||||
DB45FB0F25CA87D0005A8AC7 /* AuthenticationService.swift in Sources */,
|
DB45FB0F25CA87D0005A8AC7 /* AuthenticationService.swift in Sources */,
|
||||||
DBCCC71E25F73297007E1AB6 /* APIService+Reblog.swift in Sources */,
|
DBCCC71E25F73297007E1AB6 /* APIService+Reblog.swift in Sources */,
|
||||||
DB789A2B25F9F7AB0071ACA0 /* ComposeRepliedToTootContentTableViewCell.swift in Sources */,
|
DB789A2B25F9F7AB0071ACA0 /* ComposeRepliedToTootContentCollectionViewCell.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -26,22 +26,22 @@ extension ComposeStatusSection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension ComposeStatusSection {
|
extension ComposeStatusSection {
|
||||||
static func tableViewDiffableDataSource(
|
|
||||||
for tableView: UITableView,
|
static func collectionViewDiffableDataSource(
|
||||||
|
for collectionView: UICollectionView,
|
||||||
dependency: NeedsDependency,
|
dependency: NeedsDependency,
|
||||||
managedObjectContext: NSManagedObjectContext,
|
managedObjectContext: NSManagedObjectContext,
|
||||||
composeKind: ComposeKind,
|
composeKind: ComposeKind,
|
||||||
textEditorViewTextAttributesDelegate: TextEditorViewTextAttributesDelegate,
|
textEditorViewTextAttributesDelegate: TextEditorViewTextAttributesDelegate,
|
||||||
composeStatusAttachmentTableViewCellDelegate: ComposeStatusAttachmentTableViewCellDelegate
|
composeStatusAttachmentTableViewCellDelegate: ComposeStatusAttachmentCollectionViewCellDelegate
|
||||||
) -> UITableViewDiffableDataSource<ComposeStatusSection, ComposeStatusItem> {
|
) -> UICollectionViewDiffableDataSource<ComposeStatusSection, ComposeStatusItem> {
|
||||||
UITableViewDiffableDataSource<ComposeStatusSection, ComposeStatusItem>(tableView: tableView) { [weak textEditorViewTextAttributesDelegate, weak composeStatusAttachmentTableViewCellDelegate] tableView, indexPath, item -> UITableViewCell? in
|
UICollectionViewDiffableDataSource(collectionView: collectionView) { collectionView, indexPath, item -> UICollectionViewCell? in
|
||||||
switch item {
|
switch item {
|
||||||
case .replyTo(let repliedToStatusObjectID):
|
case .replyTo(let repliedToStatusObjectID):
|
||||||
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ComposeRepliedToTootContentTableViewCell.self), for: indexPath) as! ComposeRepliedToTootContentTableViewCell
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: ComposeRepliedToTootContentCollectionViewCell.self), for: indexPath) as! ComposeRepliedToTootContentCollectionViewCell
|
||||||
// TODO:
|
|
||||||
return cell
|
return cell
|
||||||
case .input(let replyToTootObjectID, let attribute):
|
case .input(let replyToTootObjectID, let attribute):
|
||||||
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ComposeStatusContentTableViewCell.self), for: indexPath) as! ComposeStatusContentTableViewCell
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: ComposeStatusContentCollectionViewCell.self), for: indexPath) as! ComposeStatusContentCollectionViewCell
|
||||||
cell.textEditorView.text = attribute.composeContent.value ?? ""
|
cell.textEditorView.text = attribute.composeContent.value ?? ""
|
||||||
managedObjectContext.perform {
|
managedObjectContext.perform {
|
||||||
guard let replyToTootObjectID = replyToTootObjectID,
|
guard let replyToTootObjectID = replyToTootObjectID,
|
||||||
@ -59,24 +59,24 @@ extension ComposeStatusSection {
|
|||||||
.removeDuplicates()
|
.removeDuplicates()
|
||||||
.receive(on: DispatchQueue.main)
|
.receive(on: DispatchQueue.main)
|
||||||
.sink { text in
|
.sink { text in
|
||||||
tableView.beginUpdates()
|
collectionView.collectionViewLayout.invalidateLayout()
|
||||||
tableView.endUpdates()
|
|
||||||
// bind input data
|
// bind input data
|
||||||
attribute.composeContent.value = text
|
attribute.composeContent.value = text
|
||||||
}
|
}
|
||||||
.store(in: &cell.disposeBag)
|
.store(in: &cell.disposeBag)
|
||||||
return cell
|
return cell
|
||||||
case .attachment(let attachmentService):
|
case .attachment(let attachmentService):
|
||||||
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ComposeStatusAttachmentTableViewCell.self), for: indexPath) as! ComposeStatusAttachmentTableViewCell
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: ComposeStatusAttachmentCollectionViewCell.self), for: indexPath) as! ComposeStatusAttachmentCollectionViewCell
|
||||||
cell.attachmentContainerView.descriptionTextView.text = attachmentService.description.value
|
cell.attachmentContainerView.descriptionTextView.text = attachmentService.description.value
|
||||||
cell.delegate = composeStatusAttachmentTableViewCellDelegate
|
cell.delegate = composeStatusAttachmentTableViewCellDelegate
|
||||||
attachmentService.imageData
|
attachmentService.imageData
|
||||||
.receive(on: DispatchQueue.main)
|
.receive(on: DispatchQueue.main)
|
||||||
.sink { imageData in
|
.sink { imageData in
|
||||||
|
let size = cell.attachmentContainerView.previewImageView.frame.size != .zero ? cell.attachmentContainerView.previewImageView.frame.size : CGSize(width: 1, height: 1)
|
||||||
guard let imageData = imageData,
|
guard let imageData = imageData,
|
||||||
let image = UIImage(data: imageData) else {
|
let image = UIImage(data: imageData) else {
|
||||||
let placeholder = UIImage.placeholder(
|
let placeholder = UIImage.placeholder(
|
||||||
size: cell.attachmentContainerView.previewImageView.frame.size,
|
size: size,
|
||||||
color: Asset.Colors.Background.systemGroupedBackground.color
|
color: Asset.Colors.Background.systemGroupedBackground.color
|
||||||
)
|
)
|
||||||
.af.imageRounded(
|
.af.imageRounded(
|
||||||
@ -86,7 +86,7 @@ extension ComposeStatusSection {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
cell.attachmentContainerView.previewImageView.image = image
|
cell.attachmentContainerView.previewImageView.image = image
|
||||||
.af.imageAspectScaled(toFill: cell.attachmentContainerView.previewImageView.frame.size)
|
.af.imageAspectScaled(toFill: size)
|
||||||
.af.imageRounded(withCornerRadius: AttachmentContainerView.containerViewCornerRadius)
|
.af.imageRounded(withCornerRadius: AttachmentContainerView.containerViewCornerRadius)
|
||||||
}
|
}
|
||||||
.store(in: &cell.disposeBag)
|
.store(in: &cell.disposeBag)
|
||||||
@ -97,6 +97,7 @@ extension ComposeStatusSection {
|
|||||||
.receive(on: DispatchQueue.main)
|
.receive(on: DispatchQueue.main)
|
||||||
.sink { uploadState, error in
|
.sink { uploadState, error in
|
||||||
cell.attachmentContainerView.emptyStateView.isHidden = error == nil
|
cell.attachmentContainerView.emptyStateView.isHidden = error == nil
|
||||||
|
cell.attachmentContainerView.descriptionBackgroundView.isHidden = error != nil
|
||||||
if let _ = error {
|
if let _ = error {
|
||||||
cell.attachmentContainerView.activityIndicatorView.stopAnimating()
|
cell.attachmentContainerView.activityIndicatorView.stopAnimating()
|
||||||
} else {
|
} else {
|
||||||
@ -130,7 +131,7 @@ extension ComposeStatusSection {
|
|||||||
|
|
||||||
extension ComposeStatusSection {
|
extension ComposeStatusSection {
|
||||||
static func configure(
|
static func configure(
|
||||||
cell: ComposeStatusContentTableViewCell,
|
cell: ComposeStatusContentCollectionViewCell,
|
||||||
attribute: ComposeStatusItem.ComposeStatusAttribute
|
attribute: ComposeStatusItem.ComposeStatusAttribute
|
||||||
) {
|
) {
|
||||||
// set avatar
|
// set avatar
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
//
|
||||||
|
// ComposeRepliedToTootContentCollectionViewCell.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by MainasuK Cirno on 2021-3-11.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
final class ComposeRepliedToTootContentCollectionViewCell: UICollectionViewCell {
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
_init()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
super.init(coder: coder)
|
||||||
|
_init()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ComposeRepliedToTootContentCollectionViewCell {
|
||||||
|
|
||||||
|
private func _init() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -9,18 +9,18 @@ import os.log
|
|||||||
import UIKit
|
import UIKit
|
||||||
import Combine
|
import Combine
|
||||||
|
|
||||||
protocol ComposeStatusAttachmentTableViewCellDelegate: class {
|
protocol ComposeStatusAttachmentCollectionViewCellDelegate: class {
|
||||||
func composeStatusAttachmentTableViewCell(_ cell: ComposeStatusAttachmentTableViewCell, removeButtonDidPressed button: UIButton)
|
func composeStatusAttachmentCollectionViewCell(_ cell: ComposeStatusAttachmentCollectionViewCell, removeButtonDidPressed button: UIButton)
|
||||||
}
|
}
|
||||||
|
|
||||||
final class ComposeStatusAttachmentTableViewCell: UITableViewCell {
|
final class ComposeStatusAttachmentCollectionViewCell: UICollectionViewCell {
|
||||||
|
|
||||||
var disposeBag = Set<AnyCancellable>()
|
var disposeBag = Set<AnyCancellable>()
|
||||||
|
|
||||||
static let verticalMarginHeight: CGFloat = ComposeStatusAttachmentTableViewCell.removeButtonSize.height * 0.5
|
static let verticalMarginHeight: CGFloat = ComposeStatusAttachmentCollectionViewCell.removeButtonSize.height * 0.5
|
||||||
static let removeButtonSize = CGSize(width: 22, height: 22)
|
static let removeButtonSize = CGSize(width: 22, height: 22)
|
||||||
|
|
||||||
weak var delegate: ComposeStatusAttachmentTableViewCellDelegate?
|
weak var delegate: ComposeStatusAttachmentCollectionViewCellDelegate?
|
||||||
|
|
||||||
let attachmentContainerView = AttachmentContainerView()
|
let attachmentContainerView = AttachmentContainerView()
|
||||||
let removeButton: UIButton = {
|
let removeButton: UIButton = {
|
||||||
@ -31,7 +31,7 @@ final class ComposeStatusAttachmentTableViewCell: UITableViewCell {
|
|||||||
button.setImage(image, for: .normal)
|
button.setImage(image, for: .normal)
|
||||||
button.setBackgroundImage(.placeholder(color: Asset.Colors.Background.danger.color), for: .normal)
|
button.setBackgroundImage(.placeholder(color: Asset.Colors.Background.danger.color), for: .normal)
|
||||||
button.layer.masksToBounds = true
|
button.layer.masksToBounds = true
|
||||||
button.layer.cornerRadius = ComposeStatusAttachmentTableViewCell.removeButtonSize.width * 0.5
|
button.layer.cornerRadius = ComposeStatusAttachmentCollectionViewCell.removeButtonSize.width * 0.5
|
||||||
button.layer.borderColor = Asset.Colors.Background.dangerBorder.color.cgColor
|
button.layer.borderColor = Asset.Colors.Background.dangerBorder.color.cgColor
|
||||||
button.layer.borderWidth = 1
|
button.layer.borderWidth = 1
|
||||||
return button
|
return button
|
||||||
@ -41,11 +41,14 @@ final class ComposeStatusAttachmentTableViewCell: UITableViewCell {
|
|||||||
super.prepareForReuse()
|
super.prepareForReuse()
|
||||||
|
|
||||||
attachmentContainerView.activityIndicatorView.startAnimating()
|
attachmentContainerView.activityIndicatorView.startAnimating()
|
||||||
|
attachmentContainerView.previewImageView.af.cancelImageRequest()
|
||||||
|
attachmentContainerView.previewImageView.image = .placeholder(color: .systemFill)
|
||||||
delegate = nil
|
delegate = nil
|
||||||
|
disposeBag.removeAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
override init(frame: CGRect) {
|
||||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
super.init(frame: frame)
|
||||||
_init()
|
_init()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,18 +59,18 @@ final class ComposeStatusAttachmentTableViewCell: UITableViewCell {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ComposeStatusAttachmentTableViewCell {
|
extension ComposeStatusAttachmentCollectionViewCell {
|
||||||
|
|
||||||
private func _init() {
|
private func _init() {
|
||||||
selectionStyle = .none
|
// selectionStyle = .none
|
||||||
|
|
||||||
attachmentContainerView.translatesAutoresizingMaskIntoConstraints = false
|
attachmentContainerView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
contentView.addSubview(attachmentContainerView)
|
contentView.addSubview(attachmentContainerView)
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
attachmentContainerView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: ComposeStatusAttachmentTableViewCell.verticalMarginHeight),
|
attachmentContainerView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: ComposeStatusAttachmentCollectionViewCell.verticalMarginHeight),
|
||||||
attachmentContainerView.leadingAnchor.constraint(equalTo: contentView.readableContentGuide.leadingAnchor),
|
attachmentContainerView.leadingAnchor.constraint(equalTo: contentView.readableContentGuide.leadingAnchor),
|
||||||
attachmentContainerView.trailingAnchor.constraint(equalTo: contentView.readableContentGuide.trailingAnchor),
|
attachmentContainerView.trailingAnchor.constraint(equalTo: contentView.readableContentGuide.trailingAnchor),
|
||||||
contentView.bottomAnchor.constraint(equalTo: attachmentContainerView.bottomAnchor, constant: ComposeStatusAttachmentTableViewCell.verticalMarginHeight),
|
contentView.bottomAnchor.constraint(equalTo: attachmentContainerView.bottomAnchor, constant: ComposeStatusAttachmentCollectionViewCell.verticalMarginHeight),
|
||||||
attachmentContainerView.heightAnchor.constraint(equalToConstant: 205).priority(.defaultHigh),
|
attachmentContainerView.heightAnchor.constraint(equalToConstant: 205).priority(.defaultHigh),
|
||||||
])
|
])
|
||||||
|
|
||||||
@ -76,21 +79,21 @@ extension ComposeStatusAttachmentTableViewCell {
|
|||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
removeButton.centerXAnchor.constraint(equalTo: attachmentContainerView.trailingAnchor),
|
removeButton.centerXAnchor.constraint(equalTo: attachmentContainerView.trailingAnchor),
|
||||||
removeButton.centerYAnchor.constraint(equalTo: attachmentContainerView.topAnchor),
|
removeButton.centerYAnchor.constraint(equalTo: attachmentContainerView.topAnchor),
|
||||||
removeButton.widthAnchor.constraint(equalToConstant: ComposeStatusAttachmentTableViewCell.removeButtonSize.width).priority(.defaultHigh),
|
removeButton.widthAnchor.constraint(equalToConstant: ComposeStatusAttachmentCollectionViewCell.removeButtonSize.width).priority(.defaultHigh),
|
||||||
removeButton.heightAnchor.constraint(equalToConstant: ComposeStatusAttachmentTableViewCell.removeButtonSize.height).priority(.defaultHigh),
|
removeButton.heightAnchor.constraint(equalToConstant: ComposeStatusAttachmentCollectionViewCell.removeButtonSize.height).priority(.defaultHigh),
|
||||||
])
|
])
|
||||||
|
|
||||||
removeButton.addTarget(self, action: #selector(ComposeStatusAttachmentTableViewCell.removeButtonDidPressed(_:)), for: .touchUpInside)
|
removeButton.addTarget(self, action: #selector(ComposeStatusAttachmentCollectionViewCell.removeButtonDidPressed(_:)), for: .touchUpInside)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extension ComposeStatusAttachmentTableViewCell {
|
extension ComposeStatusAttachmentCollectionViewCell {
|
||||||
|
|
||||||
@objc private func removeButtonDidPressed(_ sender: UIButton) {
|
@objc private func removeButtonDidPressed(_ sender: UIButton) {
|
||||||
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
|
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
|
||||||
delegate?.composeStatusAttachmentTableViewCell(self, removeButtonDidPressed: sender)
|
delegate?.composeStatusAttachmentCollectionViewCell(self, removeButtonDidPressed: sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// ComposeStatusContentTableViewCell.swift
|
// ComposeStatusContentCollectionViewCell.swift
|
||||||
// Mastodon
|
// Mastodon
|
||||||
//
|
//
|
||||||
// Created by MainasuK Cirno on 2021-3-11.
|
// Created by MainasuK Cirno on 2021-3-11.
|
||||||
@ -9,7 +9,7 @@ import UIKit
|
|||||||
import Combine
|
import Combine
|
||||||
import TwitterTextEditor
|
import TwitterTextEditor
|
||||||
|
|
||||||
final class ComposeStatusContentTableViewCell: UITableViewCell {
|
final class ComposeStatusContentCollectionViewCell: UICollectionViewCell {
|
||||||
|
|
||||||
var disposeBag = Set<AnyCancellable>()
|
var disposeBag = Set<AnyCancellable>()
|
||||||
|
|
||||||
@ -27,8 +27,8 @@ final class ComposeStatusContentTableViewCell: UITableViewCell {
|
|||||||
|
|
||||||
let composeContent = PassthroughSubject<String, Never>()
|
let composeContent = PassthroughSubject<String, Never>()
|
||||||
|
|
||||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
override init(frame: CGRect) {
|
||||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
super.init(frame: frame)
|
||||||
_init()
|
_init()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,10 +39,11 @@ final class ComposeStatusContentTableViewCell: UITableViewCell {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ComposeStatusContentTableViewCell {
|
extension ComposeStatusContentCollectionViewCell {
|
||||||
|
|
||||||
private func _init() {
|
private func _init() {
|
||||||
selectionStyle = .none
|
// selectionStyle = .none
|
||||||
|
preservesSuperviewLayoutMargins = true
|
||||||
|
|
||||||
statusView.translatesAutoresizingMaskIntoConstraints = false
|
statusView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
contentView.addSubview(statusView)
|
contentView.addSubview(statusView)
|
||||||
@ -82,12 +83,8 @@ extension ComposeStatusContentTableViewCell {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ComposeStatusContentTableViewCell {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - UITextViewDelegate
|
// MARK: - UITextViewDelegate
|
||||||
extension ComposeStatusContentTableViewCell: TextEditorViewChangeObserver {
|
extension ComposeStatusContentCollectionViewCell: TextEditorViewChangeObserver {
|
||||||
func textEditorView(_ textEditorView: TextEditorView, didChangeWithChangeResult changeResult: TextEditorViewChangeResult) {
|
func textEditorView(_ textEditorView: TextEditorView, didChangeWithChangeResult changeResult: TextEditorViewChangeResult) {
|
||||||
guard changeResult.isTextChanged else { return }
|
guard changeResult.isTextChanged else { return }
|
||||||
composeContent.send(textEditorView.text)
|
composeContent.send(textEditorView.text)
|
@ -39,15 +39,14 @@ final class ComposeViewController: UIViewController, NeedsDependency {
|
|||||||
return barButtonItem
|
return barButtonItem
|
||||||
}()
|
}()
|
||||||
|
|
||||||
let tableView: UITableView = {
|
let collectionView: UICollectionView = {
|
||||||
let tableView = ControlContainableTableView()
|
let collectionViewLayout = ComposeViewController.createLayout()
|
||||||
tableView.register(ComposeRepliedToTootContentTableViewCell.self, forCellReuseIdentifier: String(describing: ComposeRepliedToTootContentTableViewCell.self))
|
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: collectionViewLayout)
|
||||||
tableView.register(ComposeStatusContentTableViewCell.self, forCellReuseIdentifier: String(describing: ComposeStatusContentTableViewCell.self))
|
collectionView.register(ComposeRepliedToTootContentCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: ComposeRepliedToTootContentCollectionViewCell.self))
|
||||||
tableView.register(ComposeStatusAttachmentTableViewCell.self, forCellReuseIdentifier: String(describing: ComposeStatusAttachmentTableViewCell.self))
|
collectionView.register(ComposeStatusContentCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: ComposeStatusContentCollectionViewCell.self))
|
||||||
tableView.rowHeight = UITableView.automaticDimension
|
collectionView.register(ComposeStatusAttachmentCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: ComposeStatusAttachmentCollectionViewCell.self))
|
||||||
tableView.separatorStyle = .none
|
collectionView.backgroundColor = Asset.Colors.Background.systemBackground.color
|
||||||
tableView.showsVerticalScrollIndicator = false
|
return collectionView
|
||||||
return tableView
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
let composeToolbarView: ComposeToolbarView = {
|
let composeToolbarView: ComposeToolbarView = {
|
||||||
@ -86,6 +85,20 @@ final class ComposeViewController: UIViewController, NeedsDependency {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension ComposeViewController {
|
||||||
|
private static func createLayout() -> UICollectionViewLayout {
|
||||||
|
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(100))
|
||||||
|
let item = NSCollectionLayoutItem(layoutSize: itemSize)
|
||||||
|
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(100))
|
||||||
|
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
|
||||||
|
let section = NSCollectionLayoutSection(group: group)
|
||||||
|
section.contentInsetsReference = .readableContent
|
||||||
|
// section.interGroupSpacing = 10
|
||||||
|
// section.contentInsets = NSDirectionalEdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10)
|
||||||
|
return UICollectionViewCompositionalLayout(section: section)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extension ComposeViewController {
|
extension ComposeViewController {
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
@ -103,13 +116,13 @@ extension ComposeViewController {
|
|||||||
navigationItem.rightBarButtonItem = publishBarButtonItem
|
navigationItem.rightBarButtonItem = publishBarButtonItem
|
||||||
publishButton.addTarget(self, action: #selector(ComposeViewController.publishBarButtonItemPressed(_:)), for: .touchUpInside)
|
publishButton.addTarget(self, action: #selector(ComposeViewController.publishBarButtonItemPressed(_:)), for: .touchUpInside)
|
||||||
|
|
||||||
tableView.translatesAutoresizingMaskIntoConstraints = false
|
collectionView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
view.addSubview(tableView)
|
view.addSubview(collectionView)
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
tableView.topAnchor.constraint(equalTo: view.topAnchor),
|
collectionView.topAnchor.constraint(equalTo: view.topAnchor),
|
||||||
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||||
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
||||||
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
|
collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
|
||||||
])
|
])
|
||||||
|
|
||||||
composeToolbarView.translatesAutoresizingMaskIntoConstraints = false
|
composeToolbarView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
@ -133,9 +146,11 @@ extension ComposeViewController {
|
|||||||
view.bottomAnchor.constraint(equalTo: composeToolbarBackgroundView.bottomAnchor),
|
view.bottomAnchor.constraint(equalTo: composeToolbarBackgroundView.bottomAnchor),
|
||||||
])
|
])
|
||||||
|
|
||||||
tableView.delegate = self
|
collectionView.delegate = self
|
||||||
|
let longPressReorderGesture = UILongPressGestureRecognizer(target: self, action: #selector(ComposeViewController.longPressReorderGestureHandler(_:)))
|
||||||
|
collectionView.addGestureRecognizer(longPressReorderGesture)
|
||||||
viewModel.setupDiffableDataSource(
|
viewModel.setupDiffableDataSource(
|
||||||
for: tableView,
|
for: collectionView,
|
||||||
dependency: self,
|
dependency: self,
|
||||||
textEditorViewTextAttributesDelegate: self,
|
textEditorViewTextAttributesDelegate: self,
|
||||||
composeStatusAttachmentTableViewCellDelegate: self
|
composeStatusAttachmentTableViewCellDelegate: self
|
||||||
@ -151,45 +166,45 @@ extension ComposeViewController {
|
|||||||
)
|
)
|
||||||
.sink(receiveValue: { [weak self] isShow, state, endFrame in
|
.sink(receiveValue: { [weak self] isShow, state, endFrame in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
|
|
||||||
guard isShow, state == .dock else {
|
guard isShow, state == .dock else {
|
||||||
self.tableView.contentInset.bottom = 0.0
|
self.collectionView.contentInset.bottom = self.view.safeAreaInsets.bottom
|
||||||
self.tableView.verticalScrollIndicatorInsets.bottom = 0.0
|
self.collectionView.verticalScrollIndicatorInsets.bottom = self.view.safeAreaInsets.bottom
|
||||||
UIView.animate(withDuration: 0.3) {
|
UIView.animate(withDuration: 0.3) {
|
||||||
self.composeToolbarViewBottomLayoutConstraint.constant = 0.0
|
self.composeToolbarViewBottomLayoutConstraint.constant = self.view.safeAreaInsets.bottom
|
||||||
self.view.layoutIfNeeded()
|
self.view.layoutIfNeeded()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// isShow AND dock state
|
// isShow AND dock state
|
||||||
let contentFrame = self.view.convert(self.tableView.frame, to: nil)
|
let contentFrame = self.view.convert(self.collectionView.frame, to: nil)
|
||||||
let padding = contentFrame.maxY - endFrame.minY
|
let padding = contentFrame.maxY - endFrame.minY
|
||||||
guard padding > 0 else {
|
guard padding > 0 else {
|
||||||
self.tableView.contentInset.bottom = 0.0
|
self.collectionView.contentInset.bottom = self.view.safeAreaInsets.bottom
|
||||||
self.tableView.verticalScrollIndicatorInsets.bottom = 0.0
|
self.collectionView.verticalScrollIndicatorInsets.bottom = self.view.safeAreaInsets.bottom
|
||||||
UIView.animate(withDuration: 0.3) {
|
UIView.animate(withDuration: 0.3) {
|
||||||
self.composeToolbarViewBottomLayoutConstraint.constant = 0.0
|
self.composeToolbarViewBottomLayoutConstraint.constant = self.view.safeAreaInsets.bottom
|
||||||
self.view.layoutIfNeeded()
|
self.view.layoutIfNeeded()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// add 16pt margin
|
// add 16pt margin
|
||||||
self.tableView.contentInset.bottom = padding + 16
|
self.collectionView.contentInset.bottom = padding + 16
|
||||||
self.tableView.verticalScrollIndicatorInsets.bottom = padding + 16
|
self.collectionView.verticalScrollIndicatorInsets.bottom = padding + 16
|
||||||
UIView.animate(withDuration: 0.3) {
|
UIView.animate(withDuration: 0.3) {
|
||||||
self.composeToolbarViewBottomLayoutConstraint.constant = padding
|
self.composeToolbarViewBottomLayoutConstraint.constant = padding
|
||||||
self.view.layoutIfNeeded()
|
self.view.layoutIfNeeded()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
|
|
||||||
viewModel.isPublishBarButtonItemEnabled
|
viewModel.isPublishBarButtonItemEnabled
|
||||||
.receive(on: DispatchQueue.main)
|
.receive(on: DispatchQueue.main)
|
||||||
.assign(to: \.isEnabled, on: publishBarButtonItem)
|
.assign(to: \.isEnabled, on: publishBarButtonItem)
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
|
|
||||||
// bind custom emojis
|
// bind custom emojis
|
||||||
viewModel.customEmojiViewModel
|
viewModel.customEmojiViewModel
|
||||||
.compactMap { $0?.emojis }
|
.compactMap { $0?.emojis }
|
||||||
@ -203,7 +218,7 @@ extension ComposeViewController {
|
|||||||
self.textEditorView()?.setNeedsUpdateTextAttributes()
|
self.textEditorView()?.setNeedsUpdateTextAttributes()
|
||||||
})
|
})
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
|
|
||||||
// bind image picker toolbar state
|
// bind image picker toolbar state
|
||||||
viewModel.attachmentServices
|
viewModel.attachmentServices
|
||||||
.receive(on: DispatchQueue.main)
|
.receive(on: DispatchQueue.main)
|
||||||
@ -236,7 +251,7 @@ extension ComposeViewController {
|
|||||||
switch item {
|
switch item {
|
||||||
case .input:
|
case .input:
|
||||||
guard let indexPath = diffableDataSource.indexPath(for: item),
|
guard let indexPath = diffableDataSource.indexPath(for: item),
|
||||||
let cell = tableView.cellForRow(at: indexPath) as? ComposeStatusContentTableViewCell else {
|
let cell = collectionView.cellForItem(at: indexPath) as? ComposeStatusContentCollectionViewCell else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return cell.textEditorView
|
return cell.textEditorView
|
||||||
@ -306,6 +321,33 @@ extension ComposeViewController {
|
|||||||
dismiss(animated: true, completion: nil)
|
dismiss(animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@objc private func longPressReorderGestureHandler(_ sender: UILongPressGestureRecognizer) {
|
||||||
|
switch(sender.state) {
|
||||||
|
case .began:
|
||||||
|
guard let selectedIndexPath = collectionView.indexPathForItem(at: sender.location(in: collectionView)) else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
collectionView.beginInteractiveMovementForItem(at: selectedIndexPath)
|
||||||
|
case .changed:
|
||||||
|
guard let selectedIndexPath = collectionView.indexPathForItem(at: sender.location(in: collectionView)),
|
||||||
|
let diffableDataSource = viewModel.diffableDataSource else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
guard let item = diffableDataSource.itemIdentifier(for: selectedIndexPath),
|
||||||
|
case .attachment = item else {
|
||||||
|
collectionView.cancelInteractiveMovement()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
collectionView.updateInteractiveMovementTargetPosition(sender.location(in: collectionView))
|
||||||
|
case .ended:
|
||||||
|
collectionView.endInteractiveMovement()
|
||||||
|
default:
|
||||||
|
collectionView.cancelInteractiveMovement()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - TextEditorViewTextAttributesDelegate
|
// MARK: - TextEditorViewTextAttributesDelegate
|
||||||
@ -476,10 +518,8 @@ extension ComposeViewController: ComposeToolbarViewDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - UITableViewDelegate
|
// MARK: - UITableViewDelegate
|
||||||
extension ComposeViewController: UITableViewDelegate {
|
extension ComposeViewController: UICollectionViewDelegate {
|
||||||
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
|
|
||||||
return UITableView.automaticDimension
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - UIAdaptivePresentationControllerDelegate
|
// MARK: - UIAdaptivePresentationControllerDelegate
|
||||||
@ -565,11 +605,11 @@ extension ComposeViewController: UIDocumentPickerDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - ComposeStatusAttachmentTableViewCellDelegate
|
// MARK: - ComposeStatusAttachmentTableViewCellDelegate
|
||||||
extension ComposeViewController: ComposeStatusAttachmentTableViewCellDelegate {
|
extension ComposeViewController: ComposeStatusAttachmentCollectionViewCellDelegate {
|
||||||
|
|
||||||
func composeStatusAttachmentTableViewCell(_ cell: ComposeStatusAttachmentTableViewCell, removeButtonDidPressed button: UIButton) {
|
func composeStatusAttachmentCollectionViewCell(_ cell: ComposeStatusAttachmentCollectionViewCell, removeButtonDidPressed button: UIButton) {
|
||||||
guard let diffableDataSource = viewModel.diffableDataSource else { return }
|
guard let diffableDataSource = viewModel.diffableDataSource else { return }
|
||||||
guard let indexPath = tableView.indexPath(for: cell) else { return }
|
guard let indexPath = collectionView.indexPath(for: cell) else { return }
|
||||||
guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return }
|
guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return }
|
||||||
guard case let .attachment(attachmentService) = item else { return }
|
guard case let .attachment(attachmentService) = item else { return }
|
||||||
|
|
||||||
|
@ -11,13 +11,13 @@ import TwitterTextEditor
|
|||||||
extension ComposeViewModel {
|
extension ComposeViewModel {
|
||||||
|
|
||||||
func setupDiffableDataSource(
|
func setupDiffableDataSource(
|
||||||
for tableView: UITableView,
|
for collectionView: UICollectionView,
|
||||||
dependency: NeedsDependency,
|
dependency: NeedsDependency,
|
||||||
textEditorViewTextAttributesDelegate: TextEditorViewTextAttributesDelegate,
|
textEditorViewTextAttributesDelegate: TextEditorViewTextAttributesDelegate,
|
||||||
composeStatusAttachmentTableViewCellDelegate: ComposeStatusAttachmentTableViewCellDelegate
|
composeStatusAttachmentTableViewCellDelegate: ComposeStatusAttachmentCollectionViewCellDelegate
|
||||||
) {
|
) {
|
||||||
diffableDataSource = ComposeStatusSection.tableViewDiffableDataSource(
|
let diffableDataSource = ComposeStatusSection.collectionViewDiffableDataSource(
|
||||||
for: tableView,
|
for: collectionView,
|
||||||
dependency: dependency,
|
dependency: dependency,
|
||||||
managedObjectContext: context.managedObjectContext,
|
managedObjectContext: context.managedObjectContext,
|
||||||
composeKind: composeKind,
|
composeKind: composeKind,
|
||||||
@ -25,6 +25,26 @@ extension ComposeViewModel {
|
|||||||
composeStatusAttachmentTableViewCellDelegate: composeStatusAttachmentTableViewCellDelegate
|
composeStatusAttachmentTableViewCellDelegate: composeStatusAttachmentTableViewCellDelegate
|
||||||
)
|
)
|
||||||
|
|
||||||
|
diffableDataSource.reorderingHandlers.canReorderItem = { item in
|
||||||
|
switch item {
|
||||||
|
case .attachment: return true
|
||||||
|
default: return false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
diffableDataSource.reorderingHandlers.didReorder = { [weak self] transaction in
|
||||||
|
guard let self = self else { return }
|
||||||
|
|
||||||
|
let items = transaction.finalSnapshot.itemIdentifiers
|
||||||
|
var attachmentServices: [MastodonAttachmentService] = []
|
||||||
|
for item in items {
|
||||||
|
guard case let .attachment(attachmentService) = item else { continue }
|
||||||
|
attachmentServices.append(attachmentService)
|
||||||
|
}
|
||||||
|
self.attachmentServices.value = attachmentServices
|
||||||
|
}
|
||||||
|
self.diffableDataSource = diffableDataSource
|
||||||
|
|
||||||
var snapshot = NSDiffableDataSourceSnapshot<ComposeStatusSection, ComposeStatusItem>()
|
var snapshot = NSDiffableDataSourceSnapshot<ComposeStatusSection, ComposeStatusItem>()
|
||||||
snapshot.appendSections([.repliedTo, .status, .attachment])
|
snapshot.appendSections([.repliedTo, .status, .attachment])
|
||||||
switch composeKind {
|
switch composeKind {
|
||||||
|
@ -23,7 +23,8 @@ final class ComposeViewModel {
|
|||||||
let activeAuthenticationBox: CurrentValueSubject<AuthenticationService.MastodonAuthenticationBox?, Never>
|
let activeAuthenticationBox: CurrentValueSubject<AuthenticationService.MastodonAuthenticationBox?, Never>
|
||||||
|
|
||||||
// output
|
// output
|
||||||
var diffableDataSource: UITableViewDiffableDataSource<ComposeStatusSection, ComposeStatusItem>!
|
//var diffableDataSource: UITableViewDiffableDataSource<ComposeStatusSection, ComposeStatusItem>!
|
||||||
|
var diffableDataSource: UICollectionViewDiffableDataSource<ComposeStatusSection, ComposeStatusItem>!
|
||||||
private(set) lazy var publishStateMachine: GKStateMachine = {
|
private(set) lazy var publishStateMachine: GKStateMachine = {
|
||||||
// exclude timeline middle fetcher state
|
// exclude timeline middle fetcher state
|
||||||
let stateMachine = GKStateMachine(states: [
|
let stateMachine = GKStateMachine(states: [
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
//
|
|
||||||
// ComposeRepliedToTootContentTableViewCell.swift
|
|
||||||
// Mastodon
|
|
||||||
//
|
|
||||||
// Created by MainasuK Cirno on 2021-3-11.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
final class ComposeRepliedToTootContentTableViewCell: UITableViewCell {
|
|
||||||
|
|
||||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
|
||||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
|
||||||
_init()
|
|
||||||
}
|
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
|
||||||
super.init(coder: coder)
|
|
||||||
_init()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extension ComposeRepliedToTootContentTableViewCell {
|
|
||||||
|
|
||||||
private func _init() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -76,10 +76,10 @@ extension MastodonAttachmentService.UploadState {
|
|||||||
service.error.send(error)
|
service.error.send(error)
|
||||||
case .finished:
|
case .finished:
|
||||||
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: upload attachment success", ((#file as NSString).lastPathComponent), #line, #function)
|
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: upload attachment success", ((#file as NSString).lastPathComponent), #line, #function)
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
} receiveValue: { response in
|
} receiveValue: { response in
|
||||||
|
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: upload attachment %s success: %s", ((#file as NSString).lastPathComponent), #line, #function, response.value.id, response.value.url)
|
||||||
service.attachment.value = response.value
|
service.attachment.value = response.value
|
||||||
stateMachine.enter(Finish.self)
|
stateMachine.enter(Finish.self)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user