Convert trending hashtags to collection view

This commit is contained in:
Shadowfacts 2022-06-29 17:54:37 -07:00
parent cc10a13785
commit b842389449
6 changed files with 189 additions and 192 deletions

View File

@ -19,8 +19,6 @@
04DACE8E212CC7CC009840C4 /* ImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04DACE8D212CC7CC009840C4 /* ImageCache.swift */; };
04ED00B121481ED800567C53 /* SteppedProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04ED00B021481ED800567C53 /* SteppedProgressView.swift */; };
D6093F9B25BDD4B9004811E6 /* HashtagSearchResultsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6093F9A25BDD4B9004811E6 /* HashtagSearchResultsViewController.swift */; };
D6093FB025BE0B01004811E6 /* TrendingHashtagTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6093FAE25BE0B01004811E6 /* TrendingHashtagTableViewCell.swift */; };
D6093FB125BE0B01004811E6 /* TrendingHashtagTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6093FAF25BE0B01004811E6 /* TrendingHashtagTableViewCell.xib */; };
D6093FB725BE0CF3004811E6 /* TrendHistoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6093FB625BE0CF3004811E6 /* TrendHistoryView.swift */; };
D60CFFDB24A290BA00D00083 /* SwiftSoup in Frameworks */ = {isa = PBXBuildFile; productRef = D60CFFDA24A290BA00D00083 /* SwiftSoup */; };
D60D2B8223844C71001B87A3 /* BaseStatusTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60D2B8123844C71001B87A3 /* BaseStatusTableViewCell.swift */; };
@ -293,6 +291,7 @@
D6E426AD25334DA500C02E1C /* FuzzyMatcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E426AC25334DA500C02E1C /* FuzzyMatcherTests.swift */; };
D6E426B325337C7000C02E1C /* CustomEmojiImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E426B225337C7000C02E1C /* CustomEmojiImageView.swift */; };
D6E57FA325C26FAB00341037 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = D6E57FA525C26FAB00341037 /* Localizable.stringsdict */; };
D6E77D09286D25FA00D8B732 /* TrendingHashtagCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E77D08286D25FA00D8B732 /* TrendingHashtagCollectionViewCell.swift */; };
D6E9CDA8281A427800BBC98E /* PostService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E9CDA7281A427800BBC98E /* PostService.swift */; };
D6EAE0DB2550CC8A002DB0AC /* FocusableTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6EAE0DA2550CC8A002DB0AC /* FocusableTextField.swift */; };
D6EBF01523C55C0900AE061B /* UIApplication+Scenes.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6EBF01423C55C0900AE061B /* UIApplication+Scenes.swift */; };
@ -367,8 +366,6 @@
04DACE8D212CC7CC009840C4 /* ImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCache.swift; sourceTree = "<group>"; };
04ED00B021481ED800567C53 /* SteppedProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SteppedProgressView.swift; sourceTree = "<group>"; };
D6093F9A25BDD4B9004811E6 /* HashtagSearchResultsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HashtagSearchResultsViewController.swift; sourceTree = "<group>"; };
D6093FAE25BE0B01004811E6 /* TrendingHashtagTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingHashtagTableViewCell.swift; sourceTree = "<group>"; };
D6093FAF25BE0B01004811E6 /* TrendingHashtagTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TrendingHashtagTableViewCell.xib; sourceTree = "<group>"; };
D6093FB625BE0CF3004811E6 /* TrendHistoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendHistoryView.swift; sourceTree = "<group>"; };
D60D2B8123844C71001B87A3 /* BaseStatusTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseStatusTableViewCell.swift; sourceTree = "<group>"; };
D60E2F232442372B005F8713 /* StatusMO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusMO.swift; sourceTree = "<group>"; };
@ -648,6 +645,7 @@
D6E426B225337C7000C02E1C /* CustomEmojiImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomEmojiImageView.swift; sourceTree = "<group>"; };
D6E4885C24A2890C0011C13E /* Tusker.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Tusker.entitlements; sourceTree = "<group>"; };
D6E57FA425C26FAB00341037 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
D6E77D08286D25FA00D8B732 /* TrendingHashtagCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingHashtagCollectionViewCell.swift; sourceTree = "<group>"; };
D6E9CDA7281A427800BBC98E /* PostService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostService.swift; sourceTree = "<group>"; };
D6EAE0DA2550CC8A002DB0AC /* FocusableTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FocusableTextField.swift; sourceTree = "<group>"; };
D6EBF01423C55C0900AE061B /* UIApplication+Scenes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIApplication+Scenes.swift"; sourceTree = "<group>"; };
@ -716,8 +714,7 @@
children = (
D611C2CD232DC61100C86A49 /* HashtagTableViewCell.swift */,
D611C2CE232DC61100C86A49 /* HashtagTableViewCell.xib */,
D6093FAE25BE0B01004811E6 /* TrendingHashtagTableViewCell.swift */,
D6093FAF25BE0B01004811E6 /* TrendingHashtagTableViewCell.xib */,
D6E77D08286D25FA00D8B732 /* TrendingHashtagCollectionViewCell.swift */,
);
path = "Hashtag Cell";
sourceTree = "<group>";
@ -1653,7 +1650,6 @@
D663625D2135C74800C9CBA2 /* ConversationMainStatusTableViewCell.xib in Resources */,
D640D76922BAF5E6004FBE69 /* DomainBlocks.plist in Resources */,
D6289E84217B795D0003D1D7 /* LargeImageViewController.xib in Resources */,
D6093FB125BE0B01004811E6 /* TrendingHashtagTableViewCell.xib in Resources */,
D627FF79217E950100CC0648 /* DraftsTableViewController.xib in Resources */,
D626493D23C1000300612E6E /* AlbumTableViewCell.xib in Resources */,
D627944723A6AC9300D38C68 /* BasicTableViewCell.xib in Resources */,
@ -1857,7 +1853,6 @@
D6EAE0DB2550CC8A002DB0AC /* FocusableTextField.swift in Sources */,
D623A53D2635F5590095BD04 /* StatusPollView.swift in Sources */,
D64AAE9726C88DC400FC57FB /* ToastConfiguration.swift in Sources */,
D6093FB025BE0B01004811E6 /* TrendingHashtagTableViewCell.swift in Sources */,
D63661C02381C144004B9E16 /* PreferencesNavigationController.swift in Sources */,
D6E9CDA8281A427800BBC98E /* PostService.swift in Sources */,
D6B053A223BD2C0600A066FA /* AssetPickerViewController.swift in Sources */,
@ -1972,6 +1967,7 @@
D6C99FCB24FADC91005C74D3 /* MainComposeTextView.swift in Sources */,
D6093F9B25BDD4B9004811E6 /* HashtagSearchResultsViewController.swift in Sources */,
D6E4267725327FB400C02E1C /* ComposeAutocompleteView.swift in Sources */,
D6E77D09286D25FA00D8B732 /* TrendingHashtagCollectionViewCell.swift in Sources */,
D6757A7E2157E02600721E32 /* XCBRequestSpec.swift in Sources */,
D677284E24ECC01D00C732D3 /* Draft.swift in Sources */,
D667E5F12134D5050057A976 /* UIViewController+Delegates.swift in Sources */,

