2019-12-17 05:22:25 +00:00
//
// E x p l o r e V i e w C o n t r o l l e r . s w i f t
// T u s k e r
//
// C r e a t e d b y S h a d o w f a c t s o n 1 2 / 1 4 / 1 9 .
// C o p y r i g h t © 2 0 1 9 S h a d o w f a c t s . A l l r i g h t s r e s e r v e d .
//
import UIKit
import Combine
2019-12-17 23:48:29 +00:00
import Pachyderm
2019-12-17 05:22:25 +00:00
2021-02-06 18:48:31 +00:00
class ExploreViewController : UIViewController , UICollectionViewDelegate {
2019-12-17 05:22:25 +00:00
2020-05-13 22:57:04 +00:00
weak var mastodonController : MastodonController !
2020-01-05 20:25:07 +00:00
2021-02-06 18:48:31 +00:00
private var collectionView : UICollectionView !
private var dataSource : UICollectionViewDiffableDataSource < Section , Item > !
2019-12-17 05:22:25 +00:00
2021-02-06 18:48:31 +00:00
private ( set ) var resultsController : SearchResultsViewController !
private ( set ) var searchController : UISearchController !
2019-12-17 05:22:25 +00:00
2020-06-30 02:21:03 +00:00
var searchControllerStatusOnAppearance : Bool ? = nil
2020-01-05 20:25:07 +00:00
init ( mastodonController : MastodonController ) {
self . mastodonController = mastodonController
2021-02-06 18:48:31 +00:00
super . init ( nibName : nil , bundle : nil )
2020-12-14 23:44:41 +00:00
2019-12-17 05:22:25 +00:00
title = NSLocalizedString ( " Explore " , comment : " explore tab title " )
tabBarItem . image = UIImage ( systemName : " magnifyingglass " )
}
required init ? ( coder : NSCoder ) {
fatalError ( " init(coder:) has not been implemented " )
}
override func viewDidLoad ( ) {
super . viewDidLoad ( )
2019-12-18 02:18:32 +00:00
2021-02-06 18:48:31 +00:00
var configuration = UICollectionLayoutListConfiguration ( appearance : . insetGrouped )
configuration . trailingSwipeActionsConfigurationProvider = self . trailingSwipeActionsForCell ( at : )
configuration . headerMode = . supplementary
let layout = UICollectionViewCompositionalLayout . list ( using : configuration )
collectionView = UICollectionView ( frame : view . bounds , collectionViewLayout : layout )
collectionView . autoresizingMask = [ . flexibleWidth , . flexibleHeight ]
collectionView . delegate = self
collectionView . dragDelegate = self
view . addSubview ( collectionView )
2019-12-17 05:22:25 +00:00
2021-02-06 18:48:31 +00:00
dataSource = createDataSource ( )
applyInitialSnapshot ( )
2020-01-20 16:48:47 +00:00
2021-02-08 00:52:59 +00:00
if mastodonController . instance = = nil {
mastodonController . getOwnInstance ( completion : self . ownInstanceLoaded ( _ : ) )
}
2020-01-05 20:25:07 +00:00
resultsController = SearchResultsViewController ( mastodonController : mastodonController )
2019-12-17 05:22:25 +00:00
resultsController . exploreNavigationController = self . navigationController !
searchController = UISearchController ( searchResultsController : resultsController )
searchController . searchResultsUpdater = resultsController
searchController . searchBar . autocapitalizationType = . none
searchController . searchBar . delegate = resultsController
definesPresentationContext = true
navigationItem . searchController = searchController
navigationItem . hidesSearchBarWhenScrolling = false
2019-12-17 23:48:29 +00:00
2019-12-20 02:20:29 +00:00
NotificationCenter . default . addObserver ( self , selector : #selector ( savedHashtagsChanged ) , name : . savedHashtagsChanged , object : nil )
2019-12-20 03:41:23 +00:00
NotificationCenter . default . addObserver ( self , selector : #selector ( savedInstancesChanged ) , name : . savedInstancesChanged , object : nil )
2022-04-01 23:23:49 +00:00
NotificationCenter . default . addObserver ( self , selector : #selector ( preferencesChanged ) , name : . preferencesChanged , object : nil )
2021-02-06 18:48:31 +00:00
}
override func viewWillAppear ( _ animated : Bool ) {
super . viewWillAppear ( animated )
2019-12-20 02:20:29 +00:00
2021-02-06 18:48:31 +00:00
// C a n ' t u s e U I C o l l e c t i o n V i e w C o n t r o l l e r ' s b u i l t i n v e r s i o n o f t h i s b e c a u s e i t r e q u i r e s
// t h e c o l l e c t i o n v i e w l a y o u t b e p a s s e d i n t o t h e c o n s t r u c t o r . S w i p e a c t i o n s f o r l i s t c o l l e c t i o n v i e w s
// a r e c r e a t e d b y p a s s i n g a c l o s u r e t o t h e l a y o u t ' s c o n f i g u r a t i o n . T h i s c l o s u r e n e e d s t o c a p t u r e
// ` s e l f ` , s o i t c a n ' t b e p a s s e d i n t o t h e s u p e r c o n s t r u c t o r .
if let indexPaths = collectionView . indexPathsForSelectedItems {
for indexPath in indexPaths {
collectionView . deselectItem ( at : indexPath , animated : true )
}
}
2019-12-18 02:18:32 +00:00
}
2020-06-30 02:21:03 +00:00
override func viewDidAppear ( _ animated : Bool ) {
super . viewDidAppear ( animated )
// t h i s i s a w o r k a r o u n d f o r t h e i s s u e t h a t s e t t i n g i s A c t i v e o n a s e a r c h c o n t r o l l e r t h a t i s n o t v i s i b l e
// d o e s n o t c a u s e i t t o a u t o m a t i c a l l y b e c o m e a c t i v e o n c e i t b e c o m e s v i s i b l e
// s e e F B 7 8 1 4 5 6 1
if let active = searchControllerStatusOnAppearance {
searchController . isActive = active
searchControllerStatusOnAppearance = nil
}
}
2021-02-06 18:48:31 +00:00
private func createDataSource ( ) -> UICollectionViewDiffableDataSource < Section , Item > {
let sectionHeaderCell = UICollectionView . SupplementaryRegistration < UICollectionViewListCell > ( elementKind : UICollectionView . elementKindSectionHeader ) { ( headerView , collectionView , indexPath ) in
let section = self . dataSource . snapshot ( ) . sectionIdentifiers [ indexPath . section ]
var config = headerView . defaultContentConfiguration ( )
config . text = section . label
headerView . contentConfiguration = config
}
let listCell = UICollectionView . CellRegistration < UICollectionViewListCell , Item > { ( cell , indexPath , item ) in
var config = cell . defaultContentConfiguration ( )
config . text = item . label
config . image = item . image
cell . contentConfiguration = config
switch item {
case . addList , . addSavedHashtag , . findInstance :
cell . accessories = [ ]
default :
cell . accessories = [ . disclosureIndicator ( ) ]
}
}
let dataSource = UICollectionViewDiffableDataSource < Section , Item > ( collectionView : collectionView ) { ( collectionView , indexPath , item ) in
return collectionView . dequeueConfiguredReusableCell ( using : listCell , for : indexPath , item : item )
}
dataSource . supplementaryViewProvider = { ( collectionView , elementKind , indexPath ) in
if elementKind = = UICollectionView . elementKindSectionHeader {
return collectionView . dequeueConfiguredReusableSupplementary ( using : sectionHeaderCell , for : indexPath )
} else {
return nil
}
}
return dataSource
}
private func applyInitialSnapshot ( ) {
let account = mastodonController . accountInfo !
var snapshot = NSDiffableDataSourceSnapshot < Section , Item > ( )
2021-02-08 00:52:59 +00:00
snapshot . appendSections ( Section . allCases . filter { $0 != . discover } )
2021-02-06 18:48:31 +00:00
snapshot . appendItems ( [ . bookmarks ] , toSection : . bookmarks )
2022-04-01 23:23:49 +00:00
if mastodonController . instanceFeatures . instanceType . isMastodon ,
! Preferences . shared . hideDiscover {
addDiscoverSection ( to : & snapshot )
2021-02-08 00:52:59 +00:00
}
2021-02-06 18:48:31 +00:00
snapshot . appendItems ( [ . addList ] , toSection : . lists )
snapshot . appendItems ( SavedDataManager . shared . sortedHashtags ( for : account ) . map { . savedHashtag ( $0 ) } , toSection : . savedHashtags )
snapshot . appendItems ( [ . addSavedHashtag ] , toSection : . savedHashtags )
snapshot . appendItems ( SavedDataManager . shared . savedInstances ( for : account ) . map { . savedInstance ( $0 ) } , toSection : . savedInstances )
snapshot . appendItems ( [ . findInstance ] , toSection : . savedInstances )
dataSource . apply ( snapshot , animatingDifferences : false )
reloadLists ( )
}
2022-04-01 23:23:49 +00:00
private func addDiscoverSection ( to snapshot : inout NSDiffableDataSourceSnapshot < Section , Item > ) {
snapshot . insertSections ( [ . discover ] , afterSection : . bookmarks )
2022-04-02 14:39:03 +00:00
// t o d o : c h e c k v e r s i o n
snapshot . appendItems ( [ . trendingStatuses , . trendingTags , . profileDirectory ] , toSection : . discover )
2022-04-01 23:23:49 +00:00
}
2021-02-08 00:52:59 +00:00
private func ownInstanceLoaded ( _ instance : Instance ) {
var snapshot = self . dataSource . snapshot ( )
2022-01-26 02:01:36 +00:00
if mastodonController . instanceFeatures . instanceType . isMastodon ,
! snapshot . sectionIdentifiers . contains ( . discover ) {
2021-02-08 00:52:59 +00:00
snapshot . insertSections ( [ . discover ] , afterSection : . bookmarks )
snapshot . appendItems ( [ . trendingTags , . profileDirectory ] , toSection : . discover )
}
self . dataSource . apply ( snapshot )
}
2021-02-06 18:48:31 +00:00
private func reloadLists ( ) {
2020-01-05 19:00:39 +00:00
let request = Client . getLists ( )
2020-01-05 20:25:07 +00:00
mastodonController . run ( request ) { ( response ) in
2019-12-17 23:48:29 +00:00
guard case let . success ( lists , _ ) = response else {
2021-02-06 18:48:31 +00:00
return
2019-12-17 23:48:29 +00:00
}
var snapshot = self . dataSource . snapshot ( )
2019-12-20 02:20:29 +00:00
snapshot . deleteItems ( snapshot . itemIdentifiers ( inSection : . lists ) )
2021-02-06 18:48:31 +00:00
snapshot . appendItems ( lists . map { . list ( $0 ) } , toSection : . lists )
snapshot . appendItems ( [ . addList ] , toSection : . lists )
2019-12-17 23:48:29 +00:00
DispatchQueue . main . async {
self . dataSource . apply ( snapshot )
}
}
2019-12-17 05:22:25 +00:00
}
2019-12-17 23:48:29 +00:00
2021-02-06 18:48:31 +00:00
@objc private func savedHashtagsChanged ( ) {
2020-01-20 16:48:47 +00:00
let account = mastodonController . accountInfo !
2019-12-20 02:20:29 +00:00
var snapshot = dataSource . snapshot ( )
snapshot . deleteItems ( snapshot . itemIdentifiers ( inSection : . savedHashtags ) )
2021-02-06 18:48:31 +00:00
snapshot . appendItems ( SavedDataManager . shared . sortedHashtags ( for : account ) . map { . savedHashtag ( $0 ) } , toSection : . savedHashtags )
snapshot . appendItems ( [ . addSavedHashtag ] , toSection : . savedHashtags )
2019-12-20 02:20:29 +00:00
dataSource . apply ( snapshot )
}
2021-02-06 18:48:31 +00:00
@objc private func savedInstancesChanged ( ) {
2020-01-20 16:48:47 +00:00
let account = mastodonController . accountInfo !
2019-12-20 03:41:23 +00:00
var snapshot = dataSource . snapshot ( )
snapshot . deleteItems ( snapshot . itemIdentifiers ( inSection : . savedInstances ) )
2021-02-06 18:48:31 +00:00
snapshot . appendItems ( SavedDataManager . shared . savedInstances ( for : account ) . map { . savedInstance ( $0 ) } , toSection : . savedInstances )
snapshot . appendItems ( [ . findInstance ] , toSection : . savedInstances )
2019-12-20 03:41:23 +00:00
dataSource . apply ( snapshot )
}
2022-04-01 23:23:49 +00:00
@objc private func preferencesChanged ( ) {
var snapshot = dataSource . snapshot ( )
let hasSection = snapshot . sectionIdentifiers . contains ( . discover )
let hide = Preferences . shared . hideDiscover
if hasSection && hide {
snapshot . deleteSections ( [ . discover ] )
} else if ! hasSection && ! hide {
addDiscoverSection ( to : & snapshot )
} else {
return
}
dataSource . apply ( snapshot )
}
2021-02-06 18:48:31 +00:00
private func deleteList ( _ list : List , completion : @ escaping ( Bool ) -> Void ) {
let titleFormat = NSLocalizedString ( " Are you sure you want to delete the '%@' list? " , comment : " delete list alert title " )
let title = String ( format : titleFormat , list . title )
2019-12-20 02:20:29 +00:00
let alert = UIAlertController ( title : title , message : nil , preferredStyle : . alert )
2021-02-06 18:48:31 +00:00
alert . addAction ( UIAlertAction ( title : NSLocalizedString ( " Cancel " , comment : " delete list alert cancel button " ) , style : . cancel , handler : { ( _ ) in
completion ( false )
} ) )
2019-12-20 02:20:29 +00:00
alert . addAction ( UIAlertAction ( title : NSLocalizedString ( " Delete List " , comment : " delete list alert confirm button " ) , style : . destructive , handler : { ( _ ) in
let request = List . delete ( list )
2020-01-05 20:25:07 +00:00
self . mastodonController . run ( request ) { ( response ) in
2019-12-20 02:20:29 +00:00
guard case . success ( _ , _ ) = response else {
fatalError ( )
}
var snapshot = self . dataSource . snapshot ( )
snapshot . deleteItems ( [ . list ( list ) ] )
DispatchQueue . main . async {
self . dataSource . apply ( snapshot )
2021-02-06 18:48:31 +00:00
completion ( true )
2019-12-20 02:20:29 +00:00
}
}
} ) )
present ( alert , animated : true )
}
func removeSavedHashtag ( _ hashtag : Hashtag ) {
2020-01-20 16:48:47 +00:00
let account = mastodonController . accountInfo !
SavedDataManager . shared . remove ( hashtag : hashtag , for : account )
2019-12-20 02:20:29 +00:00
}
2019-12-20 03:41:23 +00:00
func removeSavedInstance ( _ instanceURL : URL ) {
2020-01-20 16:48:47 +00:00
let account = mastodonController . accountInfo !
SavedDataManager . shared . remove ( instance : instanceURL , for : account )
2019-12-20 03:41:23 +00:00
}
2021-02-06 18:48:31 +00:00
private func trailingSwipeActionsForCell ( at indexPath : IndexPath ) -> UISwipeActionsConfiguration ? {
let handler : UIContextualAction . Handler
switch dataSource . itemIdentifier ( for : indexPath ) {
case let . list ( list ) :
handler = { ( _ , _ , completion ) in
self . deleteList ( list , completion : completion )
}
case let . savedHashtag ( hashtag ) :
handler = { ( _ , _ , completion ) in
self . removeSavedHashtag ( hashtag )
completion ( true )
}
case let . savedInstance ( url ) :
handler = { ( _ , _ , completion ) in
self . removeSavedInstance ( url )
completion ( true )
}
default :
return nil
}
return UISwipeActionsConfiguration ( actions : [
UIContextualAction ( style : . destructive , title : NSLocalizedString ( " Delete " , comment : " delete swipe action title " ) , handler : handler )
] )
}
// MARK: - C o l l e c t i o n V i e w D e l e g a t e
2019-12-17 05:22:25 +00:00
2021-02-06 18:48:31 +00:00
func collectionView ( _ collectionView : UICollectionView , didSelectItemAt indexPath : IndexPath ) {
2019-12-17 05:22:25 +00:00
switch dataSource . itemIdentifier ( for : indexPath ) {
case nil :
return
case . bookmarks :
2020-01-05 20:25:07 +00:00
show ( BookmarksTableViewController ( mastodonController : mastodonController ) , sender : nil )
2019-12-17 05:22:25 +00:00
2022-04-02 14:39:03 +00:00
case . trendingStatuses :
show ( TrendingStatusesViewController ( mastodonController : mastodonController ) , sender : nil )
2021-02-06 19:54:35 +00:00
case . trendingTags :
show ( TrendingHashtagsViewController ( mastodonController : mastodonController ) , sender : nil )
2021-02-08 00:39:22 +00:00
case . profileDirectory :
show ( ProfileDirectoryViewController ( mastodonController : mastodonController ) , sender : nil )
2019-12-17 23:48:29 +00:00
case let . list ( list ) :
2020-01-05 20:25:07 +00:00
show ( ListTimelineViewController ( for : list , mastodonController : mastodonController ) , sender : nil )
2019-12-18 02:18:32 +00:00
case . addList :
2021-02-06 18:48:31 +00:00
collectionView . deselectItem ( at : indexPath , animated : true )
2019-12-18 02:18:32 +00:00
let alert = UIAlertController ( title : NSLocalizedString ( " New List " , comment : " new list alert title " ) , message : NSLocalizedString ( " Choose a title for your new list " , comment : " new list alert message " ) , preferredStyle : . alert )
alert . addTextField ( configurationHandler : nil )
alert . addAction ( UIAlertAction ( title : NSLocalizedString ( " Cancel " , comment : " new list alert cancel button " ) , style : . cancel , handler : nil ) )
alert . addAction ( UIAlertAction ( title : NSLocalizedString ( " Create List " , comment : " new list create button " ) , style : . default , handler : { ( _ ) in
guard let title = alert . textFields ? . first ? . text else {
fatalError ( )
}
2020-01-05 19:00:39 +00:00
let request = Client . createList ( title : title )
2020-01-05 20:25:07 +00:00
self . mastodonController . run ( request ) { ( response ) in
2019-12-18 02:18:32 +00:00
guard case let . success ( list , _ ) = response else { fatalError ( ) }
self . reloadLists ( )
DispatchQueue . main . async {
2020-01-05 20:25:07 +00:00
let listTimelineController = ListTimelineViewController ( for : list , mastodonController : self . mastodonController )
2019-12-20 02:37:47 +00:00
listTimelineController . presentEditOnAppear = true
self . show ( listTimelineController , sender : nil )
2019-12-18 02:18:32 +00:00
}
}
} ) )
present ( alert , animated : true )
2019-12-20 02:20:29 +00:00
case let . savedHashtag ( hashtag ) :
2020-01-05 20:25:07 +00:00
show ( HashtagTimelineViewController ( for : hashtag , mastodonController : mastodonController ) , sender : nil )
2019-12-20 02:20:29 +00:00
case . addSavedHashtag :
2021-02-06 18:48:31 +00:00
collectionView . deselectItem ( at : indexPath , animated : true )
2020-01-05 20:25:07 +00:00
let navController = UINavigationController ( rootViewController : AddSavedHashtagViewController ( mastodonController : mastodonController ) )
2019-12-20 02:20:29 +00:00
present ( navController , animated : true )
2019-12-20 03:41:23 +00:00
case let . savedInstance ( url ) :
2020-01-20 16:48:47 +00:00
show ( InstanceTimelineViewController ( for : url , parentMastodonController : mastodonController ) , sender : nil )
2019-12-20 03:41:23 +00:00
case . findInstance :
2021-02-06 18:48:31 +00:00
collectionView . deselectItem ( at : indexPath , animated : true )
2020-01-20 16:48:47 +00:00
let findController = FindInstanceViewController ( parentMastodonController : mastodonController )
2019-12-20 03:41:23 +00:00
findController . instanceTimelineDelegate = self
let navController = UINavigationController ( rootViewController : findController )
present ( navController , animated : true )
2019-12-17 05:22:25 +00:00
}
}
2020-03-16 03:54:04 +00:00
2019-12-17 05:22:25 +00:00
}
extension ExploreViewController {
enum Section : CaseIterable {
case bookmarks
2021-02-06 19:54:35 +00:00
case discover
2019-12-17 05:22:25 +00:00
case lists
2019-12-20 02:20:29 +00:00
case savedHashtags
2019-12-20 03:41:23 +00:00
case savedInstances
2021-02-06 18:48:31 +00:00
var label : String ? {
switch self {
case . bookmarks :
return nil
2021-02-06 19:54:35 +00:00
case . discover :
return NSLocalizedString ( " Discover " , comment : " discover section title " )
2021-02-06 18:48:31 +00:00
case . lists :
return NSLocalizedString ( " Lists " , comment : " explore lists section title " )
case . savedHashtags :
return NSLocalizedString ( " Saved Hashtags " , comment : " explore saved hashtags section title " )
case . savedInstances :
return NSLocalizedString ( " Instance Timelines " , comment : " explore instance timelines section title " )
}
}
2019-12-17 05:22:25 +00:00
}
2021-02-06 18:48:31 +00:00
2019-12-17 05:22:25 +00:00
enum Item : Hashable {
case bookmarks
2022-04-02 14:39:03 +00:00
case trendingStatuses
2021-02-06 19:54:35 +00:00
case trendingTags
2021-02-08 00:39:22 +00:00
case profileDirectory
2019-12-17 23:48:29 +00:00
case list ( List )
2019-12-18 02:18:32 +00:00
case addList
2019-12-20 02:20:29 +00:00
case savedHashtag ( Hashtag )
case addSavedHashtag
2019-12-20 03:41:23 +00:00
case savedInstance ( URL )
case findInstance
2021-02-06 18:48:31 +00:00
var label : String {
switch self {
case . bookmarks :
return NSLocalizedString ( " Bookmarks " , comment : " bookmarks nav item title " )
2022-04-02 14:39:03 +00:00
case . trendingStatuses :
return NSLocalizedString ( " Trending Posts " , comment : " trending statuses nav item title " )
2021-02-06 19:54:35 +00:00
case . trendingTags :
return NSLocalizedString ( " Trending Hashtags " , comment : " trending hashtags nav item title " )
2021-02-08 00:39:22 +00:00
case . profileDirectory :
return NSLocalizedString ( " Profile Directory " , comment : " profile directory nav item title " )
2021-02-06 18:48:31 +00:00
case let . list ( list ) :
return list . title
case . addList :
return NSLocalizedString ( " New List... " , comment : " new list nav item title " )
case let . savedHashtag ( hashtag ) :
return hashtag . name
case . addSavedHashtag :
return NSLocalizedString ( " Save Hashtag... " , comment : " save hashtag nav item title " )
case let . savedInstance ( url ) :
return url . host !
case . findInstance :
return NSLocalizedString ( " Find An Instance... " , comment : " find instance nav item title " )
}
}
var image : UIImage {
let name : String
switch self {
case . bookmarks :
name = " bookmark.fill "
2022-04-02 14:39:03 +00:00
case . trendingStatuses :
name = " doc.text.image "
2021-02-06 19:54:35 +00:00
case . trendingTags :
name = " arrow.up.arrow.down "
2021-02-08 00:39:22 +00:00
case . profileDirectory :
name = " person.2.fill "
2021-02-06 18:48:31 +00:00
case . list ( _ ) :
name = " list.bullet "
case . addList , . addSavedHashtag :
name = " plus "
case . savedHashtag ( _ ) :
name = " number "
case . savedInstance ( _ ) :
name = " globe "
case . findInstance :
name = " magnifyingglass "
}
return UIImage ( systemName : name ) !
}
static func = = ( lhs : Item , rhs : Item ) -> Bool {
2019-12-17 23:48:29 +00:00
switch ( lhs , rhs ) {
case ( . bookmarks , . bookmarks ) :
return true
2022-04-02 14:39:03 +00:00
case ( . trendingStatuses , . trendingStatuses ) :
return true
2021-02-06 19:54:35 +00:00
case ( . trendingTags , . trendingTags ) :
return true
2021-02-08 00:39:22 +00:00
case ( . profileDirectory , . profileDirectory ) :
return true
2019-12-17 23:48:29 +00:00
case let ( . list ( a ) , . list ( b ) ) :
return a . id = = b . id
2019-12-18 02:18:32 +00:00
case ( . addList , . addList ) :
return true
2019-12-20 02:20:29 +00:00
case let ( . savedHashtag ( a ) , . savedHashtag ( b ) ) :
return a = = b
case ( . addSavedHashtag , . addSavedHashtag ) :
return true
2019-12-20 03:41:23 +00:00
case let ( . savedInstance ( a ) , . savedInstance ( b ) ) :
return a = = b
case ( . findInstance , . findInstance ) :
return true
2019-12-17 23:48:29 +00:00
default :
return false
}
}
2021-02-06 18:48:31 +00:00
2019-12-17 23:48:29 +00:00
func hash ( into hasher : inout Hasher ) {
switch self {
case . bookmarks :
hasher . combine ( " bookmarks " )
2022-04-02 14:39:03 +00:00
case . trendingStatuses :
hasher . combine ( " trendingStatuses " )
2021-02-06 19:54:35 +00:00
case . trendingTags :
hasher . combine ( " trendingTags " )
2021-02-08 00:39:22 +00:00
case . profileDirectory :
hasher . combine ( " profileDirectory " )
2019-12-17 23:48:29 +00:00
case let . list ( list ) :
hasher . combine ( " list " )
hasher . combine ( list . id )
2019-12-18 02:18:32 +00:00
case . addList :
hasher . combine ( " addList " )
2019-12-20 02:20:29 +00:00
case let . savedHashtag ( hashtag ) :
hasher . combine ( " savedHashtag " )
hasher . combine ( hashtag . name )
case . addSavedHashtag :
hasher . combine ( " addSavedHashtag " )
2019-12-20 03:41:23 +00:00
case let . savedInstance ( url ) :
hasher . combine ( " savedInstance " )
hasher . combine ( url )
case . findInstance :
hasher . combine ( " findInstance " )
2019-12-17 23:48:29 +00:00
}
}
2019-12-17 05:22:25 +00:00
}
}
2019-12-20 03:41:23 +00:00
extension ExploreViewController : InstanceTimelineViewControllerDelegate {
func didSaveInstance ( url : URL ) {
dismiss ( animated : true ) {
2020-01-20 16:48:47 +00:00
self . show ( InstanceTimelineViewController ( for : url , parentMastodonController : self . mastodonController ) , sender : nil )
2019-12-20 03:41:23 +00:00
}
}
func didUnsaveInstance ( url : URL ) {
dismiss ( animated : true )
}
}
2020-12-14 23:44:41 +00:00
2021-02-06 18:48:31 +00:00
extension ExploreViewController : UICollectionViewDragDelegate {
func collectionView ( _ collectionView : UICollectionView , itemsForBeginning session : UIDragSession , at indexPath : IndexPath ) -> [ UIDragItem ] {
2020-12-14 23:44:41 +00:00
guard let item = dataSource . itemIdentifier ( for : indexPath ) ,
let accountID = mastodonController . accountInfo ? . id else {
return [ ]
}
2021-02-06 18:48:31 +00:00
2020-12-14 23:44:41 +00:00
let provider : NSItemProvider
switch item {
case . bookmarks :
provider = NSItemProvider ( object : UserActivityManager . bookmarksActivity ( ) )
case let . list ( list ) :
guard let activity = UserActivityManager . showTimelineActivity ( timeline : . list ( id : list . id ) , accountID : accountID ) else { return [ ] }
provider = NSItemProvider ( object : activity )
case let . savedHashtag ( hashtag ) :
provider = NSItemProvider ( object : hashtag . url as NSURL )
if let activity = UserActivityManager . showTimelineActivity ( timeline : . tag ( hashtag : hashtag . name ) , accountID : accountID ) {
provider . registerObject ( activity , visibility : . all )
}
case let . savedInstance ( url ) :
provider = NSItemProvider ( object : url as NSURL )
// t o d o : s h o u l d d r a g g i n g p u b l i c t i m e l i n e s i n t o n e w w i n d o w s b e s u p p o r t e d ?
2022-04-02 14:39:03 +00:00
default :
2020-12-14 23:44:41 +00:00
return [ ]
}
return [ UIDragItem ( itemProvider : provider ) ]
}
}