Store attachments in post drafts

This commit is contained in:
Shadowfacts 2019-02-22 13:53:38 -05:00
parent 9efc58225c
commit 8b24457d96
Signed by untrusted user: shadowfacts
GPG Key ID: 83FB3304046BADA4
5 changed files with 131 additions and 30 deletions

View File

@ -37,8 +37,8 @@ class DraftsManager: Codable {
return drafts.sorted(by: { $0.lastModified > $1.lastModified }) return drafts.sorted(by: { $0.lastModified > $1.lastModified })
} }
func create(text: String) { func create(text: String, attachments: [DraftAttachment]) {
drafts.append(Draft(text: text, lastModified: Date())) drafts.append(Draft(text: text, lastModified: Date(), attachments: attachments))
} }
func remove(_ draft: Draft) { func remove(_ draft: Draft) {
@ -53,20 +53,29 @@ extension DraftsManager {
let id: UUID let id: UUID
private(set) var text: String private(set) var text: String
private(set) var lastModified: Date private(set) var lastModified: Date
private(set) var attachments: [DraftAttachment]
init(text: String, lastModified: Date) { init(text: String, lastModified: Date, attachments: [DraftAttachment]) {
self.id = UUID() self.id = UUID()
self.text = text self.text = text
self.lastModified = lastModified self.lastModified = lastModified
self.attachments = attachments
} }
func update(text: String) { func update(text: String, attachments: [DraftAttachment]) {
self.text = text self.text = text
self.lastModified = Date() self.lastModified = Date()
self.attachments = attachments
} }
static func ==(lhs: Draft, rhs: Draft) -> Bool { static func ==(lhs: Draft, rhs: Draft) -> Bool {
return lhs.id == rhs.id return lhs.id == rhs.id
} }
} }
struct DraftAttachment: Codable {
/// The local identifier of the PHAsset for this attachment
let assetIdentifier: String
let description: String
}
} }

View File

@ -272,12 +272,19 @@ class ComposeViewController: UIViewController {
} }
func saveDraft() { func saveDraft() {
// TODO: save attachmenst to drafts
// TODO: save CW to draft // TODO: save CW to draft
if let currentDraft = currentDraft { var attachments = [DraftsManager.DraftAttachment]()
currentDraft.update(text: statusTextView.text) for asset in selectedAssets {
let index = attachments.count
let mediaView = attachmentsStackView.arrangedSubviews[index] as! ComposeMediaView
let description = mediaView.descriptionTextView.text!
attachments.append(DraftsManager.DraftAttachment(assetIdentifier: asset.localIdentifier, description: description))
}
if let currentDraft = self.currentDraft {
currentDraft.update(text: self.statusTextView.text, attachments: attachments)
} else { } else {
DraftsManager.shared.create(text: statusTextView.text) DraftsManager.shared.create(text: self.statusTextView.text, attachments: attachments)
} }
} }
@ -520,8 +527,26 @@ extension ComposeViewController: DraftsTableViewControllerDelegate {
func draftSelected(_ draft: DraftsManager.Draft) { func draftSelected(_ draft: DraftsManager.Draft) {
self.currentDraft = draft self.currentDraft = draft
statusTextView.text = draft.text statusTextView.text = draft.text
updatePlaceholder() updatePlaceholder()
updateCharactersRemaining() updateCharactersRemaining()
let result = PHAsset.fetchAssets(withLocalIdentifiers: draft.attachments.map { $0.assetIdentifier }, options: nil)
self.selectedAssets = []
var i = 0
while i < result.count {
selectedAssets.append(result[i])
i += 1
}
updateAttachmentViews()
var j = 0
for subview in attachmentsStackView.arrangedSubviews {
guard let mediaView = subview as? ComposeMediaView else { continue }
mediaView.descriptionTextView.text = draft.attachments[j].description
mediaView.textViewDidChange(mediaView.descriptionTextView)
j += 1
}
} }
} }

View File