View File

@ -9,19 +9,20 @@
import UIKit
import Pachyderm
class AddSavedHashtagViewController: EnhancedTableViewController {
class AddSavedHashtagViewController: UIViewController {
weak var mastodonController: MastodonController!
var resultsController: SearchResultsViewController!
var searchController: UISearchController!
var dataSource: UITableViewDiffableDataSource<Section, Item>!
private var collectionView: UICollectionView!
private var dataSource: UICollectionViewDiffableDataSource<Section, Item>!
init(mastodonController: MastodonController) {
self.mastodonController = mastodonController
super.init(style: .grouped)
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
@ -33,18 +34,38 @@ class AddSavedHashtagViewController: EnhancedTableViewController {
title = NSLocalizedString("Search", comment: "search screen title")
tableView.register(UINib(nibName: "TrendingHashtagTableViewCell", bundle: .main), forCellReuseIdentifier: "trendingTagCell")
tableView.rowHeight = 60 // 44 for content + 2 * 8 spacing
dataSource = DataSource(tableView: tableView, cellProvider: { (tableView, indexPath, item) -> UITableViewCell? in
view.backgroundColor = .systemGroupedBackground
var config = UICollectionLayoutListConfiguration(appearance: .grouped)
config.headerMode = .supplementary
let layout = UICollectionViewCompositionalLayout.list(using: config)
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
collectionView.delegate = self
view.addSubview(collectionView)
let sectionHeaderCell = UICollectionView.SupplementaryRegistration<UICollectionViewListCell>(elementKind: UICollectionView.elementKindSectionHeader) { (headerView, collectionView, indexPath) in
var config = headerView.defaultContentConfiguration()
config.text = NSLocalizedString("Trending Hashtags", comment: "trending hashtags section title")
headerView.contentConfiguration = config
}
let registration = UICollectionView.CellRegistration<TrendingHashtagCollectionViewCell, Hashtag> { cell, indexPath, hashtag in
cell.updateUI(hashtag: hashtag)
}
dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) { (collectionView, indexPath, item) in
switch item {
case let .tag(hashtag):
let cell = tableView.dequeueReusableCell(withIdentifier: "trendingTagCell", for: indexPath) as! TrendingHashtagTableViewCell
cell.updateUI(hashtag: hashtag)
return cell
return collectionView.dequeueConfiguredReusableCell(using: registration, for: indexPath, item: hashtag)
}
})
}
dataSource.supplementaryViewProvider = { (collectionView, elementKind, indexPath) in
if elementKind == UICollectionView.elementKindSectionHeader {
return collectionView.dequeueConfiguredReusableSupplementary(using: sectionHeaderCell, for: indexPath)
} else {
return nil
}
}
resultsController = HashtagSearchResultsViewController(mastodonController: mastodonController)
resultsController.delegate = self
resultsController.exploreNavigationController = self.navigationController!
@ -92,17 +113,6 @@ class AddSavedHashtagViewController: EnhancedTableViewController {
presentingViewController!.dismiss(animated: true)
}
// MARK: - Table View Delegate
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
switch dataSource.itemIdentifier(for: indexPath) {
case nil:
return
case let .tag(hashtag):
selectHashtag(hashtag)
}
}
// MARK: - Interaction
@objc func cancelButtonPressed() {
@ -115,14 +125,23 @@ extension AddSavedHashtagViewController {
enum Section {
case trendingTags
}
enum Item: Hashable {
case tag(Hashtag)
}
class DataSource: UITableViewDiffableDataSource<Section, Item> {
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return NSLocalizedString("Trending Hashtags", comment: "trending hashtags seciton title")
// class DataSource: UITableViewDiffableDataSource<Section, Item> {
// override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
// return
// }
// }
}
extension AddSavedHashtagViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
switch dataSource.itemIdentifier(for: indexPath) {
case nil:
return
case let .tag(hashtag):
selectHashtag(hashtag)
}
}
}

View File

@ -9,18 +9,17 @@
import UIKit
import Pachyderm
class TrendingHashtagsViewController: EnhancedTableViewController {
class TrendingHashtagsViewController: UIViewController {
weak var mastodonController: MastodonController!
private var dataSource: UITableViewDiffableDataSource<Section, Item>!
private var collectionView: UICollectionView!
private var dataSource: UICollectionViewDiffableDataSource<Section, Item>!
init(mastodonController: MastodonController) {
self.mastodonController = mastodonController
super.init(style: .grouped)
dragEnabled = true
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
@ -32,15 +31,24 @@ class TrendingHashtagsViewController: EnhancedTableViewController {
title = NSLocalizedString("Trending Hashtags", comment: "trending hashtags screen title")
tableView.register(UINib(nibName: "TrendingHashtagTableViewCell", bundle: .main), forCellReuseIdentifier: "trendingTagCell")
tableView.rowHeight = 60 // 44 for content + 2 * 8 spacing
view.backgroundColor = .systemGroupedBackground
dataSource = UITableViewDiffableDataSource<Section, Item>(tableView: tableView) { (tableView, indexPath, item) in
let config = UICollectionLayoutListConfiguration(appearance: .grouped)
let layout = UICollectionViewCompositionalLayout.list(using: config)
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
collectionView.delegate = self
collectionView.dragDelegate = self
view.addSubview(collectionView)
let registration = UICollectionView.CellRegistration<TrendingHashtagCollectionViewCell, Hashtag> { cell, indexPath, hashtag in
cell.updateUI(hashtag: hashtag)
}
dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView) { (collectionView, indexPath, item) in
switch item {
case let .tag(hashtag):
let cell = tableView.dequeueReusableCell(withIdentifier: "trendingTagCell", for: indexPath) as! TrendingHashtagTableViewCell
cell.updateUI(hashtag: hashtag)
return cell
return collectionView.dequeueConfiguredReusableCell(using: registration, for: indexPath, item: hashtag)
}
}
}
@ -56,45 +64,9 @@ class TrendingHashtagsViewController: EnhancedTableViewController {
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.trendingTags])
snapshot.appendItems(hashtags.map { .tag($0) })
await dataSource.apply(snapshot)
dataSource.apply(snapshot)
}
}
// MARK: - Table View Delegate
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let item = dataSource.itemIdentifier(for: indexPath),
case let .tag(hashtag) = item else {
return
}
show(HashtagTimelineViewController(for: hashtag, mastodonController: mastodonController), sender: nil)
}
override func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
guard let item = dataSource.itemIdentifier(for: indexPath),
case let .tag(hashtag) = item else {
return nil
}
return UIContextMenuConfiguration(identifier: nil) {
HashtagTimelineViewController(for: hashtag, mastodonController: self.mastodonController)
} actionProvider: { (_) in
UIMenu(children: self.actionsForHashtag(hashtag, sourceView: self.tableView.cellForRow(at: indexPath)))
}
}
override func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
guard let item = dataSource.itemIdentifier(for: indexPath),
case let .tag(hashtag) = item else {
return []
}
let provider = NSItemProvider(object: hashtag.url as NSURL)
if let activity = UserActivityManager.showTimelineActivity(timeline: .tag(hashtag: hashtag.name), accountID: mastodonController.accountInfo!.id) {
activity.displaysAuxiliaryScene = true
provider.registerObject(activity, visibility: .all)
}
return [UIDragItem(itemProvider: provider)]
}
}
@ -107,6 +79,44 @@ extension TrendingHashtagsViewController {
}
}
extension TrendingHashtagsViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let item = dataSource.itemIdentifier(for: indexPath),
case let .tag(hashtag) = item else {
return
}
show(HashtagTimelineViewController(for: hashtag, mastodonController: mastodonController), sender: nil)
}
func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
guard let item = dataSource.itemIdentifier(for: indexPath),
case let .tag(hashtag) = item else {
return nil
}
return UIContextMenuConfiguration(identifier: nil) {
HashtagTimelineViewController(for: hashtag, mastodonController: self.mastodonController)
} actionProvider: { (_) in
UIMenu(children: self.actionsForHashtag(hashtag, sourceView: self.collectionView.cellForItem(at: indexPath)))
}
}
}
extension TrendingHashtagsViewController: UICollectionViewDragDelegate {
func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
guard let item = dataSource.itemIdentifier(for: indexPath),
case let .tag(hashtag) = item else {
return []
}
let provider = NSItemProvider(object: hashtag.url as NSURL)
if let activity = UserActivityManager.showTimelineActivity(timeline: .tag(hashtag: hashtag.name), accountID: mastodonController.accountInfo!.id) {
activity.displaysAuxiliaryScene = true
provider.registerObject(activity, visibility: .all)
}
return [UIDragItem(itemProvider: provider)]
}
}
extension TrendingHashtagsViewController: TuskerNavigationDelegate {
var apiController: MastodonController { mastodonController }
}

