123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- // _____ _
- // |_ _| |_ _ _ ___ ___ _ __ __ _
- // | | | ' \| '_/ -_) -_) ' \/ _` |_
- // |_| |_||_|_| \___\___|_|_|_\__,_(_)
- //
- // Threema iOS Client
- // Copyright (c) 2020 Threema GmbH
- //
- // This program is free software: you can redistribute it and/or modify
- // it under the terms of the GNU Affero General Public License, version 3,
- // as published by the Free Software Foundation.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU Affero General Public License for more details.
- //
- // You should have received a copy of the GNU Affero General Public License
- // along with this program. If not, see <https://www.gnu.org/licenses/>.
- import UIKit
- class ThumbnailCollectionViewController: NSObject, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
-
- var parent: MediaPreviewViewController?
-
- let mediaFetchQueue = DispatchQueue(label: "MediaDataFetchQueue",
- qos: .userInitiated,
- attributes: .concurrent,
- autoreleaseFrequency: .inherit,
- target: nil)
-
- private let reuseIdentifier = "thumbnailCell"
- private let collectionViewInsets : CGFloat = 10
-
- func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
- return parent?.mediaData.count ?? 0
- }
-
- func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
- return 5.0
- }
-
- func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
- return 5.0
- }
-
- func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
- let collectionViewHeight = collectionView.frame.height
- let width = collectionViewHeight - collectionViewInsets
- let height = collectionViewHeight - collectionViewInsets
-
- return CGSize(width: width, height: height)
- }
-
- func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
- let cell = collectionView
- .dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! ThumbnailCollectionViewCell
- cell.startLoading()
-
- cell.identifier = indexPath
-
- self.mediaFetchQueue.async {
- self.parent?.mediaData[indexPath.item].getThumbnail(onCompletion: { image in
- self.imageHandler(image: image, cell : cell, indexPath: indexPath)
- })
- }
- return cell
- }
-
- func imageHandler(image : UIImage, cell : ThumbnailCollectionViewCell, indexPath : IndexPath) {
- if cell.identifier != indexPath {
- // Cell has been reused do not update image
- return
- }
- DispatchQueue.main.async {
- cell.loadImage(image: image)
- }
- }
-
- func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
- parent!.largeCollectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
- parent!.updateTextForIndex(indexPath: indexPath, animated: true)
- parent!.currentItem = indexPath
- collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
- NotificationCenter.default.post(name: NSNotification.Name(rawValue: kMediaPreviewPauseVideo), object: nil)
- }
-
- func removeItem(at indexPath: IndexPath) {
- _ = parent?.mediaData.remove(at: indexPath.item)
- parent?.largeCollectionView.reloadData()
- parent?.updateSelection()
- }
-
- func insertItem(_ item: MediaPreviewItem, at indexPath: IndexPath) {
- parent?.mediaData.insert(item, at: indexPath.item)
- parent?.largeCollectionView.reloadData()
- parent?.updateSelection()
- }
- }
- @available(iOS 11.0, *)
- extension ThumbnailCollectionViewController: UICollectionViewDragDelegate {
-
- func collectionView(_ collectionView: UICollectionView, dragSessionIsRestrictedToDraggingApplication session: UIDragSession) -> Bool {
- return true
- }
-
- func collectionView(_ collectionView: UICollectionView,
- itemsForBeginning session: UIDragSession,
- at indexPath: IndexPath) -> [UIDragItem] {
-
- let cell = collectionView.cellForItem(at: indexPath) as! ThumbnailCollectionViewCell
- guard let image = cell.imageView.image else {
- return []
- }
-
- let item = NSItemProvider(object: image)
- let dragItem = UIDragItem(itemProvider: item)
- return [dragItem]
- }
- }
- @available(iOS 11.0, *)
- extension ThumbnailCollectionViewController: UICollectionViewDropDelegate {
-
- func collectionView(
- _ collectionView: UICollectionView,
- dropSessionDidUpdate session: UIDropSession,
- withDestinationIndexPath destinationIndexPath: IndexPath?)
- -> UICollectionViewDropProposal {
- return UICollectionViewDropProposal(
- operation: .move,
- intent: .insertAtDestinationIndexPath)
- }
-
- func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator) {
- guard let destinationIndexPath = coordinator.destinationIndexPath else {
- return
- }
-
- coordinator.items.forEach { dropItem in
- guard let sourceIndexPath = dropItem.sourceIndexPath else {
- return
- }
-
- collectionView.performBatchUpdates({
- let item = parent?.mediaData[sourceIndexPath.item]
- removeItem(at: sourceIndexPath)
- insertItem(item!, at: destinationIndexPath)
- collectionView.deleteItems(at: [sourceIndexPath])
- collectionView.insertItems(at: [destinationIndexPath])
- }, completion: { _ in
- coordinator.drop(dropItem.dragItem,
- toItemAt: destinationIndexPath)
- })
- if self.parent?.currentItem == sourceIndexPath {
- self.parent?.currentItem = destinationIndexPath
- } else {
- if destinationIndexPath < self.parent!.currentItem && sourceIndexPath > self.parent!.currentItem {
- self.parent?.currentItem = IndexPath(item: min(self.parent!.currentItem.item + 1, self.parent!.mediaData.count - 1), section: 0)
- } else if destinationIndexPath > self.parent!.currentItem && sourceIndexPath < self.parent!.currentItem {
- self.parent?.currentItem = IndexPath(item: max(self.parent!.currentItem.item - 1, 0), section: 0)
- } else if destinationIndexPath == self.parent!.currentItem {
- if sourceIndexPath < self.parent!.currentItem {
- self.parent?.currentItem = IndexPath(item: max(self.parent!.currentItem.item - 1, 0), section: 0)
- } else {
- self.parent?.currentItem = IndexPath(item: min(self.parent!.currentItem.item + 1, self.parent!.mediaData.count - 1), section: 0)
-
- }
- }
- }
-
- self.parent?.largeCollectionView.selectItem(at: self.parent?.currentItem, animated: true, scrollPosition: .centeredHorizontally)
- self.parent?.updateSelection()
- self.parent?.shouldScrollTo(indexPath: self.parent!.currentItem)
- }
- }
-
- func collectionView(_ collectionView: UICollectionView,
- canHandle session: UIDropSession) -> Bool {
- return true
- }
- }
|