Compare commits
8 Commits
0691c3b9d6
...
e3cc0df283
Author | SHA1 | Date |
---|---|---|
Shadowfacts | e3cc0df283 | |
Shadowfacts | 9ed05de3ee | |
Shadowfacts | 64f41ea2b7 | |
Shadowfacts | 9af4118dfc | |
Shadowfacts | 64a8f6d733 | |
Shadowfacts | ca76568c79 | |
Shadowfacts | 18e91feb00 | |
Shadowfacts | c5d2e9af68 |
|
@ -29,15 +29,15 @@ public class Attachment: Decodable {
|
|||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.id = try container.decode(String.self, forKey: .id)
|
||||
self.kind = try container.decode(Kind.self, forKey: .kind)
|
||||
self.url = URL(lenient: try container.decode(String.self, forKey: .url))!
|
||||
self.url = URL(string: try container.decode(String.self, forKey: .url))!
|
||||
self.previewURL = URL(string: try container.decode(String.self, forKey: .previewURL))!
|
||||
if let remote = try? container.decode(String.self, forKey: .remoteURL) {
|
||||
self.remoteURL = URL(lenient: remote.replacingOccurrences(of: " ", with: "%20"))
|
||||
self.remoteURL = URL(string: remote)!
|
||||
} else {
|
||||
self.remoteURL = nil
|
||||
}
|
||||
self.previewURL = URL(lenient: try container.decode(String.self, forKey: .previewURL).replacingOccurrences(of: " ", with: "%20"))!
|
||||
if let text = try? container.decode(String.self, forKey: .textURL) {
|
||||
self.textURL = URL(lenient: text.replacingOccurrences(of: " ", with: "%20"))
|
||||
self.textURL = URL(string: text)!
|
||||
} else {
|
||||
self.textURL = nil
|
||||
}
|
||||
|
@ -113,14 +113,3 @@ extension Attachment {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate extension URL {
|
||||
private static let allowedChars = CharacterSet.urlHostAllowed.union(.urlPathAllowed).union(.urlQueryAllowed)
|
||||
|
||||
init?(lenient string: String) {
|
||||
guard let escaped = string.addingPercentEncoding(withAllowedCharacters: URL.allowedChars) else {
|
||||
return nil
|
||||
}
|
||||
self.init(string: escaped)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
04ED00B121481ED800567C53 /* SteppedProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04ED00B021481ED800567C53 /* SteppedProgressView.swift */; };
|
||||
D6028B9B2150811100F223B9 /* MastodonCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6028B9A2150811100F223B9 /* MastodonCache.swift */; };
|
||||
D60309B52419D4F100A465FF /* ComposeAttachmentsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60309B42419D4F100A465FF /* ComposeAttachmentsViewController.swift */; };
|
||||
D60C07E421E8176B0057FAA8 /* ComposeMediaView.xib in Resources */ = {isa = PBXBuildFile; fileRef = D60C07E321E8176B0057FAA8 /* ComposeMediaView.xib */; };
|
||||
D60D2B8223844C71001B87A3 /* BaseStatusTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60D2B8123844C71001B87A3 /* BaseStatusTableViewCell.swift */; };
|
||||
D61099B42144B0CC00432DC2 /* Pachyderm.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D61099AB2144B0CC00432DC2 /* Pachyderm.framework */; };
|
||||
D61099BB2144B0CC00432DC2 /* PachydermTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61099BA2144B0CC00432DC2 /* PachydermTests.swift */; };
|
||||
|
@ -106,7 +105,6 @@
|
|||
D62D2426217ABF63005076CC /* UserActivityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62D2425217ABF63005076CC /* UserActivityType.swift */; };
|
||||
D62FF04823D7CDD700909D6E /* AttributedStringHelperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62FF04723D7CDD700909D6E /* AttributedStringHelperTests.swift */; };
|
||||
D6333B372137838300CE884A /* AttributedString+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6333B362137838300CE884A /* AttributedString+Helpers.swift */; };
|
||||
D6333B772138D94E00CE884A /* ComposeMediaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6333B762138D94E00CE884A /* ComposeMediaView.swift */; };
|
||||
D6333B792139AEFD00CE884A /* Date+TimeAgo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6333B782139AEFD00CE884A /* Date+TimeAgo.swift */; };
|
||||
D63569E023908A8D003DD353 /* StatusState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60A4FFB238B726A008AC647 /* StatusState.swift */; };
|
||||
D63661C02381C144004B9E16 /* PreferencesNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D63661BF2381C144004B9E16 /* PreferencesNavigationController.swift */; };
|
||||
|
@ -311,7 +309,6 @@
|
|||
D6028B9A2150811100F223B9 /* MastodonCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonCache.swift; sourceTree = "<group>"; };
|
||||
D60309B42419D4F100A465FF /* ComposeAttachmentsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeAttachmentsViewController.swift; sourceTree = "<group>"; };
|
||||
D60A4FFB238B726A008AC647 /* StatusState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusState.swift; sourceTree = "<group>"; };
|
||||
D60C07E321E8176B0057FAA8 /* ComposeMediaView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ComposeMediaView.xib; sourceTree = "<group>"; };
|
||||
D60D2B8123844C71001B87A3 /* BaseStatusTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseStatusTableViewCell.swift; sourceTree = "<group>"; };
|
||||
D61099AB2144B0CC00432DC2 /* Pachyderm.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pachyderm.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D61099AD2144B0CC00432DC2 /* Pachyderm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Pachyderm.h; sourceTree = "<group>"; };
|
||||
|
@ -393,7 +390,6 @@
|
|||
D62D2425217ABF63005076CC /* UserActivityType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserActivityType.swift; sourceTree = "<group>"; };
|
||||
D62FF04723D7CDD700909D6E /* AttributedStringHelperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringHelperTests.swift; sourceTree = "<group>"; };
|
||||
D6333B362137838300CE884A /* AttributedString+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AttributedString+Helpers.swift"; sourceTree = "<group>"; };
|
||||
D6333B762138D94E00CE884A /* ComposeMediaView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeMediaView.swift; sourceTree = "<group>"; };
|
||||
D6333B782139AEFD00CE884A /* Date+TimeAgo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+TimeAgo.swift"; sourceTree = "<group>"; };
|
||||
D63661BF2381C144004B9E16 /* PreferencesNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesNavigationController.swift; sourceTree = "<group>"; };
|
||||
D63F9C65241C4CC3004C03CF /* AddAttachmentTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AddAttachmentTableViewCell.xib; sourceTree = "<group>"; };
|
||||
|
@ -603,15 +599,6 @@
|
|||
path = Transitions;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D60C07E221E817560057FAA8 /* Compose Media */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D60C07E321E8176B0057FAA8 /* ComposeMediaView.xib */,
|
||||
D6333B762138D94E00CE884A /* ComposeMediaView.swift */,
|
||||
);
|
||||
path = "Compose Media";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D61099AC2144B0CC00432DC2 /* Pachyderm */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -707,6 +694,37 @@
|
|||
path = "Hashtag Cell";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D61959D0241E842400A37B8E /* Draft Cell */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D627FF7C217E958900CC0648 /* DraftTableViewCell.xib */,
|
||||
D627FF7E217E95E000CC0648 /* DraftTableViewCell.swift */,
|
||||
);
|
||||
path = "Draft Cell";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D61959D1241E844900A37B8E /* Attachment Cells */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D63F9C67241C4F79004C03CF /* AddAttachmentTableViewCell.swift */,
|
||||
D63F9C65241C4CC3004C03CF /* AddAttachmentTableViewCell.xib */,
|
||||
D63F9C69241C50B9004C03CF /* ComposeAttachmentTableViewCell.swift */,
|
||||
D63F9C6A241C50B9004C03CF /* ComposeAttachmentTableViewCell.xib */,
|
||||
);
|
||||
path = "Attachment Cells";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D61959D2241E846D00A37B8E /* Models */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D6285B5221EA708700FE4B39 /* StatusFormat.swift */,
|
||||
D620483123D2A6A3008A63EF /* CompositionState.swift */,
|
||||
D63F9C6D241D2D85004C03CF /* CompositionAttachment.swift */,
|
||||
D626493423BD94CE00612E6E /* CompositionAttachmentData.swift */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D61AC1DA232EA43100C54D2D /* Instance Cell */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -774,8 +792,6 @@
|
|||
children = (
|
||||
D627FF78217E950100CC0648 /* DraftsTableViewController.xib */,
|
||||
D627FF7A217E951500CC0648 /* DraftsTableViewController.swift */,
|
||||
D627FF7C217E958900CC0648 /* DraftTableViewCell.xib */,
|
||||
D627FF7E217E95E000CC0648 /* DraftTableViewCell.swift */,
|
||||
);
|
||||
path = Drafts;
|
||||
sourceTree = "<group>";
|
||||
|
@ -791,20 +807,6 @@
|
|||
path = Shortcuts;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D63F9C64241C4CAA004C03CF /* Attachments */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D63F9C6D241D2D85004C03CF /* CompositionAttachment.swift */,
|
||||
D626493423BD94CE00612E6E /* CompositionAttachmentData.swift */,
|
||||
D60309B42419D4F100A465FF /* ComposeAttachmentsViewController.swift */,
|
||||
D63F9C67241C4F79004C03CF /* AddAttachmentTableViewCell.swift */,
|
||||
D63F9C65241C4CC3004C03CF /* AddAttachmentTableViewCell.xib */,
|
||||
D63F9C69241C50B9004C03CF /* ComposeAttachmentTableViewCell.swift */,
|
||||
D63F9C6A241C50B9004C03CF /* ComposeAttachmentTableViewCell.xib */,
|
||||
);
|
||||
path = Attachments;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D641C780213DD7C4004B4513 /* Screens */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -816,6 +818,8 @@
|
|||
D641C785213DD83B004B4513 /* Conversation */,
|
||||
D641C786213DD852004B4513 /* Notifications */,
|
||||
D641C787213DD862004B4513 /* Compose */,
|
||||
D6B053A023BD2BED00A066FA /* Asset Picker */,
|
||||
D627FF77217E94F200CC0648 /* Drafts */,
|
||||
D627943C23A5635D00D38C68 /* Explore */,
|
||||
D6BC9DD8232D8BCA002CA326 /* Search */,
|
||||
D627944B23A9A02400D38C68 /* Lists */,
|
||||
|
@ -887,13 +891,9 @@
|
|||
D641C787213DD862004B4513 /* Compose */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D6B053A023BD2BED00A066FA /* Asset Picker */,
|
||||
D63F9C64241C4CAA004C03CF /* Attachments */,
|
||||
D627FF77217E94F200CC0648 /* Drafts */,
|
||||
D6A5FAF0217B7E05003DB2D9 /* ComposeViewController.xib */,
|
||||
D66362702136338600C9CBA2 /* ComposeViewController.swift */,
|
||||
D6285B5221EA708700FE4B39 /* StatusFormat.swift */,
|
||||
D620483123D2A6A3008A63EF /* CompositionState.swift */,
|
||||
D60309B42419D4F100A465FF /* ComposeAttachmentsViewController.swift */,
|
||||
);
|
||||
path = Compose;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1155,8 +1155,9 @@
|
|||
D627944623A6AC9300D38C68 /* BasicTableViewCell.xib */,
|
||||
D67C57A721E2649B00C3118B /* Account Detail */,
|
||||
D67C57B021E28F9400C3118B /* Compose Status Reply */,
|
||||
D60C07E221E817560057FAA8 /* Compose Media */,
|
||||
D626494023C122C800612E6E /* Asset Picker */,
|
||||
D61959D1241E844900A37B8E /* Attachment Cells */,
|
||||
D61959D0241E842400A37B8E /* Draft Cell */,
|
||||
D641C78A213DD926004B4513 /* Status */,
|
||||
D6C7D27B22B6EBE200071952 /* Attachments */,
|
||||
D641C78B213DD92F004B4513 /* Profile Header */,
|
||||
|
@ -1237,6 +1238,7 @@
|
|||
D663626021360A9600C9CBA2 /* Preferences */,
|
||||
D6AEBB3F2321640F00E5038B /* Activities */,
|
||||
D667E5F62135C2ED0057A976 /* Extensions */,
|
||||
D61959D2241E846D00A37B8E /* Models */,
|
||||
D6F953F121251A2F00CF0F2B /* Controllers */,
|
||||
D641C780213DD7C4004B4513 /* Screens */,
|
||||
D6BED1722126661300F02DA0 /* Views */,
|
||||
|
@ -1509,7 +1511,6 @@
|
|||
D63F9C6C241C50B9004C03CF /* ComposeAttachmentTableViewCell.xib in Resources */,
|
||||
D6A3BC812321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.xib in Resources */,
|
||||
D63F9C66241C4CC3004C03CF /* AddAttachmentTableViewCell.xib in Resources */,
|
||||
D60C07E421E8176B0057FAA8 /* ComposeMediaView.xib in Resources */,
|
||||
D667E5E12134937B0057A976 /* TimelineStatusTableViewCell.xib in Resources */,
|
||||
D6A5FAF1217B7E05003DB2D9 /* ComposeViewController.xib in Resources */,
|
||||
);
|
||||
|
@ -1671,7 +1672,6 @@
|
|||
D627FF7B217E951500CC0648 /* DraftsTableViewController.swift in Sources */,
|
||||
D6A3BC8F2321FFB900FD64D5 /* StatusActionAccountListTableViewController.swift in Sources */,
|
||||
D6AEBB4823216B1D00E5038B /* AccountActivity.swift in Sources */,
|
||||
D6333B772138D94E00CE884A /* ComposeMediaView.swift in Sources */,
|
||||
04ED00B121481ED800567C53 /* SteppedProgressView.swift in Sources */,
|
||||
D6BC9DDA232D8BE5002CA326 /* SearchResultsViewController.swift in Sources */,
|
||||
D627FF7F217E95E000CC0648 /* DraftTableViewCell.swift in Sources */,
|
||||
|
|
|
@ -82,6 +82,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|||
// This occurs shortly after the scene enters the background, or when its session is discarded.
|
||||
// Release any resources associated with this scene that can be re-created the next time the scene connects.
|
||||
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
|
||||
|
||||
Preferences.save()
|
||||
DraftsManager.save()
|
||||
}
|
||||
|
||||
func sceneDidBecomeActive(_ scene: UIScene) {
|
||||
|
@ -92,6 +95,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|||
func sceneWillResignActive(_ scene: UIScene) {
|
||||
// Called when the scene will move from an active state to an inactive state.
|
||||
// This may occur due to temporary interruptions (ex. an incoming phone call).
|
||||
|
||||
Preferences.save()
|
||||
DraftsManager.save()
|
||||
}
|
||||
|
||||
func sceneWillEnterForeground(_ scene: UIScene) {
|
||||
|
@ -103,9 +109,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|||
// Called as the scene transitions from the foreground to the background.
|
||||
// Use this method to save data, release shared resources, and store enough scene-specific state information
|
||||
// to restore the scene back to its current state.
|
||||
|
||||
Preferences.save()
|
||||
DraftsManager.save()
|
||||
}
|
||||
|
||||
func activateAccount(_ account: LocalData.UserAccountInfo) {
|
||||
|
|
|
@ -177,10 +177,11 @@ class AssetCollectionViewController: UICollectionViewController {
|
|||
}
|
||||
|
||||
override func collectionView(_ collectionView: UICollectionView, previewForHighlightingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
|
||||
if let indexPath = (configuration.identifier as? NSIndexPath) as IndexPath?, let cell = collectionView.cellForItem(at: indexPath) {
|
||||
if let indexPath = (configuration.identifier as? NSIndexPath) as IndexPath?,
|
||||
let cell = collectionView.cellForItem(at: indexPath) as? AssetCollectionViewCell {
|
||||
let parameters = UIPreviewParameters()
|
||||
parameters.backgroundColor = .black
|
||||
return UITargetedPreview(view: cell, parameters: parameters)
|
||||
return UITargetedPreview(view: cell.imageView, parameters: parameters)
|
||||
} else {
|
||||
return nil
|
||||
}
|
|
@ -13,14 +13,18 @@ import AVKit
|
|||
|
||||
class AssetPreviewViewController: UIViewController {
|
||||
|
||||
let asset: PHAsset
|
||||
let attachment: CompositionAttachmentData
|
||||
|
||||
init(asset: PHAsset) {
|
||||
self.asset = asset
|
||||
init(attachment: CompositionAttachmentData) {
|
||||
self.attachment = attachment
|
||||
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
}
|
||||
|
||||
convenience init(asset: PHAsset) {
|
||||
self.init(attachment: .asset(asset))
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
@ -30,21 +34,29 @@ class AssetPreviewViewController: UIViewController {
|
|||
|
||||
view.backgroundColor = .black
|
||||
|
||||
if asset.mediaType == .image {
|
||||
if asset.mediaSubtypes.contains(.photoLive) {
|
||||
showLivePhoto()
|
||||
} else {
|
||||
showImage()
|
||||
switch attachment {
|
||||
case let .image(image):
|
||||
showImage(image)
|
||||
case let .video(url):
|
||||
showVideo(asset: AVURLAsset(url: url))
|
||||
case let .asset(asset):
|
||||
switch asset.mediaType {
|
||||
case .image:
|
||||
if asset.mediaSubtypes.contains(.photoLive) {
|
||||
showLivePhoto(asset)
|
||||
} else {
|
||||
showAssetImage(asset)
|
||||
}
|
||||
case .video:
|
||||
showAssetVideo(asset)
|
||||
default:
|
||||
fatalError("asset mediaType must be image or video")
|
||||
}
|
||||
} else if asset.mediaType == .video {
|
||||
playVideo()
|
||||
} else {
|
||||
fatalError("asset mediaType must be image or video")
|
||||
}
|
||||
}
|
||||
|
||||
func showImage() {
|
||||
let imageView = UIImageView()
|
||||
func showImage(_ image: UIImage) {
|
||||
let imageView = UIImageView(image: image)
|
||||
imageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
imageView.contentMode = .scaleAspectFit
|
||||
view.addSubview(imageView)
|
||||
|
@ -54,7 +66,10 @@ class AssetPreviewViewController: UIViewController {
|
|||
imageView.topAnchor.constraint(equalTo: view.topAnchor),
|
||||
imageView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
|
||||
])
|
||||
preferredContentSize = image.size
|
||||
}
|
||||
|
||||
func showAssetImage(_ asset: PHAsset) {
|
||||
let options = PHImageRequestOptions()
|
||||
options.version = .current
|
||||
options.deliveryMode = .opportunistic
|
||||
|
@ -62,13 +77,12 @@ class AssetPreviewViewController: UIViewController {
|
|||
options.isNetworkAccessAllowed = true
|
||||
PHImageManager.default().requestImage(for: asset, targetSize: view.bounds.size, contentMode: .aspectFit, options: options) { (image, _) in
|
||||
DispatchQueue.main.async {
|
||||
imageView.image = image
|
||||
self.preferredContentSize = image!.size
|
||||
self.showImage(image!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func showLivePhoto() {
|
||||
func showLivePhoto(_ asset: PHAsset) {
|
||||
let options = PHLivePhotoRequestOptions()
|
||||
options.deliveryMode = .opportunistic
|
||||
options.version = .current
|
||||
|
@ -96,7 +110,18 @@ class AssetPreviewViewController: UIViewController {
|
|||
}
|
||||
}
|
||||
|
||||
func playVideo() {
|
||||
func showVideo(asset: AVAsset) {
|
||||
let playerController = AVPlayerViewController()
|
||||
let item = AVPlayerItem(asset: asset)
|
||||
let player = AVPlayer(playerItem: item)
|
||||
player.isMuted = true
|
||||
player.play()
|
||||
playerController.player = player
|
||||
self.embedChild(playerController)
|
||||
self.preferredContentSize = item.presentationSize
|
||||
}
|
||||
|
||||
func showAssetVideo(_ asset: PHAsset) {
|
||||
let options = PHVideoRequestOptions()
|
||||
options.deliveryMode = .automatic
|
||||
options.isNetworkAccessAllowed = true
|
||||
|
@ -106,14 +131,7 @@ class AssetPreviewViewController: UIViewController {
|
|||
fatalError("failed to get AVAsset")
|
||||
}
|
||||
DispatchQueue.main.async {
|
||||
let playerController = AVPlayerViewController()
|
||||
let item = AVPlayerItem(asset: avAsset)
|
||||
let player = AVPlayer(playerItem: item)
|
||||
player.isMuted = true
|
||||
player.play()
|
||||
playerController.player = player
|
||||
self.embedChild(playerController)
|
||||
self.preferredContentSize = item.presentationSize
|
||||
self.showVideo(asset: avAsset)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,13 +25,14 @@ class ComposeAttachmentsViewController: UITableViewController {
|
|||
var attachments: [CompositionAttachment] = [] {
|
||||
didSet {
|
||||
delegate?.composeSelectedAttachmentsDidChange()
|
||||
delegate?.composeRequiresAttachmentDescriptionsDidChange()
|
||||
updateAddAttachmentsButtonEnabled()
|
||||
}
|
||||
}
|
||||
|
||||
var requiresAttachmentDescriptions: Bool {
|
||||
if Preferences.shared.requireAttachmentDescriptions {
|
||||
return !attachments.allSatisfy { $0.description.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty }
|
||||
return attachments.contains { $0.attachmentDescription.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty }
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
|
@ -264,6 +265,37 @@ class ComposeAttachmentsViewController: UITableViewController {
|
|||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
|
||||
let attachment = attachments[indexPath.row]
|
||||
// cast to NSIndexPath because identifier needs to conform to NSCopying
|
||||
return UIContextMenuConfiguration(identifier: indexPath as NSIndexPath, previewProvider: { () -> UIViewController? in
|
||||
return AssetPreviewViewController(attachment: attachment.data)
|
||||
}) { (_) -> UIMenu? in
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private func targetedPreview(forConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
|
||||
if let indexPath = (configuration.identifier as? NSIndexPath) as IndexPath?,
|
||||
let cell = tableView.cellForRow(at: indexPath) as? ComposeAttachmentTableViewCell {
|
||||
let parameters = UIPreviewParameters()
|
||||
parameters.backgroundColor = .black
|
||||
return UITargetedPreview(view: cell.assetImageView, parameters: parameters)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, previewForHighlightingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
|
||||
return targetedPreview(forConfiguration: configuration)
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, previewForDismissingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
|
||||
return targetedPreview(forConfiguration: configuration)
|
||||
}
|
||||
|
||||
// MARK: Interaction
|
||||
|
||||
func addAttachmentPressed() {
|
||||
let sheetContainer = AssetPickerSheetContainerViewController()
|
||||
sheetContainer.assetPicker.assetPickerDelegate = self
|
|
@ -7,6 +7,7 @@
|
|||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftSoup
|
||||
|
||||
class AccountTableViewCell: UITableViewCell {
|
||||
|
||||
|
@ -16,6 +17,7 @@ class AccountTableViewCell: UITableViewCell {
|
|||
@IBOutlet weak var avatarImageView: UIImageView!
|
||||
@IBOutlet weak var displayNameLabel: EmojiLabel!
|
||||
@IBOutlet weak var usernameLabel: UILabel!
|
||||
@IBOutlet weak var noteLabel: EmojiLabel!
|
||||
|
||||
var accountID: String!
|
||||
|
||||
|
@ -54,6 +56,10 @@ class AccountTableViewCell: UITableViewCell {
|
|||
|
||||
usernameLabel.text = "@\(account.acct)"
|
||||
|
||||
let doc = try! SwiftSoup.parse(account.note)
|
||||
noteLabel.text = try! doc.text()
|
||||
noteLabel.setEmojis(account.emojis, identifier: account.id)
|
||||
|
||||
updateUIForPrefrences()
|
||||
}
|
||||
|
||||
|
|
|
@ -9,40 +9,45 @@
|
|||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="KGk-i7-Jjw" customClass="AccountTableViewCell" customModule="Tusker" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="66"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="100" id="KGk-i7-Jjw" customClass="AccountTableViewCell" customModule="Tusker" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="100"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="66"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="100"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Rp2-O5-Vew">
|
||||
<rect key="frame" x="16" y="8" width="50" height="50"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="Rp2-O5-Vew" secondAttribute="height" multiplier="1:1" id="1AQ-lU-ptd"/>
|
||||
<constraint firstAttribute="height" priority="999" constant="50" id="NqI-m0-owe"/>
|
||||
<constraint firstAttribute="height" constant="50" id="NqI-m0-owe"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="Iif-9m-vM5">
|
||||
<rect key="frame" x="74" y="11" width="230" height="44"/>
|
||||
<rect key="frame" x="74" y="11" width="230" height="78"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" text="Display Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Fhc-bZ-lkB" customClass="EmojiLabel" customModule="Tusker" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="230" height="26"/>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Display Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Fhc-bZ-lkB" customClass="EmojiLabel" customModule="Tusker" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="230" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="@username" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JMo-QH-1is">
|
||||
<rect key="frame" x="0.0" y="26" width="230" height="18"/>
|
||||
<rect key="frame" x="0.0" y="20.5" width="230" height="18"/>
|
||||
<fontDescription key="fontDescription" type="system" weight="light" pointSize="15"/>
|
||||
<color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" text="Note" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bNO-qR-YEe" customClass="EmojiLabel" customModule="Tusker" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="38.5" width="230" height="39.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="Rp2-O5-Vew" secondAttribute="bottom" constant="8" id="Vw1-OF-tnw"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="Iif-9m-vM5" secondAttribute="bottom" id="dV0-Vm-DUb"/>
|
||||
<constraint firstItem="Iif-9m-vM5" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" id="ihr-er-kLO"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="Iif-9m-vM5" secondAttribute="trailing" id="q7a-DT-WPF"/>
|
||||
|
@ -55,9 +60,10 @@
|
|||
<connections>
|
||||
<outlet property="avatarImageView" destination="Rp2-O5-Vew" id="3Gw-Xg-bd5"/>
|
||||
<outlet property="displayNameLabel" destination="Fhc-bZ-lkB" id="1b0-3k-KR8"/>
|
||||
<outlet property="noteLabel" destination="bNO-qR-YEe" id="4oO-c0-BOT"/>
|
||||
<outlet property="usernameLabel" destination="JMo-QH-1is" id="ElX-ua-xcQ"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="173.91304347826087" y="24.107142857142858"/>
|
||||
<point key="canvasLocation" x="173.91304347826087" y="35.491071428571423"/>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
</document>
|
||||
|
|
|
@ -82,8 +82,8 @@ class ComposeAttachmentTableViewCell: UITableViewCell {
|
|||
|
||||
extension ComposeAttachmentTableViewCell: UITextViewDelegate {
|
||||
func textViewDidChange(_ textView: UITextView) {
|
||||
delegate?.attachmentDescriptionChanged(self)
|
||||
attachment.attachmentDescription = textView.text
|
||||
updateDescriptionPlaceholderLabel()
|
||||
delegate?.attachmentDescriptionChanged(self)
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
//
|
||||
// ComposeAttachmentView.swift
|
||||
// Tusker
|
||||
//
|
||||
// Created by Shadowfacts on 1/10/19.
|
||||
// Copyright © 2019 Shadowfacts. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Photos
|
||||
import AVFoundation
|
||||
|
||||
protocol ComposeMediaViewDelegate: class {
|
||||
func didRemoveMedia(_ mediaView: ComposeMediaView)
|
||||
func descriptionTextViewDidChange(_ mediaView: ComposeMediaView)
|
||||
}
|
||||
|
||||
class ComposeMediaView: UIView {
|
||||
|
||||
weak var delegate: ComposeMediaViewDelegate?
|
||||
|
||||
@IBOutlet weak var imageView: UIImageView!
|
||||
@IBOutlet weak var descriptionTextView: UITextView!
|
||||
@IBOutlet weak var placeholderLabel: UILabel!
|
||||
|
||||
var attachment: CompositionAttachmentData!
|
||||
|
||||
static func create() -> ComposeMediaView {
|
||||
return UINib(nibName: "ComposeMediaView", bundle: nil).instantiate(withOwner: nil, options: nil).first as! ComposeMediaView
|
||||
}
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
imageView.layer.masksToBounds = true
|
||||
imageView.layer.cornerRadius = 10 // 0.1 * imageView.frame.width
|
||||
|
||||
descriptionTextView.delegate = self
|
||||
}
|
||||
|
||||
func update(attachment: CompositionAttachmentData) {
|
||||
self.attachment = attachment
|
||||
|
||||
switch attachment {
|
||||
case let .image(image):
|
||||
imageView.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
|
||||
guard self.attachment == attachment else { return }
|
||||
self.imageView.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) {
|
||||
imageView.image = UIImage(cgImage: cgImage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Interaction
|
||||
|
||||
@IBAction func removePressed(_ sender: Any) {
|
||||
delegate?.didRemoveMedia(self)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension ComposeMediaView: UITextViewDelegate {
|
||||
func textViewDidChange(_ textView: UITextView) {
|
||||
placeholderLabel.isHidden = !descriptionTextView.text.isEmpty
|
||||
delegate?.descriptionTextViewDidChange(self)
|
||||
}
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="15702" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15704"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="iN0-l3-epB" customClass="ComposeMediaView" customModule="Tusker" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="u7I-sx-kUe">
|
||||
<rect key="frame" x="8" y="293.5" width="80" height="80"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="80" id="CgF-eC-We6"/>
|
||||
<constraint firstAttribute="width" constant="80" id="S3g-yM-TRb"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="G1g-Lw-Ren">
|
||||
<rect key="frame" x="345" y="322.5" width="22" height="22"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="22" id="dyG-5Y-91s"/>
|
||||
<constraint firstAttribute="width" constant="22" id="sWQ-3z-Z5r"/>
|
||||
</constraints>
|
||||
<state key="normal" image="xmark.circle.fill" catalog="system">
|
||||
<preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="large"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="removePressed:" destination="iN0-l3-epB" eventType="touchUpInside" id="aor-Cq-YjJ"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" scrollEnabled="NO" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="O6b-Zs-u8r">
|
||||
<rect key="frame" x="96" y="0.0" width="241" height="667"/>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="80" id="GsE-uM-fhe"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||
</textView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Describe for the visually impaired..." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rkD-NP-09H">
|
||||
<rect key="frame" x="100" y="8" width="233" height="41"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0h4-wv-2R8">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="1"/>
|
||||
<color key="backgroundColor" systemColor="separatorColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.28999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="1" id="aQa-2T-uYY"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<constraints>
|
||||
<constraint firstItem="vUN-kp-3ea" firstAttribute="bottom" secondItem="O6b-Zs-u8r" secondAttribute="bottom" id="3sv-wo-gxe"/>
|
||||
<constraint firstItem="u7I-sx-kUe" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" id="5Qs-i7-glv"/>
|
||||
<constraint firstItem="u7I-sx-kUe" firstAttribute="top" relation="greaterThanOrEqual" secondItem="0h4-wv-2R8" secondAttribute="bottom" constant="8" id="86L-Cb-Lsk"/>
|
||||
<constraint firstItem="O6b-Zs-u8r" firstAttribute="top" secondItem="vUN-kp-3ea" secondAttribute="top" id="9QY-MR-Yc2"/>
|
||||
<constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="0h4-wv-2R8" secondAttribute="trailing" id="FCS-un-JT6"/>
|
||||
<constraint firstItem="u7I-sx-kUe" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="8" id="UWq-Lf-zGB"/>
|
||||
<constraint firstItem="rkD-NP-09H" firstAttribute="leading" secondItem="O6b-Zs-u8r" secondAttribute="leading" constant="4" id="aQd-T9-n1I"/>
|
||||
<constraint firstItem="0h4-wv-2R8" firstAttribute="top" secondItem="vUN-kp-3ea" secondAttribute="top" id="edp-4a-YGq"/>
|
||||
<constraint firstItem="G1g-Lw-Ren" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" id="hJA-JF-MHp"/>
|
||||
<constraint firstItem="O6b-Zs-u8r" firstAttribute="leading" secondItem="u7I-sx-kUe" secondAttribute="trailing" constant="8" id="hvZ-m4-TOV"/>
|
||||
<constraint firstItem="G1g-Lw-Ren" firstAttribute="leading" secondItem="O6b-Zs-u8r" secondAttribute="trailing" constant="8" id="ith-0X-3Yz"/>
|
||||
<constraint firstItem="vUN-kp-3ea" firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="u7I-sx-kUe" secondAttribute="bottom" constant="8" id="lGN-Qg-mBO"/>
|
||||
<constraint firstItem="rkD-NP-09H" firstAttribute="top" secondItem="O6b-Zs-u8r" secondAttribute="top" constant="8" id="mRb-3M-7uz"/>
|
||||
<constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="G1g-Lw-Ren" secondAttribute="trailing" constant="8" id="o4F-MV-ahd"/>
|
||||
<constraint firstItem="0h4-wv-2R8" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="sFo-wp-MYP"/>
|
||||
<constraint firstItem="O6b-Zs-u8r" firstAttribute="trailing" secondItem="rkD-NP-09H" secondAttribute="trailing" constant="4" id="vwg-7l-8ca"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
|
||||
<connections>
|
||||
<outlet property="descriptionTextView" destination="O6b-Zs-u8r" id="TNy-7h-0sY"/>
|
||||
<outlet property="imageView" destination="u7I-sx-kUe" id="o3a-O0-m85"/>
|
||||
<outlet property="placeholderLabel" destination="rkD-NP-09H" id="WtV-2h-L3n"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="136.80000000000001" y="142.57871064467767"/>
|
||||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="xmark.circle.fill" catalog="system" width="64" height="60"/>
|
||||
</resources>
|
||||
</document>
|
|
@ -101,7 +101,10 @@ class TimelineStatusTableViewCell: BaseStatusTableViewCell {
|
|||
}
|
||||
|
||||
func updateTimestamp() {
|
||||
guard let mastodonController = mastodonController, let status = mastodonController.cache.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") }
|
||||
// if the mastodonController is nil (i.e. the delegate is nil), then the screen this cell was a part of has been deallocated
|
||||
// so we bail out immediately, since there's nothing to update
|
||||
guard let mastodonController = mastodonController else { return }
|
||||
guard let status = mastodonController.cache.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") }
|
||||
|
||||
timestampLabel.text = status.createdAt.timeAgoString()
|
||||
timestampLabel.accessibilityLabel = TimelineStatusTableViewCell.relativeDateFormatter.localizedString(for: status.createdAt, relativeTo: Date())
|
||||
|
|
Loading…
Reference in New Issue