View File

@ -0,0 +1,80 @@
//
// TrendingHashtagCollectionViewCell.swift
// Tusker
//
// Created by Shadowfacts on 6/29/22.
// Copyright © 2022 Shadowfacts. All rights reserved.
//
import UIKit
import Pachyderm
class TrendingHashtagCollectionViewCell: UICollectionViewCell {
private let hashtagLabel = UILabel()
private let peopleTodayLabel = UILabel()
private let historyView = TrendHistoryView()
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .systemBackground
hashtagLabel.font = .preferredFont(forTextStyle: .title2)
peopleTodayLabel.font = .preferredFont(forTextStyle: .caption1)
let vStack = UIStackView(arrangedSubviews: [
hashtagLabel,
peopleTodayLabel,
])
vStack.axis = .vertical
vStack.alignment = .fill
vStack.distribution = .fill
vStack.spacing = 0
let hStack = UIStackView(arrangedSubviews: [
vStack,
historyView,
])
hStack.axis = .horizontal
hStack.alignment = .center
hStack.distribution = .fill
hStack.spacing = 8
hStack.translatesAutoresizingMaskIntoConstraints = false
addSubview(hStack)
NSLayoutConstraint.activate([
hStack.leadingAnchor.constraint(equalToSystemSpacingAfter: leadingAnchor, multiplier: 1),
trailingAnchor.constraint(equalToSystemSpacingAfter: hStack.trailingAnchor, multiplier: 1),
hStack.topAnchor.constraint(equalTo: topAnchor, constant: 8),
hStack.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8),
historyView.widthAnchor.constraint(equalToConstant: 100),
historyView.heightAnchor.constraint(equalToConstant: 44),
])
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func updateUI(hashtag: Hashtag) {
hashtagLabel.text = "#\(hashtag.name)"
historyView.setHistory(hashtag.history)
historyView.isHidden = hashtag.history == nil || hashtag.history!.count < 2
if let history = hashtag.history {
let sorted = history.sorted(by: { $0.day < $1.day })
let lastTwo = sorted[(sorted.count - 2)...]
let accounts = lastTwo.map(\.accounts).reduce(0, +)
let uses = lastTwo.map(\.uses).reduce(0, +)
let format = NSLocalizedString("trending hashtag info", comment: "trending hashtag posts and people")
peopleTodayLabel.text = String.localizedStringWithFormat(format, accounts, uses)
peopleTodayLabel.isHidden = false
} else {
peopleTodayLabel.isHidden = true
}
}
}

