forked from shadowfacts/Tusker
Show favorite, reblog, and full timestamp in conversation main status
This commit is contained in:
parent
818c0afec6
commit
2edb65d302
|
@ -7,20 +7,44 @@
|
|||
//
|
||||
|
||||
import UIKit
|
||||
import Pachyderm
|
||||
|
||||
class StatusActionAccountListTableViewController: EnhancedTableViewController {
|
||||
|
||||
private let statusCell = "statusCell"
|
||||
private let accountCell = "accountCell"
|
||||
|
||||
let actionType: ActionType
|
||||
let statusID: String
|
||||
let accountIDs: [String]
|
||||
var accountIDs: [String]? {
|
||||
didSet {
|
||||
tableView.reloadData()
|
||||
}
|
||||
}
|
||||
|
||||
init(statusID: String, accountIDs: [String]) {
|
||||
/// If `true`, a warning will be shown below the account list describing that the total favs/reblogs may be innacurate.
|
||||
var showInacurateCountWarning = false
|
||||
|
||||
/**
|
||||
Creates a new view controller showing the accounts that performed the given action on the given status.
|
||||
|
||||
- Parameter actionType The action that this VC is for.
|
||||
- Parameter statusID The ID of the status to show.
|
||||
- Parameter accountIDs The accounts that will be shown. If `nil` is passed, a request will be performed to load the accounts.
|
||||
*/
|
||||
init(actionType: ActionType, statusID: String, accountIDs: [String]?) {
|
||||
self.actionType = actionType
|
||||
self.statusID = statusID
|
||||
self.accountIDs = accountIDs
|
||||
|
||||
super.init(style: .grouped)
|
||||
|
||||
switch actionType {
|
||||
case .favorite:
|
||||
title = NSLocalizedString("Favorited By", comment: "status favorited by accounts list title")
|
||||
case .reblog:
|
||||
title = NSLocalizedString("Reblogged By", comment: "status reblogged by accounts list title")
|
||||
}
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
|
@ -39,6 +63,25 @@ class StatusActionAccountListTableViewController: EnhancedTableViewController {
|
|||
tableView.alwaysBounceVertical = true
|
||||
|
||||
tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: CGFloat.leastNormalMagnitude))
|
||||
|
||||
if accountIDs == nil {
|
||||
// account IDs haven't been set, so perform a request to load them
|
||||
guard let status = MastodonCache.status(for: statusID) else {
|
||||
fatalError("Missing cached status \(statusID)")
|
||||
}
|
||||
|
||||
tableView.tableFooterView = UIActivityIndicatorView(style: .large)
|
||||
|
||||
let request = actionType == .favorite ? Status.getFavourites(status) : Status.getReblogs(status)
|
||||
MastodonController.client.run(request) { (response) in
|
||||
guard case let .success(accounts, _) = response else { fatalError() }
|
||||
MastodonCache.addAll(accounts: accounts)
|
||||
DispatchQueue.main.async {
|
||||
self.accountIDs = accounts.map { $0.id }
|
||||
self.tableView.tableFooterView = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Table view data source
|
||||
|
@ -52,7 +95,11 @@ class StatusActionAccountListTableViewController: EnhancedTableViewController {
|
|||
case 0: // status
|
||||
return 1
|
||||
case 1: // accounts
|
||||
if let accountIDs = accountIDs {
|
||||
return accountIDs.count
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
default:
|
||||
fatalError("Invalid section \(section)")
|
||||
}
|
||||
|
@ -66,7 +113,8 @@ class StatusActionAccountListTableViewController: EnhancedTableViewController {
|
|||
cell.delegate = self
|
||||
return cell
|
||||
case 1:
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: accountCell, for: indexPath) as? AccountTableViewCell else { fatalError() }
|
||||
guard let accountIDs = accountIDs,
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: accountCell, for: indexPath) as? AccountTableViewCell else { fatalError() }
|
||||
cell.updateUI(accountID: accountIDs[indexPath.row])
|
||||
cell.delegate = self
|
||||
return cell
|
||||
|
@ -75,50 +123,14 @@ class StatusActionAccountListTableViewController: EnhancedTableViewController {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// Override to support conditional editing of the table view.
|
||||
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
|
||||
// Return false if you do not want the specified item to be editable.
|
||||
return true
|
||||
override func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
|
||||
guard section == 1, showInacurateCountWarning else { return nil }
|
||||
return NSLocalizedString("Favorite and reblog counts for posts originating from instances other than your own may not be accurate.", comment: "shown on lists of status total actions")
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
// Override to support editing the table view.
|
||||
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
|
||||
if editingStyle == .delete {
|
||||
// Delete the row from the data source
|
||||
tableView.deleteRows(at: [indexPath], with: .fade)
|
||||
} else if editingStyle == .insert {
|
||||
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
|
||||
enum ActionType {
|
||||
case favorite, reblog
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
// Override to support rearranging the table view.
|
||||
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
// Override to support conditional rearranging of the table view.
|
||||
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
|
||||
// Return false if you do not want the item to be re-orderable.
|
||||
return true
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
// MARK: - Navigation
|
||||
|
||||
// In a storyboard-based application, you will often want to do a little preparation before navigation
|
||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||
// Get the new view controller using segue.destination.
|
||||
// Pass the selected object to the new view controller.
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@ import Pachyderm
|
|||
|
||||
protocol TuskerNavigationDelegate {
|
||||
|
||||
func show(_ vc: UIViewController)
|
||||
|
||||
func selected(account accountID: String)
|
||||
|
||||
func selected(mention: Mention)
|
||||
|
@ -44,11 +46,15 @@ protocol TuskerNavigationDelegate {
|
|||
|
||||
func showFollowedByList(accountIDs: [String])
|
||||
|
||||
func showStatusActionAccountList(statusID: String, accountIDs: [String], action: Pachyderm.Notification.Kind)
|
||||
func statusActionAccountList(action: StatusActionAccountListTableViewController.ActionType, statusID: String, accountIDs: [String]?) -> StatusActionAccountListTableViewController
|
||||
}
|
||||
|
||||
extension TuskerNavigationDelegate where Self: UIViewController {
|
||||
|
||||
func show(_ vc: UIViewController) {
|
||||
show(vc, sender: self)
|
||||
}
|
||||
|
||||
func selected(account accountID: String) {
|
||||
// don't open if the account is the same as the current one
|
||||
if let profileController = self as? ProfileTableViewController,
|
||||
|
@ -179,17 +185,8 @@ extension TuskerNavigationDelegate where Self: UIViewController {
|
|||
show(vc, sender: self)
|
||||
}
|
||||
|
||||
func showStatusActionAccountList(statusID: String, accountIDs: [String], action: Pachyderm.Notification.Kind) {
|
||||
let vc = StatusActionAccountListTableViewController(statusID: statusID, accountIDs: accountIDs)
|
||||
switch action {
|
||||
case .favourite:
|
||||
vc.title = NSLocalizedString("Favorited By", comment: "status favorited by accounts list title")
|
||||
case .reblog:
|
||||
vc.title = NSLocalizedString("Reblogged By", comment: "status reblogged by accounts list title")
|
||||
default:
|
||||
fatalError("Invalid notification type for action account list, only favourite and relog are allowed")
|
||||
}
|
||||
show(vc, sender: self)
|
||||
func statusActionAccountList(action: StatusActionAccountListTableViewController.ActionType, statusID: String, accountIDs: [String]?) -> StatusActionAccountListTableViewController {
|
||||
return StatusActionAccountListTableViewController(actionType: action, statusID: statusID, accountIDs: accountIDs)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -153,10 +153,20 @@ class ActionNotificationGroupTableViewCell: UITableViewCell {
|
|||
override func setSelected(_ selected: Bool, animated: Bool) {
|
||||
super.setSelected(selected, animated: animated)
|
||||
|
||||
if selected {
|
||||
if selected, let delegate = delegate {
|
||||
let notifications = group.notificationIDs.compactMap(MastodonCache.notification(for:))
|
||||
let accountIDs = notifications.map { $0.account.id }
|
||||
delegate?.showStatusActionAccountList(statusID: statusID, accountIDs: accountIDs, action: notifications.first!.kind)
|
||||
let action: StatusActionAccountListTableViewController.ActionType
|
||||
switch notifications.first!.kind {
|
||||
case .favourite:
|
||||
action = .favorite
|
||||
case .reblog:
|
||||
action = .reblog
|
||||
default:
|
||||
fatalError()
|
||||
}
|
||||
let vc = delegate.statusActionAccountList(action: action, statusID: statusID, accountIDs: accountIDs)
|
||||
delegate.show(vc)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,8 +176,18 @@ extension ActionNotificationGroupTableViewCell: MenuPreviewProvider {
|
|||
|
||||
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? {
|
||||
return (content: {
|
||||
let accountIDs = self.group.notificationIDs.compactMap(MastodonCache.notification(for:)).map { $0.account.id }
|
||||
return StatusActionAccountListTableViewController(statusID: self.statusID, accountIDs: accountIDs)
|
||||
let notifications = self.group.notificationIDs.compactMap(MastodonCache.notification(for:))
|
||||
let accountIDs = notifications.map { $0.account.id }
|
||||
let action: StatusActionAccountListTableViewController.ActionType
|
||||
switch notifications.first!.kind {
|
||||
case .favourite:
|
||||
action = .favorite
|
||||
case .reblog:
|
||||
action = .reblog
|
||||
default:
|
||||
fatalError()
|
||||
}
|
||||
return self.delegate?.statusActionAccountList(action: action, statusID: self.statusID, accountIDs: accountIDs)
|
||||
}, actions: {
|
||||
return self.actionsForNotificationGroup(self.group)
|
||||
})
|
||||
|
|
|
@ -12,6 +12,13 @@ import Pachyderm
|
|||
|
||||
class ConversationMainStatusTableViewCell: UITableViewCell {
|
||||
|
||||
static let dateFormatter: DateFormatter = {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateStyle = .medium
|
||||
formatter.timeStyle = .medium
|
||||
return formatter
|
||||
}()
|
||||
|
||||
var delegate: StatusTableViewCellDelegate? {
|
||||
didSet {
|
||||
contentLabel.navigationDelegate = delegate
|
||||
|
@ -22,7 +29,9 @@ class ConversationMainStatusTableViewCell: UITableViewCell {
|
|||
@IBOutlet weak var usernameLabel: UILabel!
|
||||
@IBOutlet weak var contentLabel: StatusContentLabel!
|
||||
@IBOutlet weak var avatarImageView: UIImageView!
|
||||
@IBOutlet weak var timestampLabel: UILabel!
|
||||
@IBOutlet weak var totalFavoritesButton: UIButton!
|
||||
@IBOutlet weak var totalReblogsButton: UIButton!
|
||||
@IBOutlet weak var timestampAndClientLabel: UILabel!
|
||||
@IBOutlet weak var attachmentsView: AttachmentsContainerView!
|
||||
@IBOutlet weak var favoriteButton: UIButton!
|
||||
@IBOutlet weak var reblogButton: UIButton!
|
||||
|
@ -46,7 +55,6 @@ class ConversationMainStatusTableViewCell: UITableViewCell {
|
|||
}
|
||||
|
||||
var avatarURL: URL?
|
||||
var updateTimestampWorkItem: DispatchWorkItem?
|
||||
|
||||
var statusUpdater: Cancellable?
|
||||
var accountUpdater: Cancellable?
|
||||
|
@ -93,7 +101,12 @@ class ConversationMainStatusTableViewCell: UITableViewCell {
|
|||
updateUI(account: account)
|
||||
updateUIForPreferences()
|
||||
|
||||
updateTimestamp()
|
||||
var timestampAndClientText = ConversationMainStatusTableViewCell.dateFormatter.string(from: status.createdAt)
|
||||
if let application = status.application {
|
||||
timestampAndClientText += " • \(application.name)"
|
||||
}
|
||||
timestampAndClientLabel.text = timestampAndClientText
|
||||
|
||||
|
||||
attachmentsView.updateUI(status: status)
|
||||
|
||||
|
@ -106,6 +119,10 @@ class ConversationMainStatusTableViewCell: UITableViewCell {
|
|||
private func updateStatusState(status: Status) {
|
||||
favorited = status.favourited ?? false
|
||||
reblogged = status.reblogged ?? false
|
||||
|
||||
// todo: localize me
|
||||
totalFavoritesButton.setTitle("\(status.favouritesCount) Favorite\(status.favouritesCount == 1 ? "" : "s")", for: .normal)
|
||||
totalReblogsButton.setTitle("\(status.reblogsCount) Reblog\(status.reblogsCount == 1 ? "" : "s")", for: .normal)
|
||||
}
|
||||
|
||||
private func updateUI(account: Account) {
|
||||
|
@ -128,35 +145,10 @@ class ConversationMainStatusTableViewCell: UITableViewCell {
|
|||
displayNameLabel.text = account.realDisplayName
|
||||
}
|
||||
|
||||
func updateTimestamp() {
|
||||
guard let status = MastodonCache.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") }
|
||||
|
||||
timestampLabel.text = status.createdAt.timeAgoString()
|
||||
let delay: DispatchTimeInterval?
|
||||
switch status.createdAt.timeAgo().1 {
|
||||
case .second:
|
||||
delay = .seconds(10)
|
||||
case .minute:
|
||||
delay = .seconds(60)
|
||||
default:
|
||||
delay = nil
|
||||
}
|
||||
if let delay = delay {
|
||||
updateTimestampWorkItem = DispatchWorkItem {
|
||||
self.updateTimestamp()
|
||||
}
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: updateTimestampWorkItem!)
|
||||
} else {
|
||||
updateTimestampWorkItem = nil
|
||||
}
|
||||
}
|
||||
|
||||
override func prepareForReuse() {
|
||||
if let url = avatarURL {
|
||||
ImageCache.avatars.cancel(url)
|
||||
}
|
||||
updateTimestampWorkItem?.cancel()
|
||||
updateTimestampWorkItem = nil
|
||||
attachmentsView.subviews.forEach { $0.removeFromSuperview() }
|
||||
}
|
||||
|
||||
|
@ -219,6 +211,23 @@ class ConversationMainStatusTableViewCell: UITableViewCell {
|
|||
delegate?.showMoreOptions(forStatus: statusID)
|
||||
}
|
||||
|
||||
@IBAction func totalFavoritesPressed(_ sender: Any) {
|
||||
if let delegate = delegate {
|
||||
// accounts aren't known, pass nil so the VC will load them
|
||||
let vc = delegate.statusActionAccountList(action: .favorite, statusID: statusID, accountIDs: nil)
|
||||
vc.showInacurateCountWarning = true
|
||||
delegate.show(vc)
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func totalReblogsPressed(_ sender: Any) {
|
||||
if let delegate = delegate {
|
||||
// accounts aren't known, pass nil so the VC will load them
|
||||
let vc = delegate.statusActionAccountList(action: .reblog, statusID: statusID, accountIDs: nil)
|
||||
vc.showInacurateCountWarning = true
|
||||
delegate.show(vc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ConversationMainStatusTableViewCell: AttachmentViewDelegate {
|
||||
|
|
|
@ -1,24 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14810.11" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14865.1" 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="14766.13"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14819.2"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
<capability name="iOS 13.0 system colors" minToolsVersion="11.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="ConversationMainStatusTableViewCell" customModule="Tusker" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="200"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="238"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="top" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="GuG-Qd-B8I">
|
||||
<rect key="frame" x="16" y="8" width="343" height="184"/>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="GuG-Qd-B8I">
|
||||
<rect key="frame" x="16" y="8" width="343" height="222"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" verticalHuggingPriority="249" translatesAutoresizingMaskIntoConstraints="NO" id="Cnd-Fj-B7l">
|
||||
<rect key="frame" x="0.0" y="0.0" width="343" height="158"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="343" height="118.5"/>
|
||||
<subviews>
|
||||
<imageView contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="mB9-HO-1vf">
|
||||
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
|
||||
|
@ -28,7 +27,7 @@
|
|||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" contentMode="left" verticalHuggingPriority="251" text="Display name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lZY-2e-17d">
|
||||
<rect key="frame" x="58" y="0.0" width="252.5" height="29"/>
|
||||
<rect key="frame" x="58" y="0.0" width="277" height="29"/>
|
||||
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="24"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
|
@ -36,21 +35,15 @@
|
|||
<label opaque="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="@username" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SWg-Ka-QyP">
|
||||
<rect key="frame" x="58" y="29" width="285" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" weight="light" pointSize="17"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="secondaryLabelColor"/>
|
||||
<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" verticalHuggingPriority="249" text="Content" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="TgY-hs-Klo" customClass="StatusContentLabel" customModule="Tusker" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="54" width="343" height="104"/>
|
||||
<rect key="frame" x="0.0" y="54" width="343" height="64.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="20"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="2m" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="R3N-Pg-4hn">
|
||||
<rect key="frame" x="318.5" y="0.0" width="24.5" height="29"/>
|
||||
<fontDescription key="fontDescription" type="system" weight="light" pointSize="17"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="secondaryLabelColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
|
@ -58,28 +51,91 @@
|
|||
<constraint firstAttribute="trailing" secondItem="SWg-Ka-QyP" secondAttribute="trailing" id="4g6-BT-eW4"/>
|
||||
<constraint firstAttribute="bottom" secondItem="TgY-hs-Klo" secondAttribute="bottom" id="5Og-Pd-Vck"/>
|
||||
<constraint firstItem="lZY-2e-17d" firstAttribute="top" secondItem="Cnd-Fj-B7l" secondAttribute="top" id="8fU-y9-K5Z"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="lZY-2e-17d" secondAttribute="trailing" id="AAJ-pd-omx"/>
|
||||
<constraint firstItem="lZY-2e-17d" firstAttribute="leading" secondItem="mB9-HO-1vf" secondAttribute="trailing" constant="8" id="Aqj-co-Szp"/>
|
||||
<constraint firstItem="R3N-Pg-4hn" firstAttribute="top" secondItem="Cnd-Fj-B7l" secondAttribute="top" id="Gl6-Ss-hKQ"/>
|
||||
<constraint firstAttribute="trailing" secondItem="R3N-Pg-4hn" secondAttribute="trailing" id="Oiy-II-fvT"/>
|
||||
<constraint firstItem="mB9-HO-1vf" firstAttribute="top" secondItem="Cnd-Fj-B7l" secondAttribute="top" id="R7P-rD-Gbm"/>
|
||||
<constraint firstAttribute="trailing" secondItem="TgY-hs-Klo" secondAttribute="trailing" id="SOE-Q5-IWd"/>
|
||||
<constraint firstItem="mB9-HO-1vf" firstAttribute="leading" secondItem="Cnd-Fj-B7l" secondAttribute="leading" id="bxq-Fs-1aH"/>
|
||||
<constraint firstItem="R3N-Pg-4hn" firstAttribute="leading" secondItem="lZY-2e-17d" secondAttribute="trailing" constant="8" id="dVP-Er-Z2l"/>
|
||||
<constraint firstItem="SWg-Ka-QyP" firstAttribute="leading" secondItem="mB9-HO-1vf" secondAttribute="trailing" constant="8" id="e45-gE-myI"/>
|
||||
<constraint firstItem="R3N-Pg-4hn" firstAttribute="height" secondItem="lZY-2e-17d" secondAttribute="height" id="fBi-wD-elQ"/>
|
||||
<constraint firstItem="TgY-hs-Klo" firstAttribute="top" secondItem="mB9-HO-1vf" secondAttribute="bottom" constant="4" id="l6y-Rr-Nmc"/>
|
||||
<constraint firstItem="SWg-Ka-QyP" firstAttribute="top" secondItem="lZY-2e-17d" secondAttribute="bottom" id="lvX-1b-8cN"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IF9-9U-Gk0" customClass="AttachmentsContainerView" customModule="Tusker" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="162" width="343" height="0.0"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="secondarySystemBackgroundColor"/>
|
||||
<rect key="frame" x="0.0" y="122.5" width="343" height="0.0"/>
|
||||
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" priority="999" constant="200" id="UMv-Bk-ZyY"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ejU-sO-Og5">
|
||||
<rect key="frame" x="0.0" y="126.5" width="343" height="0.5"/>
|
||||
<color key="backgroundColor" systemColor="opaqueSeparatorColor" red="0.77647058820000003" green="0.77647058820000003" blue="0.7843137255" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="0.5" id="DRI-lB-TyG"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="HZv-qj-gi6">
|
||||
<rect key="frame" x="0.0" y="135" width="343" height="18"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="252" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="yyj-Bs-Vjq">
|
||||
<rect key="frame" x="0.0" y="0.0" width="163.5" height="18"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="18" id="F9W-LW-swd"/>
|
||||
</constraints>
|
||||
<state key="normal" title="2 Favorites">
|
||||
<color key="titleColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="totalFavoritesPressed:" destination="iN0-l3-epB" eventType="touchUpInside" id="cj1-BB-TuR"/>
|
||||
</connections>
|
||||
</button>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="dYU-Hk-ee3">
|
||||
<rect key="frame" x="171.5" y="0.0" width="0.5" height="18"/>
|
||||
<color key="backgroundColor" systemColor="opaqueSeparatorColor" red="0.77647058820000003" green="0.77647058820000003" blue="0.7843137255" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="0.5" id="kcB-YZ-hDW"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dem-vG-cPB">
|
||||
<rect key="frame" x="180" y="0.0" width="163" height="18"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="18" id="k0P-W7-wMF"/>
|
||||
</constraints>
|
||||
<state key="normal" title="1 Reblog">
|
||||
<color key="titleColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="totalReblogsPressed:" destination="iN0-l3-epB" eventType="touchUpInside" id="duG-bV-hcI"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="dem-vG-cPB" firstAttribute="width" secondItem="yyj-Bs-Vjq" secondAttribute="width" id="gcs-mS-vcQ"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="pcy-jH-lL9">
|
||||
<rect key="frame" x="0.0" y="161" width="343" height="0.5"/>
|
||||
<color key="backgroundColor" systemColor="opaqueSeparatorColor" red="0.77647058820000003" green="0.77647058820000003" blue="0.7843137255" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="0.5" id="0Ga-Fr-g0g"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Sep 7, 2019 12:12:53 PM • Web" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YHN-wG-YWi">
|
||||
<rect key="frame" x="0.0" y="169.5" width="343" height="18"/>
|
||||
<fontDescription key="fontDescription" type="system" 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>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3Fp-Nj-sVj">
|
||||
<rect key="frame" x="0.0" y="195.5" width="343" height="0.5"/>
|
||||
<color key="backgroundColor" systemColor="opaqueSeparatorColor" red="0.77647058820000003" green="0.77647058820000003" blue="0.7843137255" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="0.5" id="akf-Kl-8mK"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" distribution="equalSpacing" translatesAutoresizingMaskIntoConstraints="NO" id="3Bg-XP-d13">
|
||||
<rect key="frame" x="0.0" y="166" width="343" height="18"/>
|
||||
<rect key="frame" x="0.0" y="204" width="343" height="18"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="leading" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="2cc-lE-AdG">
|
||||
<rect key="frame" x="0.0" y="0.0" width="21.5" height="18"/>
|
||||
|
@ -96,14 +152,14 @@
|
|||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="GUG-f7-Hdy">
|
||||
<rect key="frame" x="215.5" y="0.0" width="23" height="18"/>
|
||||
<rect key="frame" x="215.5" y="0.0" width="22.5" height="18"/>
|
||||
<state key="normal" image="repeat" catalog="system"/>
|
||||
<connections>
|
||||
<action selector="reblogPressed:" destination="iN0-l3-epB" eventType="touchUpInside" id="SAf-RN-q8N"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Ujo-Ap-dmK">
|
||||
<rect key="frame" x="324.5" y="0.0" width="18.5" height="18"/>
|
||||
<rect key="frame" x="324" y="0.0" width="19" height="18"/>
|
||||
<state key="normal" image="ellipsis" catalog="system"/>
|
||||
<connections>
|
||||
<action selector="morePressed:" destination="iN0-l3-epB" eventType="touchUpInside" id="dWb-67-CoL"/>
|
||||
|
@ -118,11 +174,14 @@
|
|||
<constraints>
|
||||
<constraint firstItem="Cnd-Fj-B7l" firstAttribute="width" secondItem="GuG-Qd-B8I" secondAttribute="width" id="2hS-RG-81T"/>
|
||||
<constraint firstItem="IF9-9U-Gk0" firstAttribute="width" secondItem="GuG-Qd-B8I" secondAttribute="width" id="8A8-wi-7sg"/>
|
||||
<constraint firstItem="pcy-jH-lL9" firstAttribute="width" secondItem="GuG-Qd-B8I" secondAttribute="width" id="bPY-g6-swp"/>
|
||||
<constraint firstItem="ejU-sO-Og5" firstAttribute="width" secondItem="GuG-Qd-B8I" secondAttribute="width" id="biK-oQ-SLy"/>
|
||||
<constraint firstItem="3Bg-XP-d13" firstAttribute="width" secondItem="GuG-Qd-B8I" secondAttribute="width" id="iIq-gh-90O"/>
|
||||
<constraint firstItem="3Fp-Nj-sVj" firstAttribute="width" secondItem="GuG-Qd-B8I" secondAttribute="width" id="kfI-WN-ouW"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<constraints>
|
||||
<constraint firstItem="vUN-kp-3ea" firstAttribute="bottom" secondItem="GuG-Qd-B8I" secondAttribute="bottom" constant="8" id="2F3-0f-0tC"/>
|
||||
<constraint firstItem="GuG-Qd-B8I" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="16" id="PFH-TI-ZQ9"/>
|
||||
|
@ -138,10 +197,12 @@
|
|||
<outlet property="displayNameLabel" destination="lZY-2e-17d" id="7og-23-eHy"/>
|
||||
<outlet property="favoriteButton" destination="DhN-rJ-jdA" id="b2Q-ch-kSP"/>
|
||||
<outlet property="reblogButton" destination="GUG-f7-Hdy" id="WtT-Ph-DQm"/>
|
||||
<outlet property="timestampLabel" destination="R3N-Pg-4hn" id="z5j-Tw-Lk5"/>
|
||||
<outlet property="timestampAndClientLabel" destination="YHN-wG-YWi" id="Onb-fe-qwG"/>
|
||||
<outlet property="totalFavoritesButton" destination="yyj-Bs-Vjq" id="4pV-Qi-Z2X"/>
|
||||
<outlet property="totalReblogsButton" destination="dem-vG-cPB" id="i9E-Qn-d76"/>
|
||||
<outlet property="usernameLabel" destination="SWg-Ka-QyP" id="h2I-g4-AD9"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="40.799999999999997" y="-163.71814092953525"/>
|
||||
<point key="canvasLocation" x="40.799999999999997" y="-146.62668665667167"/>
|
||||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
|
|
Loading…
Reference in New Issue