From b5503cc00a0abb8cf973f7195019690bbcaf721a Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Tue, 20 Mar 2018 18:12:23 -0400 Subject: [PATCH] Handle empty media gallery // FREEBIE --- .../MediaTileViewController.swift | 70 ++++++++++++++----- .../translations/en.lproj/Localizable.strings | 5 +- 2 files changed, 55 insertions(+), 20 deletions(-) diff --git a/Signal/src/ViewControllers/MediaTileViewController.swift b/Signal/src/ViewControllers/MediaTileViewController.swift index d2a2522ea..3c4e1eb3a 100644 --- a/Signal/src/ViewControllers/MediaTileViewController.swift +++ b/Signal/src/ViewControllers/MediaTileViewController.swift @@ -84,7 +84,7 @@ public class MediaTileViewController: UICollectionViewController, MediaGalleryCe collectionView.register(MediaGalleryCell.self, forCellWithReuseIdentifier: MediaGalleryCell.reuseIdentifier) collectionView.register(MediaGallerySectionHeader.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: MediaGallerySectionHeader.reuseIdentifier) - collectionView.register(MediaGalleryLoadingHeader.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: MediaGalleryLoadingHeader.reuseIdentifier) + collectionView.register(MediaGalleryStaticHeader.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: MediaGalleryStaticHeader.reuseIdentifier) collectionView.delegate = self @@ -146,10 +146,22 @@ public class MediaTileViewController: UICollectionViewController, MediaGalleryCe // MARK: UIColletionViewDataSource override public func numberOfSections(in collectionView: UICollectionView) -> Int { + guard galleryDates.count > 0 else { + // empty gallery + return 1 + } + + // One for each galleryDate plus a "loading older" and "loading newer" section return galleryItems.keys.count + 2 } override public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection sectionIdx: Int) -> Int { + + guard galleryDates.count > 0 else { + // empty gallery + return 0 + } + if sectionIdx == kLoadOlderSectionIdx { // load older return 0 @@ -176,10 +188,22 @@ public class MediaTileViewController: UICollectionViewController, MediaGalleryCe override public func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { let defaultView = UICollectionReusableView() + + guard galleryDates.count > 0 else { + guard let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: MediaGalleryStaticHeader.reuseIdentifier, for: indexPath) as? MediaGalleryStaticHeader else { + + owsFail("\(logTag) in \(#function) unable to build section header for kLoadOlderSectionIdx") + return defaultView + } + let title = NSLocalizedString("GALLERY_TILES_EMPTY_GALLERY", comment: "Label indicating media gallery is empty") + sectionHeader.configure(title: title) + return sectionHeader + } + if (kind == UICollectionElementKindSectionHeader) { switch indexPath.section { case kLoadOlderSectionIdx: - guard let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: MediaGalleryLoadingHeader.reuseIdentifier, for: indexPath) as? MediaGalleryLoadingHeader else { + guard let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: MediaGalleryStaticHeader.reuseIdentifier, for: indexPath) as? MediaGalleryStaticHeader else { owsFail("\(logTag) in \(#function) unable to build section header for kLoadOlderSectionIdx") return defaultView @@ -188,7 +212,7 @@ public class MediaTileViewController: UICollectionViewController, MediaGalleryCe sectionHeader.configure(title: title) return sectionHeader case loadNewerSectionIdx: - guard let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: MediaGalleryLoadingHeader.reuseIdentifier, for: indexPath) as? MediaGalleryLoadingHeader else { + guard let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: MediaGalleryStaticHeader.reuseIdentifier, for: indexPath) as? MediaGalleryStaticHeader else { owsFail("\(logTag) in \(#function) unable to build section header for kLoadOlderSectionIdx") return defaultView @@ -219,6 +243,11 @@ public class MediaTileViewController: UICollectionViewController, MediaGalleryCe let defaultCell = UICollectionViewCell() + guard galleryDates.count > 0 else { + owsFail("\(logTag) in \(#function) unexpected cell for loadNewerSectionIdx") + return defaultCell + } + switch indexPath.section { case kLoadOlderSectionIdx: owsFail("\(logTag) in \(#function) unexpected cell for kLoadOlderSectionIdx") @@ -259,25 +288,27 @@ public class MediaTileViewController: UICollectionViewController, MediaGalleryCe layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { - let kHeaderHeight: CGFloat = 50 + let kMonthHeaderSize: CGSize = CGSize(width: 0, height: 50) + let kStaticHeaderSize: CGSize = CGSize(width: 0, height: 100) + + guard galleryDates.count > 0 else { + return kStaticHeaderSize + } + + guard let mediaGalleryDataSource = self.mediaGalleryDataSource else { + owsFail("\(logTag) in \(#function) mediaGalleryDataSource was unexpectedly nil") + return CGSize.zero + } switch section { case kLoadOlderSectionIdx: // Show "loading older..." iff there is still older data to be fetched - guard let mediaGalleryDataSource = self.mediaGalleryDataSource else { - owsFail("\(logTag) in \(#function) mediaGalleryDataSource was unexpectedly nil") - return CGSize.zero - } - return mediaGalleryDataSource.hasFetchedOldest ? CGSize.zero : CGSize(width: 0, height: 100) + return mediaGalleryDataSource.hasFetchedOldest ? CGSize.zero : kStaticHeaderSize case loadNewerSectionIdx: // Show "loading newer..." iff there is still more recent data to be fetched - guard let mediaGalleryDataSource = self.mediaGalleryDataSource else { - owsFail("\(logTag) in \(#function) mediaGalleryDataSource was unexpectedly nil") - return CGSize.zero - } - return mediaGalleryDataSource.hasFetchedMostRecent ? CGSize.zero : CGSize(width: 0, height: 100) + return mediaGalleryDataSource.hasFetchedMostRecent ? CGSize.zero : kStaticHeaderSize default: - return CGSize(width: 0, height: kHeaderHeight) + return kMonthHeaderSize } } // MARK: MediaGalleryDelegate @@ -518,19 +549,20 @@ fileprivate protocol MediaGalleryCellDelegate: class { func didTapCell(_ cell: MediaGalleryCell, item: MediaGalleryItem) } -fileprivate class MediaGalleryLoadingHeader: UICollectionViewCell { +fileprivate class MediaGalleryStaticHeader: UICollectionViewCell { - static let reuseIdentifier = "MediaGalleryLoadingHeader" + static let reuseIdentifier = "MediaGalleryStaticHeader" let label = UILabel() override init(frame: CGRect) { super.init(frame: frame) - // TODO add spinnner, start/stop animating on will/end display addSubview(label) - label.autoCenterInSuperview() + label.textAlignment = .center + label.numberOfLines = 0 + label.autoPinEdgesToSuperviewMargins() } @available(*, unavailable, message: "Unimplemented") diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index dc32e2d7e..1309f1733 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -770,8 +770,11 @@ /* Accessibilty label for finishing new group */ "FINISH_GROUP_CREATION_LABEL" = "Finish creating group"; +/* Label indicating media gallery is empty */ +"GALLERY_TILES_EMPTY_GALLERY" = "You haven't sent or received any media in this conversation yet."; + /* Label indicating loading is in progress */ -"GALLERY_TILES_LOADING_MORE_RECENT_LABEL" = "Loadering Newer Media..."; +"GALLERY_TILES_LOADING_MORE_RECENT_LABEL" = "Loading Newer Media..."; /* Label indicating loading is in progress */ "GALLERY_TILES_LOADING_OLDER_LABEL" = "Loading Older Media...";