View File

@ -1,41 +0,0 @@
//
// TrendingHashtagTableViewCell.swift
// Tusker
//
// Created by Shadowfacts on 1/24/21.
// Copyright © 2021 Shadowfacts. All rights reserved.
//
import UIKit
import Pachyderm
class TrendingHashtagTableViewCell: UITableViewCell {
@IBOutlet weak var hashtagLabel: UILabel!
@IBOutlet weak var peopleTodayLabel: UILabel!
@IBOutlet weak var historyView: TrendHistoryView!
override func awakeFromNib() {
super.awakeFromNib()
}
func updateUI(hashtag: Hashtag) {
hashtagLabel.text = "#\(hashtag.name)"
historyView.setHistory(hashtag.history)
historyView.isHidden = hashtag.history == nil || hashtag.history!.count < 2
if let history = hashtag.history {
let sorted = history.sorted(by: { $0.day < $1.day })
let lastTwo = sorted[(sorted.count - 2)...]
let accounts = lastTwo.map(\.accounts).reduce(0, +)
let uses = lastTwo.map(\.uses).reduce(0, +)
let format = NSLocalizedString("trending hashtag info", comment: "trending hashtag posts and people")
peopleTodayLabel.text = String.localizedStringWithFormat(format, accounts, uses)
peopleTodayLabel.isHidden = false
} else {
peopleTodayLabel.isHidden = true
}
}
}