@ -7,15 +7,43 @@
// //
import UIKit import UIKit
import Photos
class DraftTableViewCell: UITableViewCell { class DraftTableViewCell: UITableViewCell {
@IBOutlet weak var contentLabel: UILabel! @IBOutlet weak var contentLabel: UILabel!
@IBOutlet weak var lastModifiedLabel: UILabel! @IBOutlet weak var lastModifiedLabel: UILabel!
@IBOutlet weak var attachmentsStackViewContainer: UIView!
@IBOutlet weak var attachmentsStackView: UIStackView!
func updateUI(for draft: DraftsManager.Draft) { func updateUI(for draft: DraftsManager.Draft) {
contentLabel.text = draft.text contentLabel.text = draft.text
lastModifiedLabel.text = draft.lastModified.timeAgoString() lastModifiedLabel.text = draft.lastModified.timeAgoString()
attachmentsStackViewContainer.isHidden = draft.attachments.count == 0
let result = PHAsset.fetchAssets(withLocalIdentifiers: draft.attachments.map { $0.assetIdentifier }, options: nil)
var i = 0
while i < result.count {
let asset = result[i]
let size = CGSize(width: 50, height: 50)
let imageView = UIImageView(frame: CGRect(origin: .zero, size: size))
imageView.layer.masksToBounds = true
imageView.layer.cornerRadius = 5
attachmentsStackView.addArrangedSubview(imageView)
PHImageManager.default().requestImage(for: asset, targetSize: size, contentMode: .aspectFill, options: nil) { (image, _) in
imageView.image = image
}
i += 1
}
}
override func prepareForReuse() {
super.prepareForReuse()
attachmentsStackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
} }
} }

View File

