forked from shadowfacts/Tusker
Show follow requsts in notifications w/ accept/reject buttons
Closes #64
This commit is contained in:
parent
c31916d67e
commit
ad09e36907
|
@ -29,12 +29,12 @@ public class Account: Decodable {
|
|||
public let fields: [Field]?
|
||||
public let bot: Bool?
|
||||
|
||||
public static func authorizeFollowRequest(_ account: Account) -> Request<Empty> {
|
||||
return Request<Empty>(method: .post, path: "/api/v1/follow_requests/\(account.id)/authorize")
|
||||
public static func authorizeFollowRequest(_ account: Account) -> Request<Relationship> {
|
||||
return Request<Relationship>(method: .post, path: "/api/v1/follow_requests/\(account.id)/authorize")
|
||||
}
|
||||
|
||||
public static func rejectFollowRequest(_ account: Account) -> Request<Empty> {
|
||||
return Request<Empty>(method: .post, path: "/api/v1/follow_requests/\(account.id)/reject")
|
||||
public static func rejectFollowRequest(_ account: Account) -> Request<Relationship> {
|
||||
return Request<Relationship>(method: .post, path: "/api/v1/follow_requests/\(account.id)/reject")
|
||||
}
|
||||
|
||||
public static func removeFromFollowRequests(_ account: Account) -> Request<Empty> {
|
||||
|
|
|
@ -36,6 +36,7 @@ extension Notification {
|
|||
case reblog
|
||||
case favourite
|
||||
case follow
|
||||
case followRequest = "follow_request"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -116,6 +116,8 @@
|
|||
D64BC18623C1253A000D0238 /* AssetPreviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64BC18523C1253A000D0238 /* AssetPreviewViewController.swift */; };
|
||||
D64BC18823C1640A000D0238 /* PinStatusActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64BC18723C1640A000D0238 /* PinStatusActivity.swift */; };
|
||||
D64BC18A23C16487000D0238 /* UnpinStatusActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64BC18923C16487000D0238 /* UnpinStatusActivity.swift */; };
|
||||
D64BC18F23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64BC18D23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.swift */; };
|
||||
D64BC19023C18B9D000D0238 /* FollowRequestNotificationTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D64BC18E23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.xib */; };
|
||||
D64D0AAD2128D88B005A6F37 /* LocalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AAC2128D88B005A6F37 /* LocalData.swift */; };
|
||||
D64D0AB12128D9AE005A6F37 /* OnboardingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */; };
|
||||
D64F80E2215875CC00BEF393 /* XCBActionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64F80E1215875CC00BEF393 /* XCBActionType.swift */; };
|
||||
|
@ -384,6 +386,8 @@
|
|||
D64BC18523C1253A000D0238 /* AssetPreviewViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AssetPreviewViewController.swift; sourceTree = "<group>"; };
|
||||
D64BC18723C1640A000D0238 /* PinStatusActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinStatusActivity.swift; sourceTree = "<group>"; };
|
||||
D64BC18923C16487000D0238 /* UnpinStatusActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnpinStatusActivity.swift; sourceTree = "<group>"; };
|
||||
D64BC18D23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowRequestNotificationTableViewCell.swift; sourceTree = "<group>"; };
|
||||
D64BC18E23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FollowRequestNotificationTableViewCell.xib; sourceTree = "<group>"; };
|
||||
D64D0AAC2128D88B005A6F37 /* LocalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalData.swift; sourceTree = "<group>"; };
|
||||
D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewController.swift; sourceTree = "<group>"; };
|
||||
D64F80E1215875CC00BEF393 /* XCBActionType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCBActionType.swift; sourceTree = "<group>"; };
|
||||
|
@ -906,6 +910,8 @@
|
|||
D6A3BC7B232195C600FD64D5 /* ActionNotificationGroupTableViewCell.xib */,
|
||||
D6A3BC7E2321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.swift */,
|
||||
D6A3BC7F2321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.xib */,
|
||||
D64BC18D23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.swift */,
|
||||
D64BC18E23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.xib */,
|
||||
);
|
||||
path = Notifications;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1482,6 +1488,7 @@
|
|||
D626493323BD751600612E6E /* ShowCameraCollectionViewCell.xib in Resources */,
|
||||
D626493D23C1000300612E6E /* AlbumTableViewCell.xib in Resources */,
|
||||
D627944723A6AC9300D38C68 /* BasicTableViewCell.xib in Resources */,
|
||||
D64BC19023C18B9D000D0238 /* FollowRequestNotificationTableViewCell.xib in Resources */,
|
||||
D67C57B221E28FAD00C3118B /* ComposeStatusReplyView.xib in Resources */,
|
||||
0411610122B442870030A9B7 /* AttachmentViewController.xib in Resources */,
|
||||
D6A3BC812321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.xib in Resources */,
|
||||
|
@ -1614,6 +1621,7 @@
|
|||
D6BC9DB3232D4C07002CA326 /* WellnessPrefsView.swift in Sources */,
|
||||
D6D58DF922074B74009C8DD9 /* LinkLabel.swift in Sources */,
|
||||
0454DDAF22B462EF00B8BB8E /* GalleryExpandAnimationController.swift in Sources */,
|
||||
D64BC18F23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.swift in Sources */,
|
||||
D6A3BC8A2321F79B00FD64D5 /* AccountTableViewCell.swift in Sources */,
|
||||
D66A77BB233838DC0058F1EC /* UIFont+Traits.swift in Sources */,
|
||||
D68FEC4F232C5BC300C84F23 /* SegmentedPageViewController.swift in Sources */,
|
||||
|
|
|
@ -12,7 +12,9 @@ import Pachyderm
|
|||
extension Account {
|
||||
|
||||
var realDisplayName: String {
|
||||
if Preferences.shared.hideCustomEmojiInUsernames {
|
||||
if displayName.isEmpty {
|
||||
return username
|
||||
} else if Preferences.shared.hideCustomEmojiInUsernames {
|
||||
return stripCustomEmoji(from: displayName)
|
||||
} else {
|
||||
return displayName
|
||||
|
|
|
@ -14,6 +14,7 @@ class NotificationsTableViewController: EnhancedTableViewController {
|
|||
private let statusCell = "statusCell"
|
||||
private let actionGroupCell = "actionGroupCell"
|
||||
private let followGroupCell = "followGroupCell"
|
||||
private let followRequestCell = "followRequestCell"
|
||||
|
||||
let excludedTypes: [Pachyderm.Notification.Kind]
|
||||
let groupTypes = [Notification.Kind.favourite, .reblog, .follow]
|
||||
|
@ -48,9 +49,10 @@ class NotificationsTableViewController: EnhancedTableViewController {
|
|||
tableView.rowHeight = UITableView.automaticDimension
|
||||
tableView.estimatedRowHeight = 140
|
||||
|
||||
tableView.register(UINib(nibName: "TimelineStatusTableViewCell", bundle: nil), forCellReuseIdentifier: statusCell)
|
||||
tableView.register(UINib(nibName: "ActionNotificationGroupTableViewCell", bundle: nil), forCellReuseIdentifier: actionGroupCell)
|
||||
tableView.register(UINib(nibName: "FollowNotificationGroupTableViewCell", bundle: nil), forCellReuseIdentifier: followGroupCell)
|
||||
tableView.register(UINib(nibName: "TimelineStatusTableViewCell", bundle: .main), forCellReuseIdentifier: statusCell)
|
||||
tableView.register(UINib(nibName: "ActionNotificationGroupTableViewCell", bundle: .main), forCellReuseIdentifier: actionGroupCell)
|
||||
tableView.register(UINib(nibName: "FollowNotificationGroupTableViewCell", bundle: .main), forCellReuseIdentifier: followGroupCell)
|
||||
tableView.register(UINib(nibName: "FollowRequestNotificationTableViewCell", bundle: .main), forCellReuseIdentifier: followRequestCell)
|
||||
|
||||
tableView.prefetchDataSource = self
|
||||
|
||||
|
@ -102,10 +104,17 @@ class NotificationsTableViewController: EnhancedTableViewController {
|
|||
return cell
|
||||
|
||||
case .follow:
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: "followGroupCell", for: indexPath) as? FollowNotificationGroupTableViewCell else { fatalError() }
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: followGroupCell, for: indexPath) as? FollowNotificationGroupTableViewCell else { fatalError() }
|
||||
cell.updateUI(group: group)
|
||||
cell.delegate = self
|
||||
return cell
|
||||
|
||||
case .followRequest:
|
||||
guard let notification = MastodonCache.notification(for: group.notificationIDs.first!),
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: followRequestCell, for: indexPath) as? FollowRequestNotificationTableViewCell else { fatalError() }
|
||||
cell.updateUI(notification: notification)
|
||||
cell.delegate = self
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="15701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<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="retina6_1" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15703"/>
|
||||
<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>
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
//
|
||||
// FollowRequestNotificationTableViewCell.swift
|
||||
// Tusker
|
||||
//
|
||||
// Created by Shadowfacts on 1/4/20.
|
||||
// Copyright © 2020 Shadowfacts. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Pachyderm
|
||||
|
||||
class FollowRequestNotificationTableViewCell: UITableViewCell {
|
||||
|
||||
var delegate: TuskerNavigationDelegate?
|
||||
|
||||
@IBOutlet weak var stackView: UIStackView!
|
||||
@IBOutlet weak var avatarImageView: UIImageView!
|
||||
@IBOutlet weak var timestampLabel: UILabel!
|
||||
@IBOutlet weak var actionLabel: UILabel!
|
||||
@IBOutlet weak var actionButtonsStackView: UIStackView!
|
||||
@IBOutlet weak var acceptButton: UIButton!
|
||||
@IBOutlet weak var rejectButton: UIButton!
|
||||
|
||||
var notification: Pachyderm.Notification?
|
||||
var account: Account!
|
||||
|
||||
var updateTimestampWorkItem: DispatchWorkItem?
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
avatarImageView.layer.masksToBounds = true
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(updateUIForPreferences), name: .preferencesChanged, object: nil)
|
||||
updateUIForPreferences()
|
||||
}
|
||||
|
||||
@objc func updateUIForPreferences() {
|
||||
avatarImageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadiusFraction * 30
|
||||
}
|
||||
|
||||
func updateUI(notification: Pachyderm.Notification) {
|
||||
self.notification = notification
|
||||
updateUI(account: notification.account)
|
||||
updateTimestamp()
|
||||
}
|
||||
|
||||
func updateUI(account: Account) {
|
||||
self.account = account
|
||||
actionLabel.text = "Request to follow from \(account.realDisplayName)"
|
||||
ImageCache.avatars.get(account.avatar) { (data) in
|
||||
guard self.account == account, let data = data, let image = UIImage(data: data) else { return }
|
||||
DispatchQueue.main.async {
|
||||
self.avatarImageView.image = image
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateTimestamp() {
|
||||
guard let notification = notification else { return }
|
||||
|
||||
timestampLabel.text = notification.createdAt.timeAgoString()
|
||||
|
||||
let delay: DispatchTimeInterval?
|
||||
switch notification.createdAt.timeAgo().1 {
|
||||
case .second:
|
||||
delay = .seconds(10)
|
||||
case .minute:
|
||||
delay = .seconds(60)
|
||||
default:
|
||||
delay = nil
|
||||
}
|
||||
if let delay = delay {
|
||||
updateTimestampWorkItem = DispatchWorkItem(block: self.updateTimestamp)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: updateTimestampWorkItem!)
|
||||
} else {
|
||||
updateTimestampWorkItem = nil
|
||||
}
|
||||
}
|
||||
|
||||
override func prepareForReuse() {
|
||||
super.prepareForReuse()
|
||||
|
||||
updateTimestampWorkItem?.cancel()
|
||||
updateTimestampWorkItem = nil
|
||||
}
|
||||
|
||||
// MARK: - Interaction
|
||||
|
||||
@IBAction func rejectButtonPressed() {
|
||||
let request = Account.rejectFollowRequest(account)
|
||||
MastodonController.client.run(request) { (response) in
|
||||
guard case let .success(relationship, _) = response else { fatalError() }
|
||||
MastodonCache.add(relationship: relationship)
|
||||
DispatchQueue.main.async {
|
||||
UINotificationFeedbackGenerator().notificationOccurred(.success)
|
||||
self.actionButtonsStackView.isHidden = true
|
||||
let label = UILabel()
|
||||
label.textAlignment = .center
|
||||
label.font = .boldSystemFont(ofSize: 17)
|
||||
label.text = NSLocalizedString("Rejected", comment: "rejected follow request label")
|
||||
self.stackView.addArrangedSubview(label)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func acceptButtonPressed() {
|
||||
let request = Account.authorizeFollowRequest(account)
|
||||
MastodonController.client.run(request) { (response) in
|
||||
guard case let .success(relationship, _) = response else { fatalError() }
|
||||
MastodonCache.add(relationship: relationship)
|
||||
DispatchQueue.main.async {
|
||||
UINotificationFeedbackGenerator().notificationOccurred(.success)
|
||||
self.actionButtonsStackView.isHidden = true
|
||||
let label = UILabel()
|
||||
label.textAlignment = .center
|
||||
label.font = .boldSystemFont(ofSize: 17)
|
||||
label.text = NSLocalizedString("Accepted", comment: "accepted follow request label")
|
||||
self.stackView.addArrangedSubview(label)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FollowRequestNotificationTableViewCell: SelectableTableViewCell {
|
||||
func didSelectCell() {
|
||||
delegate?.selected(account: account.id)
|
||||
}
|
||||
}
|
||||
|
||||
extension FollowRequestNotificationTableViewCell: MenuPreviewProvider {
|
||||
var navigationDelegate: TuskerNavigationDelegate? { return delegate }
|
||||
|
||||
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? {
|
||||
return (content: {
|
||||
return ProfileTableViewController(accountID: self.account.id)
|
||||
}, actions: {
|
||||
return []
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
<?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="retina6_1" 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"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="107" id="Pcu-ap-Xqf" customClass="FollowRequestNotificationTableViewCell" customModule="Tusker" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="107"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Pcu-ap-Xqf" id="Ulr-P8-MK9">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="107"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="4" translatesAutoresizingMaskIntoConstraints="NO" id="Cth-1T-Km3">
|
||||
<rect key="frame" x="74" y="11" width="230" height="85"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="G6v-p7-JbC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="230" height="30"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="0j2-g5-Y0W">
|
||||
<rect key="frame" x="0.0" y="0.0" width="30" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="0j2-g5-Y0W" secondAttribute="height" multiplier="1:1" id="05S-TD-ePl"/>
|
||||
<constraint firstAttribute="height" constant="30" id="KCp-Zt-Cm6"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<view contentMode="scaleToFill" horizontalHuggingPriority="249" translatesAutoresizingMaskIntoConstraints="NO" id="9WN-Ql-DDL">
|
||||
<rect key="frame" x="30" y="0.0" width="175.5" height="30"/>
|
||||
</view>
|
||||
<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="Saq-P5-oVH">
|
||||
<rect key="frame" x="205.5" y="0.0" width="24.5" height="30"/>
|
||||
<fontDescription key="fontDescription" type="system" weight="light" pointSize="17"/>
|
||||
<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>
|
||||
</subviews>
|
||||
</stackView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Request to follow by Person 1" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aM6-C6-9QH">
|
||||
<rect key="frame" x="0.0" y="34" width="230" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" translatesAutoresizingMaskIntoConstraints="NO" id="20F-2n-eQx">
|
||||
<rect key="frame" x="0.0" y="58.5" width="230" height="26.5"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CMQ-TI-X9k">
|
||||
<rect key="frame" x="0.0" y="0.0" width="115" height="26.5"/>
|
||||
<state key="normal" image="checkmark.circle.fill" catalog="system">
|
||||
<preferredSymbolConfiguration key="preferredSymbolConfiguration" configurationType="pointSize" pointSize="22"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="acceptButtonPressed" destination="Pcu-ap-Xqf" eventType="touchUpInside" id="hGw-3d-RNi"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="7MW-rY-m5l">
|
||||
<rect key="frame" x="115" y="0.0" width="115" height="26.5"/>
|
||||
<state key="normal" image="xmark.circle.fill" catalog="system">
|
||||
<preferredSymbolConfiguration key="preferredSymbolConfiguration" configurationType="pointSize" pointSize="22"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="rejectButtonPressed" destination="Pcu-ap-Xqf" eventType="touchUpInside" id="EP6-Bg-3nC"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</stackView>
|
||||
</subviews>
|
||||
</stackView>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="person.fill" catalog="system" translatesAutoresizingMaskIntoConstraints="NO" id="1qX-LD-7ZK">
|
||||
<rect key="frame" x="36" y="12.5" width="30" height="27"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="UDV-Vb-1bn"/>
|
||||
<constraint firstAttribute="width" constant="30" id="d5A-cf-hFe"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="Cth-1T-Km3" secondAttribute="trailing" id="9Zn-8U-6HF"/>
|
||||
<constraint firstItem="Cth-1T-Km3" firstAttribute="top" secondItem="Ulr-P8-MK9" secondAttribute="topMargin" id="EIi-sE-AkN"/>
|
||||
<constraint firstItem="1qX-LD-7ZK" firstAttribute="top" secondItem="Ulr-P8-MK9" secondAttribute="topMargin" id="GUW-Xm-fLN"/>
|
||||
<constraint firstItem="Cth-1T-Km3" firstAttribute="leading" secondItem="Ulr-P8-MK9" secondAttribute="leadingMargin" constant="58" id="QvY-68-add"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="Cth-1T-Km3" secondAttribute="bottom" id="aje-GB-qn6"/>
|
||||
<constraint firstItem="Cth-1T-Km3" firstAttribute="leading" secondItem="1qX-LD-7ZK" secondAttribute="trailing" constant="8" id="qnO-DF-3wu"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<viewLayoutGuide key="safeArea" id="ctM-Hq-1Oz"/>
|
||||
<connections>
|
||||
<outlet property="acceptButton" destination="CMQ-TI-X9k" id="xL1-MG-SHi"/>
|
||||
<outlet property="actionButtonsStackView" destination="20F-2n-eQx" id="Uaj-3F-N05"/>
|
||||
<outlet property="actionLabel" destination="aM6-C6-9QH" id="UfY-EF-7Ya"/>
|
||||
<outlet property="avatarImageView" destination="0j2-g5-Y0W" id="3Qj-5q-e73"/>
|
||||
<outlet property="rejectButton" destination="7MW-rY-m5l" id="ZeH-FG-T7M"/>
|
||||
<outlet property="stackView" destination="Cth-1T-Km3" id="Elz-8v-AFa"/>
|
||||
<outlet property="timestampLabel" destination="Saq-P5-oVH" id="d6F-HV-HXs"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="131.8840579710145" y="174.44196428571428"/>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="checkmark.circle.fill" catalog="system" width="64" height="60"/>
|
||||
<image name="person.fill" catalog="system" width="64" height="60"/>
|
||||
<image name="xmark.circle.fill" catalog="system" width="64" height="60"/>
|
||||
</resources>
|
||||
</document>
|
Loading…
Reference in New Issue