View File

@ -1,67 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<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" id="KGk-i7-Jjw" customClass="TrendingHashtagTableViewCell" 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>
<stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="tEP-en-vHK">
<rect key="frame" x="16" y="0.0" width="288" height="66"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="iCc-do-llt">
<rect key="frame" x="0.0" y="15" width="180" height="36.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="#hashtag" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SIS-9e-Paj">
<rect key="frame" x="0.0" y="0.0" width="180" height="23"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle2"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="6 people today" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Kc5-BL-bmu">
<rect key="frame" x="0.0" y="23" width="180" height="13.5"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Xrw-2v-ybZ" customClass="TrendHistoryView" customModule="Tusker" customModuleProvider="target">
<rect key="frame" x="188" y="11" width="100" height="44"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="W4C-uw-zWg"/>
<constraint firstAttribute="width" constant="100" id="XHb-vd-qNk"/>
</constraints>
</view>
</subviews>
</stackView>
</subviews>
<constraints>
<constraint firstItem="tEP-en-vHK" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" id="3Qd-rF-nGk"/>
<constraint firstAttribute="trailingMargin" secondItem="tEP-en-vHK" secondAttribute="trailing" id="Ws6-oZ-9Es"/>
<constraint firstItem="tEP-en-vHK" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" id="if4-Ea-awg"/>
<constraint firstAttribute="bottom" secondItem="tEP-en-vHK" secondAttribute="bottom" id="nTV-Ih-vTj"/>
</constraints>
</tableViewCellContentView>
<viewLayoutGuide key="safeArea" id="njF-e1-oar"/>
<connections>
<outlet property="hashtagLabel" destination="SIS-9e-Paj" id="1UK-Va-3rL"/>
<outlet property="historyView" destination="Xrw-2v-ybZ" id="OIh-K9-gSk"/>
<outlet property="peopleTodayLabel" destination="Kc5-BL-bmu" id="5L8-aO-zt4"/>
</connections>
<point key="canvasLocation" x="132" y="132"/>
</tableViewCell>
</objects>
</document>