@ -10,40 +10,76 @@
<objects> <objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/> <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="Q7N-Mt-RPF" customClass="DraftTableViewCell" customModule="Tusker" customModuleProvider="target"> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="109" id="Q7N-Mt-RPF" customClass="DraftTableViewCell" customModule="Tusker" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/> <rect key="frame" x="0.0" y="0.0" width="375" height="109"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Q7N-Mt-RPF" id="KVi-jA-AET"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Q7N-Mt-RPF" id="KVi-jA-AET">
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/> <rect key="frame" x="0.0" y="0.0" width="375" height="108.5"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Content" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8eA-yd-rBp"> <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="gaD-3B-qO1">
<rect key="frame" x="16" y="11" width="302" height="22"/> <rect key="frame" x="16" y="11" width="351" height="89.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/> <subviews>
<nil key="textColor"/> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="zMS-88-DcM">
<nil key="highlightedColor"/> <rect key="frame" x="0.0" y="0.0" width="351" height="31.5"/>
</label> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" text="2m" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="D2X-9O-iQw"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Content" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8eA-yd-rBp">
<rect key="frame" x="334" y="11" width="25" height="21"/> <rect key="frame" x="0.0" y="0.0" width="310.5" height="31.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/> <fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <nil key="textColor"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" text="2m" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="D2X-9O-iQw">
<rect key="frame" x="326.5" y="0.0" width="24.5" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="D2X-9O-iQw" firstAttribute="leading" secondItem="8eA-yd-rBp" secondAttribute="trailing" constant="16" id="6Ux-ee-J5h"/>
<constraint firstAttribute="trailing" secondItem="D2X-9O-iQw" secondAttribute="trailing" id="IRH-mM-HSs"/>
<constraint firstItem="8eA-yd-rBp" firstAttribute="leading" secondItem="zMS-88-DcM" secondAttribute="leading" id="StS-F9-9B3"/>
<constraint firstItem="8eA-yd-rBp" firstAttribute="top" secondItem="zMS-88-DcM" secondAttribute="top" id="Uuq-g5-n0A"/>
<constraint firstItem="D2X-9O-iQw" firstAttribute="top" secondItem="zMS-88-DcM" secondAttribute="top" id="lWB-6Z-nbG"/>
<constraint firstAttribute="bottom" secondItem="8eA-yd-rBp" secondAttribute="bottom" id="zCK-s5-4Zo"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="csc-gx-KVg">
<rect key="frame" x="0.0" y="39.5" width="351" height="50"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="htC-hf-vJ4">
<rect key="frame" x="8" y="0.0" width="359" height="50"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="lxT-O2-afE"/>
</constraints>
</stackView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="htC-hf-vJ4" firstAttribute="leading" secondItem="csc-gx-KVg" secondAttribute="leading" id="c0s-O9-XKa"/>
<constraint firstItem="htC-hf-vJ4" firstAttribute="top" secondItem="csc-gx-KVg" secondAttribute="top" id="lcl-RN-qHw"/>
<constraint firstAttribute="bottom" secondItem="htC-hf-vJ4" secondAttribute="bottom" id="oHX-Qh-bmI"/>
</constraints>
</view>
</subviews>
</stackView>
</subviews> </subviews>
<constraints> <constraints>
<constraint firstAttribute="bottomMargin" secondItem="8eA-yd-rBp" secondAttribute="bottom" priority="999" id="DEM-HZ-jff"/> <constraint firstAttribute="bottom" secondItem="gaD-3B-qO1" secondAttribute="bottomMargin" constant="8" id="4Hz-ax-JI6"/>
<constraint firstItem="8eA-yd-rBp" firstAttribute="leading" secondItem="KVi-jA-AET" secondAttribute="leadingMargin" id="Doq-4D-KSu"/> <constraint firstItem="gaD-3B-qO1" firstAttribute="leading" secondItem="KVi-jA-AET" secondAttribute="leadingMargin" id="KRA-Q8-klX"/>
<constraint firstItem="D2X-9O-iQw" firstAttribute="leading" secondItem="8eA-yd-rBp" secondAttribute="trailing" constant="16" id="H9K-4w-Bhi"/> <constraint firstAttribute="trailing" secondItem="gaD-3B-qO1" secondAttribute="trailingMargin" constant="8" id="iGc-c4-n9y"/>
<constraint firstItem="D2X-9O-iQw" firstAttribute="top" secondItem="KVi-jA-AET" secondAttribute="topMargin" id="ZI4-HN-ar2"/> <constraint firstItem="gaD-3B-qO1" firstAttribute="top" secondItem="KVi-jA-AET" secondAttribute="topMargin" id="rVE-Jo-6zG"/>
<constraint firstAttribute="trailingMargin" secondItem="D2X-9O-iQw" secondAttribute="trailing" id="cCQ-XZ-ojE"/>
<constraint firstItem="8eA-yd-rBp" firstAttribute="top" secondItem="KVi-jA-AET" secondAttribute="topMargin" id="yco-33-WZZ"/>
</constraints> </constraints>
</tableViewCellContentView> </tableViewCellContentView>
<connections> <connections>
<outlet property="attachmentsStackView" destination="htC-hf-vJ4" id="kEX-m7-LuE"/>
<outlet property="attachmentsStackViewContainer" destination="csc-gx-KVg" id="rIM-pj-TFX"/>
<outlet property="contentLabel" destination="8eA-yd-rBp" id="Uy0-8G-WbU"/> <outlet property="contentLabel" destination="8eA-yd-rBp" id="Uy0-8G-WbU"/>
<outlet property="lastModifiedLabel" destination="D2X-9O-iQw" id="dx7-0E-RuM"/> <outlet property="lastModifiedLabel" destination="D2X-9O-iQw" id="dx7-0E-RuM"/>
</connections> </connections>
<point key="canvasLocation" x="-388" y="141"/> <point key="canvasLocation" x="-388" y="169.56521739130437"/>
</tableViewCell> </tableViewCell>
</objects> </objects>
</document> </document>

View File

@ -31,6 +31,9 @@ class DraftsTableViewController: UITableViewController {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 140
tableView.register(UINib(nibName: "DraftTableViewCell", bundle: nil), forCellReuseIdentifier: "draftCell") tableView.register(UINib(nibName: "DraftTableViewCell", bundle: nil), forCellReuseIdentifier: "draftCell")
} }