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 fields: [Field]?
|
||||||
public let bot: Bool?
|
public let bot: Bool?
|
||||||
|
|
||||||
public static func authorizeFollowRequest(_ account: Account) -> Request<Empty> {
|
public static func authorizeFollowRequest(_ account: Account) -> Request<Relationship> {
|
||||||
return Request<Empty>(method: .post, path: "/api/v1/follow_requests/\(account.id)/authorize")
|
return Request<Relationship>(method: .post, path: "/api/v1/follow_requests/\(account.id)/authorize")
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func rejectFollowRequest(_ account: Account) -> Request<Empty> {
|
public static func rejectFollowRequest(_ account: Account) -> Request<Relationship> {
|
||||||
return Request<Empty>(method: .post, path: "/api/v1/follow_requests/\(account.id)/reject")
|
return Request<Relationship>(method: .post, path: "/api/v1/follow_requests/\(account.id)/reject")
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func removeFromFollowRequests(_ account: Account) -> Request<Empty> {
|
public static func removeFromFollowRequests(_ account: Account) -> Request<Empty> {
|
||||||
|
|
|
@ -36,6 +36,7 @@ extension Notification {
|
||||||
case reblog
|
case reblog
|
||||||
case favourite
|
case favourite
|
||||||
case follow
|
case follow
|
||||||
|
case followRequest = "follow_request"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,8 @@
|
||||||
D64BC18623C1253A000D0238 /* AssetPreviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64BC18523C1253A000D0238 /* AssetPreviewViewController.swift */; };
|
D64BC18623C1253A000D0238 /* AssetPreviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64BC18523C1253A000D0238 /* AssetPreviewViewController.swift */; };
|
||||||
D64BC18823C1640A000D0238 /* PinStatusActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64BC18723C1640A000D0238 /* PinStatusActivity.swift */; };
|
D64BC18823C1640A000D0238 /* PinStatusActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64BC18723C1640A000D0238 /* PinStatusActivity.swift */; };
|
||||||
D64BC18A23C16487000D0238 /* UnpinStatusActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64BC18923C16487000D0238 /* UnpinStatusActivity.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 */; };
|
D64D0AAD2128D88B005A6F37 /* LocalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AAC2128D88B005A6F37 /* LocalData.swift */; };
|
||||||
D64D0AB12128D9AE005A6F37 /* OnboardingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */; };
|
D64D0AB12128D9AE005A6F37 /* OnboardingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */; };
|
||||||
D64F80E2215875CC00BEF393 /* XCBActionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64F80E1215875CC00BEF393 /* XCBActionType.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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
D64F80E1215875CC00BEF393 /* XCBActionType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCBActionType.swift; sourceTree = "<group>"; };
|
||||||
|
@ -906,6 +910,8 @@
|
||||||
D6A3BC7B232195C600FD64D5 /* ActionNotificationGroupTableViewCell.xib */,
|
D6A3BC7B232195C600FD64D5 /* ActionNotificationGroupTableViewCell.xib */,
|
||||||
D6A3BC7E2321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.swift */,
|
D6A3BC7E2321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.swift */,
|
||||||
D6A3BC7F2321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.xib */,
|
D6A3BC7F2321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.xib */,
|
||||||
|
D64BC18D23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.swift */,
|
||||||
|
D64BC18E23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.xib */,
|
||||||
);
|
);
|
||||||
path = Notifications;
|
path = Notifications;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1482,6 +1488,7 @@
|
||||||
D626493323BD751600612E6E /* ShowCameraCollectionViewCell.xib in Resources */,
|
D626493323BD751600612E6E /* ShowCameraCollectionViewCell.xib in Resources */,
|
||||||
D626493D23C1000300612E6E /* AlbumTableViewCell.xib in Resources */,
|
D626493D23C1000300612E6E /* AlbumTableViewCell.xib in Resources */,
|
||||||
D627944723A6AC9300D38C68 /* BasicTableViewCell.xib in Resources */,
|
D627944723A6AC9300D38C68 /* BasicTableViewCell.xib in Resources */,
|
||||||
|
D64BC19023C18B9D000D0238 /* FollowRequestNotificationTableViewCell.xib in Resources */,
|
||||||
D67C57B221E28FAD00C3118B /* ComposeStatusReplyView.xib in Resources */,
|
D67C57B221E28FAD00C3118B /* ComposeStatusReplyView.xib in Resources */,
|
||||||
0411610122B442870030A9B7 /* AttachmentViewController.xib in Resources */,
|
0411610122B442870030A9B7 /* AttachmentViewController.xib in Resources */,
|
||||||
D6A3BC812321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.xib in Resources */,
|
D6A3BC812321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.xib in Resources */,
|
||||||
|
@ -1614,6 +1621,7 @@
|
||||||
D6BC9DB3232D4C07002CA326 /* WellnessPrefsView.swift in Sources */,
|
D6BC9DB3232D4C07002CA326 /* WellnessPrefsView.swift in Sources */,
|
||||||
D6D58DF922074B74009C8DD9 /* LinkLabel.swift in Sources */,
|
D6D58DF922074B74009C8DD9 /* LinkLabel.swift in Sources */,
|
||||||
0454DDAF22B462EF00B8BB8E /* GalleryExpandAnimationController.swift in Sources */,
|
0454DDAF22B462EF00B8BB8E /* GalleryExpandAnimationController.swift in Sources */,
|
||||||
|
D64BC18F23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.swift in Sources */,
|
||||||
D6A3BC8A2321F79B00FD64D5 /* AccountTableViewCell.swift in Sources */,
|
D6A3BC8A2321F79B00FD64D5 /* AccountTableViewCell.swift in Sources */,
|
||||||
D66A77BB233838DC0058F1EC /* UIFont+Traits.swift in Sources */,
|
D66A77BB233838DC0058F1EC /* UIFont+Traits.swift in Sources */,
|
||||||
D68FEC4F232C5BC300C84F23 /* SegmentedPageViewController.swift in Sources */,
|
D68FEC4F232C5BC300C84F23 /* SegmentedPageViewController.swift in Sources */,
|
||||||
|
|
|
@ -12,7 +12,9 @@ import Pachyderm
|
||||||
extension Account {
|
extension Account {
|
||||||
|
|
||||||
var realDisplayName: String {
|
var realDisplayName: String {
|
||||||
if Preferences.shared.hideCustomEmojiInUsernames {
|
if displayName.isEmpty {
|
||||||
|
return username
|
||||||
|
} else if Preferences.shared.hideCustomEmojiInUsernames {
|
||||||
return stripCustomEmoji(from: displayName)
|
return stripCustomEmoji(from: displayName)
|
||||||
} else {
|
} else {
|
||||||
return displayName
|
return displayName
|
||||||
|
|
|
@ -13,7 +13,7 @@ class NotificationsPageViewController: SegmentedPageViewController {
|
||||||
|
|
||||||
private let notificationsTitle = NSLocalizedString("Notifications", comment: "notifications tab title")
|
private let notificationsTitle = NSLocalizedString("Notifications", comment: "notifications tab title")
|
||||||
private let mentionsTitle = NSLocalizedString("Mentions", comment: "mentions tab title")
|
private let mentionsTitle = NSLocalizedString("Mentions", comment: "mentions tab title")
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
let notifications = NotificationsTableViewController(allowedTypes: Pachyderm.Notification.Kind.allCases)
|
let notifications = NotificationsTableViewController(allowedTypes: Pachyderm.Notification.Kind.allCases)
|
||||||
notifications.title = notificationsTitle
|
notifications.title = notificationsTitle
|
||||||
|
|
|
@ -14,6 +14,7 @@ class NotificationsTableViewController: EnhancedTableViewController {
|
||||||
private let statusCell = "statusCell"
|
private let statusCell = "statusCell"
|
||||||
private let actionGroupCell = "actionGroupCell"
|
private let actionGroupCell = "actionGroupCell"
|
||||||
private let followGroupCell = "followGroupCell"
|
private let followGroupCell = "followGroupCell"
|
||||||
|
private let followRequestCell = "followRequestCell"
|
||||||
|
|
||||||
let excludedTypes: [Pachyderm.Notification.Kind]
|
let excludedTypes: [Pachyderm.Notification.Kind]
|
||||||
let groupTypes = [Notification.Kind.favourite, .reblog, .follow]
|
let groupTypes = [Notification.Kind.favourite, .reblog, .follow]
|
||||||
|
@ -48,9 +49,10 @@ class NotificationsTableViewController: EnhancedTableViewController {
|
||||||
tableView.rowHeight = UITableView.automaticDimension
|
tableView.rowHeight = UITableView.automaticDimension
|
||||||
tableView.estimatedRowHeight = 140
|
tableView.estimatedRowHeight = 140
|
||||||
|
|
||||||
tableView.register(UINib(nibName: "TimelineStatusTableViewCell", bundle: nil), forCellReuseIdentifier: statusCell)
|
tableView.register(UINib(nibName: "TimelineStatusTableViewCell", bundle: .main), forCellReuseIdentifier: statusCell)
|
||||||
tableView.register(UINib(nibName: "ActionNotificationGroupTableViewCell", bundle: nil), forCellReuseIdentifier: actionGroupCell)
|
tableView.register(UINib(nibName: "ActionNotificationGroupTableViewCell", bundle: .main), forCellReuseIdentifier: actionGroupCell)
|
||||||
tableView.register(UINib(nibName: "FollowNotificationGroupTableViewCell", bundle: nil), forCellReuseIdentifier: followGroupCell)
|
tableView.register(UINib(nibName: "FollowNotificationGroupTableViewCell", bundle: .main), forCellReuseIdentifier: followGroupCell)
|
||||||
|
tableView.register(UINib(nibName: "FollowRequestNotificationTableViewCell", bundle: .main), forCellReuseIdentifier: followRequestCell)
|
||||||
|
|
||||||
tableView.prefetchDataSource = self
|
tableView.prefetchDataSource = self
|
||||||
|
|
||||||
|
@ -102,10 +104,17 @@ class NotificationsTableViewController: EnhancedTableViewController {
|
||||||
return cell
|
return cell
|
||||||
|
|
||||||
case .follow:
|
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.updateUI(group: group)
|
||||||
cell.delegate = self
|
cell.delegate = self
|
||||||
return cell
|
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"?>
|
<?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"/>
|
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<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="Safe area layout guides" minToolsVersion="9.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</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