Compare commits
2 Commits
a363308147
...
76bc6a665c
Author | SHA1 | Date |
---|---|---|
Shadowfacts | 76bc6a665c | |
Shadowfacts | a8ae559c9d |
|
@ -148,6 +148,10 @@
|
||||||
D6A3BC7D232195C600FD64D5 /* ActionNotificationGroupTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6A3BC7B232195C600FD64D5 /* ActionNotificationGroupTableViewCell.xib */; };
|
D6A3BC7D232195C600FD64D5 /* ActionNotificationGroupTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6A3BC7B232195C600FD64D5 /* ActionNotificationGroupTableViewCell.xib */; };
|
||||||
D6A3BC802321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A3BC7E2321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.swift */; };
|
D6A3BC802321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A3BC7E2321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.swift */; };
|
||||||
D6A3BC812321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6A3BC7F2321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.xib */; };
|
D6A3BC812321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6A3BC7F2321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.xib */; };
|
||||||
|
D6A3BC852321F6C100FD64D5 /* AccountListTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A3BC832321F6C100FD64D5 /* AccountListTableViewController.swift */; };
|
||||||
|
D6A3BC862321F6C100FD64D5 /* AccountListTableViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6A3BC842321F6C100FD64D5 /* AccountListTableViewController.xib */; };
|
||||||
|
D6A3BC8A2321F79B00FD64D5 /* AccountTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A3BC882321F79B00FD64D5 /* AccountTableViewCell.swift */; };
|
||||||
|
D6A3BC8B2321F79B00FD64D5 /* AccountTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6A3BC892321F79B00FD64D5 /* AccountTableViewCell.xib */; };
|
||||||
D6A5FAF1217B7E05003DB2D9 /* ComposeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6A5FAF0217B7E05003DB2D9 /* ComposeViewController.xib */; };
|
D6A5FAF1217B7E05003DB2D9 /* ComposeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6A5FAF0217B7E05003DB2D9 /* ComposeViewController.xib */; };
|
||||||
D6A5FAFB217B86CE003DB2D9 /* OnboardingViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6A5FAFA217B86CE003DB2D9 /* OnboardingViewController.xib */; };
|
D6A5FAFB217B86CE003DB2D9 /* OnboardingViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6A5FAFA217B86CE003DB2D9 /* OnboardingViewController.xib */; };
|
||||||
D6AEBB3E2321638100E5038B /* UIActivity+Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6AEBB3D2321638100E5038B /* UIActivity+Types.swift */; };
|
D6AEBB3E2321638100E5038B /* UIActivity+Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6AEBB3D2321638100E5038B /* UIActivity+Types.swift */; };
|
||||||
|
@ -389,6 +393,10 @@
|
||||||
D6A3BC7B232195C600FD64D5 /* ActionNotificationGroupTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ActionNotificationGroupTableViewCell.xib; sourceTree = "<group>"; };
|
D6A3BC7B232195C600FD64D5 /* ActionNotificationGroupTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ActionNotificationGroupTableViewCell.xib; sourceTree = "<group>"; };
|
||||||
D6A3BC7E2321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowNotificationGroupTableViewCell.swift; sourceTree = "<group>"; };
|
D6A3BC7E2321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowNotificationGroupTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
D6A3BC7F2321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FollowNotificationGroupTableViewCell.xib; sourceTree = "<group>"; };
|
D6A3BC7F2321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FollowNotificationGroupTableViewCell.xib; sourceTree = "<group>"; };
|
||||||
|
D6A3BC832321F6C100FD64D5 /* AccountListTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountListTableViewController.swift; sourceTree = "<group>"; };
|
||||||
|
D6A3BC842321F6C100FD64D5 /* AccountListTableViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AccountListTableViewController.xib; sourceTree = "<group>"; };
|
||||||
|
D6A3BC882321F79B00FD64D5 /* AccountTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
|
D6A3BC892321F79B00FD64D5 /* AccountTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AccountTableViewCell.xib; sourceTree = "<group>"; };
|
||||||
D6A5FAF0217B7E05003DB2D9 /* ComposeViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ComposeViewController.xib; sourceTree = "<group>"; };
|
D6A5FAF0217B7E05003DB2D9 /* ComposeViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ComposeViewController.xib; sourceTree = "<group>"; };
|
||||||
D6A5FAFA217B86CE003DB2D9 /* OnboardingViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = OnboardingViewController.xib; sourceTree = "<group>"; };
|
D6A5FAFA217B86CE003DB2D9 /* OnboardingViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = OnboardingViewController.xib; sourceTree = "<group>"; };
|
||||||
D6AEBB3D2321638100E5038B /* UIActivity+Types.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIActivity+Types.swift"; sourceTree = "<group>"; };
|
D6AEBB3D2321638100E5038B /* UIActivity+Types.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIActivity+Types.swift"; sourceTree = "<group>"; };
|
||||||
|
@ -674,6 +682,7 @@
|
||||||
D641C788213DD86D004B4513 /* Large Image */,
|
D641C788213DD86D004B4513 /* Large Image */,
|
||||||
0411610422B4571E0030A9B7 /* Attachment */,
|
0411610422B4571E0030A9B7 /* Attachment */,
|
||||||
0411610522B457290030A9B7 /* Gallery */,
|
0411610522B457290030A9B7 /* Gallery */,
|
||||||
|
D6A3BC822321F69400FD64D5 /* Account List */,
|
||||||
D641C789213DD87E004B4513 /* Preferences */,
|
D641C789213DD87E004B4513 /* Preferences */,
|
||||||
);
|
);
|
||||||
path = Screens;
|
path = Screens;
|
||||||
|
@ -941,6 +950,24 @@
|
||||||
path = Utilities;
|
path = Utilities;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
D6A3BC822321F69400FD64D5 /* Account List */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
D6A3BC832321F6C100FD64D5 /* AccountListTableViewController.swift */,
|
||||||
|
D6A3BC842321F6C100FD64D5 /* AccountListTableViewController.xib */,
|
||||||
|
);
|
||||||
|
path = "Account List";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
D6A3BC872321F78000FD64D5 /* Account Cell */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
D6A3BC882321F79B00FD64D5 /* AccountTableViewCell.swift */,
|
||||||
|
D6A3BC892321F79B00FD64D5 /* AccountTableViewCell.xib */,
|
||||||
|
);
|
||||||
|
path = "Account Cell";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
D6AEBB3F2321640F00E5038B /* Activities */ = {
|
D6AEBB3F2321640F00E5038B /* Activities */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -977,6 +1004,7 @@
|
||||||
D6C7D27B22B6EBE200071952 /* Attachments */,
|
D6C7D27B22B6EBE200071952 /* Attachments */,
|
||||||
D641C78B213DD92F004B4513 /* Profile Header */,
|
D641C78B213DD92F004B4513 /* Profile Header */,
|
||||||
D641C78C213DD937004B4513 /* Notifications */,
|
D641C78C213DD937004B4513 /* Notifications */,
|
||||||
|
D6A3BC872321F78000FD64D5 /* Account Cell */,
|
||||||
);
|
);
|
||||||
path = Views;
|
path = Views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1338,6 +1366,8 @@
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
D6A3BC862321F6C100FD64D5 /* AccountListTableViewController.xib in Resources */,
|
||||||
|
D6A3BC8B2321F79B00FD64D5 /* AccountTableViewCell.xib in Resources */,
|
||||||
D627FF7D217E958900CC0648 /* DraftTableViewCell.xib in Resources */,
|
D627FF7D217E958900CC0648 /* DraftTableViewCell.xib in Resources */,
|
||||||
D6A3BC7D232195C600FD64D5 /* ActionNotificationGroupTableViewCell.xib in Resources */,
|
D6A3BC7D232195C600FD64D5 /* ActionNotificationGroupTableViewCell.xib in Resources */,
|
||||||
D667E5E921349EE50057A976 /* ProfileHeaderTableViewCell.xib in Resources */,
|
D667E5E921349EE50057A976 /* ProfileHeaderTableViewCell.xib in Resources */,
|
||||||
|
@ -1453,6 +1483,7 @@
|
||||||
D6C693F92162E4DB007D6A6D /* StatusContentLabel.swift in Sources */,
|
D6C693F92162E4DB007D6A6D /* StatusContentLabel.swift in Sources */,
|
||||||
D6D58DF922074B74009C8DD9 /* LinkLabel.swift in Sources */,
|
D6D58DF922074B74009C8DD9 /* LinkLabel.swift in Sources */,
|
||||||
0454DDAF22B462EF00B8BB8E /* GalleryExpandAnimationController.swift in Sources */,
|
0454DDAF22B462EF00B8BB8E /* GalleryExpandAnimationController.swift in Sources */,
|
||||||
|
D6A3BC8A2321F79B00FD64D5 /* AccountTableViewCell.swift in Sources */,
|
||||||
0450531F22B0097E00100BA2 /* Timline+UI.swift in Sources */,
|
0450531F22B0097E00100BA2 /* Timline+UI.swift in Sources */,
|
||||||
D667E5F52135BCD50057A976 /* ConversationTableViewController.swift in Sources */,
|
D667E5F52135BCD50057A976 /* ConversationTableViewController.swift in Sources */,
|
||||||
D6C7D27D22B6EBF800071952 /* AttachmentsContainerView.swift in Sources */,
|
D6C7D27D22B6EBF800071952 /* AttachmentsContainerView.swift in Sources */,
|
||||||
|
@ -1465,6 +1496,7 @@
|
||||||
D62D2422217AA7E1005076CC /* UserActivityManager.swift in Sources */,
|
D62D2422217AA7E1005076CC /* UserActivityManager.swift in Sources */,
|
||||||
D62D2424217ABF3F005076CC /* NSUserActivity+Extensions.swift in Sources */,
|
D62D2424217ABF3F005076CC /* NSUserActivity+Extensions.swift in Sources */,
|
||||||
D646C958213B367000269FB5 /* LargeImageShrinkAnimationController.swift in Sources */,
|
D646C958213B367000269FB5 /* LargeImageShrinkAnimationController.swift in Sources */,
|
||||||
|
D6A3BC852321F6C100FD64D5 /* AccountListTableViewController.swift in Sources */,
|
||||||
D646C956213B365700269FB5 /* LargeImageExpandAnimationController.swift in Sources */,
|
D646C956213B365700269FB5 /* LargeImageExpandAnimationController.swift in Sources */,
|
||||||
0454DDB122B467AA00B8BB8E /* GalleryShrinkAnimationController.swift in Sources */,
|
0454DDB122B467AA00B8BB8E /* GalleryShrinkAnimationController.swift in Sources */,
|
||||||
D667E5F82135C3040057A976 /* Mastodon+Equatable.swift in Sources */,
|
D667E5F82135C3040057A976 /* Mastodon+Equatable.swift in Sources */,
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
//
|
||||||
|
// AccountListTableViewController.swift
|
||||||
|
// Tusker
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 9/5/19.
|
||||||
|
// Copyright © 2019 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class AccountListTableViewController: UITableViewController {
|
||||||
|
|
||||||
|
private let accountCell = "accountCell"
|
||||||
|
|
||||||
|
let accountIDs: [String]
|
||||||
|
|
||||||
|
init(accountIDs: [String]) {
|
||||||
|
self.accountIDs = accountIDs
|
||||||
|
|
||||||
|
super.init(nibName: "AccountListTableViewController", bundle: .main)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
tableView.register(UINib(nibName: "AccountTableViewCell", bundle: .main), forCellReuseIdentifier: accountCell)
|
||||||
|
|
||||||
|
tableView.rowHeight = 66
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Table view data source
|
||||||
|
|
||||||
|
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||||
|
return accountIDs.count
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||||
|
guard let cell = tableView.dequeueReusableCell(withIdentifier: accountCell, for: indexPath) as? AccountTableViewCell else { fatalError() }
|
||||||
|
|
||||||
|
let id = accountIDs[indexPath.row]
|
||||||
|
cell.updateUI(accountID: id)
|
||||||
|
cell.delegate = self
|
||||||
|
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension AccountListTableViewController: TuskerNavigationDelegate {}
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13142" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||||
|
<dependencies>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12042"/>
|
||||||
|
<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" customClass="AccountListTableViewController" customModuleProvider="target">
|
||||||
|
<connections>
|
||||||
|
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
|
||||||
|
</connections>
|
||||||
|
</placeholder>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||||
|
<tableView opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" bouncesZoom="NO" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="i5M-Pr-FkT">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<viewLayoutGuide key="safeArea" id="vLr-E1-eTs"/>
|
||||||
|
<connections>
|
||||||
|
<outlet property="dataSource" destination="-1" id="Tng-2m-Rnh"/>
|
||||||
|
<outlet property="delegate" destination="-1" id="9aC-8N-iBw"/>
|
||||||
|
</connections>
|
||||||
|
</tableView>
|
||||||
|
</objects>
|
||||||
|
</document>
|
|
@ -41,6 +41,8 @@ protocol TuskerNavigationDelegate {
|
||||||
func showMoreOptions(forStatus statusID: String)
|
func showMoreOptions(forStatus statusID: String)
|
||||||
|
|
||||||
func showMoreOptions(forURL url: URL)
|
func showMoreOptions(forURL url: URL)
|
||||||
|
|
||||||
|
func showFollowedByList(accountIDs: [String])
|
||||||
}
|
}
|
||||||
|
|
||||||
extension TuskerNavigationDelegate where Self: UIViewController {
|
extension TuskerNavigationDelegate where Self: UIViewController {
|
||||||
|
@ -169,4 +171,10 @@ extension TuskerNavigationDelegate where Self: UIViewController {
|
||||||
present(moreOptions(forURL: url), animated: true)
|
present(moreOptions(forURL: url), animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func showFollowedByList(accountIDs: [String]) {
|
||||||
|
let vc = AccountListTableViewController(accountIDs: accountIDs)
|
||||||
|
vc.title = NSLocalizedString("Followed By", comment: "followed by accounts list title")
|
||||||
|
show(vc, sender: self)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
//
|
||||||
|
// AccountTableViewCell.swift
|
||||||
|
// Tusker
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 9/5/19.
|
||||||
|
// Copyright © 2019 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class AccountTableViewCell: UITableViewCell {
|
||||||
|
|
||||||
|
var delegate: TuskerNavigationDelegate?
|
||||||
|
|
||||||
|
@IBOutlet weak var avatarImageView: UIImageView!
|
||||||
|
@IBOutlet weak var displayNameLabel: UILabel!
|
||||||
|
@IBOutlet weak var usernameLabel: UILabel!
|
||||||
|
|
||||||
|
var accountID: String!
|
||||||
|
|
||||||
|
var avatarURL: URL?
|
||||||
|
|
||||||
|
override func awakeFromNib() {
|
||||||
|
super.awakeFromNib()
|
||||||
|
|
||||||
|
avatarImageView.layer.masksToBounds = true
|
||||||
|
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(updateUIForPrefrences), name: .preferencesChanged, object: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func updateUIForPrefrences() {
|
||||||
|
avatarImageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadius(for: avatarImageView)
|
||||||
|
|
||||||
|
guard let account = MastodonCache.account(for: accountID) else {
|
||||||
|
fatalError("Missing cached account \(accountID!)")
|
||||||
|
}
|
||||||
|
displayNameLabel.text = account.realDisplayName
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateUI(accountID: String) {
|
||||||
|
self.accountID = accountID
|
||||||
|
guard let account = MastodonCache.account(for: accountID) else {
|
||||||
|
fatalError("Missing cached account \(accountID)")
|
||||||
|
}
|
||||||
|
|
||||||
|
self.avatarURL = account.avatar
|
||||||
|
ImageCache.avatars.get(account.avatar) { (data) in
|
||||||
|
guard let data = data, self.avatarURL == account.avatar else { return }
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.avatarImageView.image = UIImage(data: data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
displayNameLabel.text = account.realDisplayName
|
||||||
|
usernameLabel.text = "@\(account.acct)"
|
||||||
|
}
|
||||||
|
|
||||||
|
override func setSelected(_ selected: Bool, animated: Bool) {
|
||||||
|
super.setSelected(selected, animated: animated)
|
||||||
|
|
||||||
|
if selected {
|
||||||
|
delegate?.selected(account: accountID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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="retina6_1" orientation="portrait" appearance="light"/>
|
||||||
|
<dependencies>
|
||||||
|
<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"/>
|
||||||
|
</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="66" id="KGk-i7-Jjw" customClass="AccountTableViewCell" customModule="Tusker" customModuleProvider="target">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="320" height="66"/>
|
||||||
|
<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"/>
|
||||||
|
<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="height" constant="50" id="NqI-m0-owe"/>
|
||||||
|
<constraint firstAttribute="width" constant="50" id="lar-P0-gRh"/>
|
||||||
|
</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"/>
|
||||||
|
<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">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="230" height="26"/>
|
||||||
|
<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"/>
|
||||||
|
<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>
|
||||||
|
</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"/>
|
||||||
|
<constraint firstItem="Iif-9m-vM5" firstAttribute="leading" secondItem="Rp2-O5-Vew" secondAttribute="trailing" constant="8" id="sk1-KY-Ttj"/>
|
||||||
|
<constraint firstItem="Rp2-O5-Vew" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" constant="8" id="xpB-wY-5d6"/>
|
||||||
|
<constraint firstItem="Rp2-O5-Vew" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" id="yd4-AU-qbj"/>
|
||||||
|
</constraints>
|
||||||
|
</tableViewCellContentView>
|
||||||
|
<viewLayoutGuide key="safeArea" id="njF-e1-oar"/>
|
||||||
|
<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="usernameLabel" destination="JMo-QH-1is" id="ElX-ua-xcQ"/>
|
||||||
|
</connections>
|
||||||
|
<point key="canvasLocation" x="173.91304347826087" y="24.107142857142858"/>
|
||||||
|
</tableViewCell>
|
||||||
|
</objects>
|
||||||
|
</document>
|
|
@ -94,7 +94,7 @@ class ActionNotificationGroupTableViewCell: UITableViewCell {
|
||||||
func updateTimestamp() {
|
func updateTimestamp() {
|
||||||
guard let id = group.notificationIDs.first,
|
guard let id = group.notificationIDs.first,
|
||||||
let notification = MastodonCache.notification(for: id) else {
|
let notification = MastodonCache.notification(for: id) else {
|
||||||
fatalError("Missing cached status")
|
fatalError("Missing cached notification")
|
||||||
}
|
}
|
||||||
|
|
||||||
timestampLabel.text = notification.createdAt.timeAgoString()
|
timestampLabel.text = notification.createdAt.timeAgoString()
|
||||||
|
|
|
@ -14,10 +14,13 @@ class FollowNotificationGroupTableViewCell: UITableViewCell {
|
||||||
var delegate: TuskerNavigationDelegate?
|
var delegate: TuskerNavigationDelegate?
|
||||||
|
|
||||||
@IBOutlet weak var avatarStackView: UIStackView!
|
@IBOutlet weak var avatarStackView: UIStackView!
|
||||||
|
@IBOutlet weak var timestampLabel: UILabel!
|
||||||
@IBOutlet weak var actionLabel: UILabel!
|
@IBOutlet weak var actionLabel: UILabel!
|
||||||
|
|
||||||
var group: NotificationGroup!
|
var group: NotificationGroup!
|
||||||
|
|
||||||
|
var updateTimestampWorkItem: DispatchWorkItem?
|
||||||
|
|
||||||
override func awakeFromNib() {
|
override func awakeFromNib() {
|
||||||
super.awakeFromNib()
|
super.awakeFromNib()
|
||||||
|
|
||||||
|
@ -39,6 +42,7 @@ class FollowNotificationGroupTableViewCell: UITableViewCell {
|
||||||
let people = group.notificationIDs.compactMap(MastodonCache.notification(for:)).map { $0.account }
|
let people = group.notificationIDs.compactMap(MastodonCache.notification(for:)).map { $0.account }
|
||||||
|
|
||||||
updateActionLabel(people: people)
|
updateActionLabel(people: people)
|
||||||
|
updateTimestamp()
|
||||||
|
|
||||||
avatarStackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
|
avatarStackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
|
||||||
for account in people {
|
for account in people {
|
||||||
|
@ -63,7 +67,7 @@ class FollowNotificationGroupTableViewCell: UITableViewCell {
|
||||||
func updateActionLabel(people: [Account]) {
|
func updateActionLabel(people: [Account]) {
|
||||||
// todo: figure out how to localize this
|
// todo: figure out how to localize this
|
||||||
let peopleStr: String
|
let peopleStr: String
|
||||||
switch (people.count) {
|
switch people.count {
|
||||||
case 1:
|
case 1:
|
||||||
peopleStr = people.first!.realDisplayName
|
peopleStr = people.first!.realDisplayName
|
||||||
case 2:
|
case 2:
|
||||||
|
@ -75,4 +79,54 @@ class FollowNotificationGroupTableViewCell: UITableViewCell {
|
||||||
actionLabel.text = "Followed by \(peopleStr)"
|
actionLabel.text = "Followed by \(peopleStr)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateTimestamp() {
|
||||||
|
guard let id = group.notificationIDs.first,
|
||||||
|
let notification = MastodonCache.notification(for: id) else {
|
||||||
|
fatalError("Missing cached notification")
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
self.updateTimestamp()
|
||||||
|
}
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: updateTimestampWorkItem!)
|
||||||
|
} else {
|
||||||
|
updateTimestampWorkItem = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func prepareForReuse() {
|
||||||
|
super.prepareForReuse()
|
||||||
|
|
||||||
|
updateTimestampWorkItem?.cancel()
|
||||||
|
updateTimestampWorkItem = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
override func setSelected(_ selected: Bool, animated: Bool) {
|
||||||
|
super.setSelected(selected, animated: animated)
|
||||||
|
|
||||||
|
if selected {
|
||||||
|
let people = group.notificationIDs.compactMap(MastodonCache.notification(for:)).map { $0.account.id }
|
||||||
|
switch people.count {
|
||||||
|
case 0:
|
||||||
|
return
|
||||||
|
case 1:
|
||||||
|
delegate?.selected(account: people.first!)
|
||||||
|
default:
|
||||||
|
delegate?.showFollowedByList(accountIDs: people)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,17 +16,31 @@
|
||||||
<rect key="frame" x="0.0" y="0.0" width="320" height="98"/>
|
<rect key="frame" x="0.0" y="0.0" width="320" height="98"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="top" translatesAutoresizingMaskIntoConstraints="NO" id="g8L-M7-dD6">
|
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="g8L-M7-dD6">
|
||||||
<rect key="frame" x="74" y="11" width="230" height="76"/>
|
<rect key="frame" x="74" y="11" width="230" height="76"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<stackView opaque="NO" contentMode="scaleToFill" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="xyB-aZ-YhR">
|
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="7lu-x4-ldA">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="230" height="30"/>
|
<rect key="frame" x="0.0" y="0.0" width="230" height="30"/>
|
||||||
|
<subviews>
|
||||||
|
<stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="xyB-aZ-YhR">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="205.5" height="30"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" constant="30" id="3ns-8D-P1Q"/>
|
<constraint firstAttribute="height" constant="30" id="3ns-8D-P1Q"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</stackView>
|
</stackView>
|
||||||
|
<view contentMode="scaleToFill" horizontalHuggingPriority="249" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eEp-GR-rtF">
|
||||||
|
<rect key="frame" x="205.5" y="0.0" width="0.0" 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="Iub-HC-orP">
|
||||||
|
<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="Followed by Person 1 and Person 2" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bHA-9x-pcO">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Followed by Person 1 and Person 2" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bHA-9x-pcO">
|
||||||
<rect key="frame" x="0.0" y="30" width="198" height="46"/>
|
<rect key="frame" x="0.0" y="30" width="230" height="46"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
|
@ -54,6 +68,7 @@
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="actionLabel" destination="bHA-9x-pcO" id="Woa-25-hgd"/>
|
<outlet property="actionLabel" destination="bHA-9x-pcO" id="Woa-25-hgd"/>
|
||||||
<outlet property="avatarStackView" destination="xyB-aZ-YhR" id="DDp-5c-Qdo"/>
|
<outlet property="avatarStackView" destination="xyB-aZ-YhR" id="DDp-5c-Qdo"/>
|
||||||
|
<outlet property="timestampLabel" destination="Iub-HC-orP" id="OCV-mm-LXF"/>
|
||||||
</connections>
|
</connections>
|
||||||
<point key="canvasLocation" x="131.8840579710145" y="171.42857142857142"/>
|
<point key="canvasLocation" x="131.8840579710145" y="171.42857142857142"/>
|
||||||
</tableViewCell>
|
</tableViewCell>
|
||||||
|
|
Loading…
Reference in New Issue