// // DetailViewController.swift // kplayer // // Created by Marco Schmickler on 24.05.15. // Copyright (c) 2015 Marco Schmickler. All rights reserved. // import UIKit import Alamofire import FileBrowser import AVFoundation import ZIPFoundation import SwiftUI protocol DetailDelegate { func loadDetails(selectedItem: MediaItem, completionHandler: @escaping () -> Void) func deleteThumb(selectedItem: MediaItem) func deleteLocal(selectedItem: MediaItem) func saveItem(selectedItem: MediaItem) func favItem(_ item: MediaItem) func settings() -> KSettings func offline() -> Bool } class DetailViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource, UICollectionViewDragDelegate { var delegate : DetailDelegate? @IBOutlet weak var detailDescriptionLabel: UILabel! var showFavoritesOnly = false var collectionView: UICollectionView! var currentItem: MediaItem? var defaultItemSize = CGSize(width: (15 * 16) - 6, height: 15 * 9) var modeButton: UIBarButtonItem? var mode = false var detailItem: MediaItem? { didSet { // print(detailItem!.children) if collectionView != nil { collectionView.reloadData() } } } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) NotificationCenter.default.addObserver(self, selector: #selector(refreshItems(_:)), name: NSNotification.Name(rawValue: "loadedItems"), object: nil) } deinit { NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: "loadedItems"), object: nil) } override func viewDidLoad() { super.viewDidLoad() let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout() layout.sectionInset = UIEdgeInsets(top: 1, left: 0, bottom: 1, right: 0) layout.minimumInteritemSpacing = 0.0; layout.itemSize = defaultItemSize layout.headerReferenceSize = CGSize(width: 50, height: 50) collectionView = UICollectionView(frame: view.frame, collectionViewLayout: layout) collectionView.dataSource = self collectionView.delegate = self collectionView.register(ItemCell.self, forCellWithReuseIdentifier: "Cell") collectionView.backgroundColor = UIColor.lightGray collectionView.register(HeaderCell.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "HeaderView"); collectionView.dragInteractionEnabled = true collectionView.dragDelegate = self view.addSubview(collectionView) view.autoresizesSubviews = true collectionView.autoresizingMask = [UIView.AutoresizingMask.flexibleWidth, UIView.AutoresizingMask.flexibleHeight] // Do any additional setup after loading the view, typically from a nib. collectionView.reloadData() // attach long press gesture to collectionView let lpgr = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(_:))) lpgr.minimumPressDuration = 1; //seconds lpgr.delaysTouchesBegan = true self.collectionView.addGestureRecognizer(lpgr); modeButton = UIBarButtonItem(barButtonSystemItem: .search , target: self, action: #selector(switchMode)); let settingsButton = UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(settings)); let overviewButton = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(overview)); let favButton = UIBarButtonItem(barButtonSystemItem: .bookmarks, target: self, action: #selector(favorites)); let browserButton = UIBarButtonItem(barButtonSystemItem: .organize, target: self, action: #selector(fileBrowser)); navigationItem.rightBarButtonItems = [settingsButton, favButton, overviewButton,browserButton,modeButton!] if detailItem != nil { if detailItem!.children != nil { var d = detailItem!.children // print("Details \(d)") } } } @objc func switchMode() { mode = !mode if let b = modeButton { b.isSelected = mode } } // https://github.com/marmelroy/FileBrowser @objc func fileBrowser() { let d = FileHelper.getDocumentsDirectory() LocalManager.sharedInstance.prepareLocalFolder() let fileBrowser = FileBrowser(initialPath: d, allowEditing: true) fileBrowser.modalPresentationStyle = .fullScreen present(fileBrowser, animated: true, completion: nil) } // Favorites Button @objc func favorites() { showFavoritesOnly = !showFavoritesOnly collectionView.reloadData() } // Edit Settings Button @objc func settings() { let kv = KSettingsView(kSettings: LocalManager.sharedInstance.settings, completionHandler: { self.dismiss(animated: true, completion: nil); } ) let pc = UIHostingController(rootView: kv) let navController = UINavigationController(rootViewController: pc) // Creating a navigation controller with pc at the root of the navigation stack. navController.modalPresentationStyle = .fullScreen present(navController, animated: false, completion: nil) } // Overview Button @objc func overview() { var i = [MediaItem]() if let d = detailItem { showAllVideos(d) return let pc = MediaPhotoController() for it in d.children { if it.children.count > 1 || !showFavoritesOnly { for c in it.children { i.append(c) } } } pc.items = i pc.completionHandler = { self.dismiss(animated: true, completion: nil); } let navController = UINavigationController(rootViewController: pc) // Creating a navigation controller with pc at the root of the navigation stack. navController.modalPresentationStyle = .fullScreen present(navController, animated: false, completion: nil) } } @objc func refreshItems(_ notification: Notification) { if notification.object == nil { if self.collectionView != nil { self.collectionView.reloadData() } return } let i = notification.object as! MediaItem let index = i.index let oid = ObjectIdentifier(self) if let detail: MediaItem = self.detailItem { if i.type == ItemType.VIDEO { let set = IndexSet(integer: index) if index < detail.children.count { if (collectionView != nil) { collectionView.reloadSections(set) } } } else { if i.parent! !== detail { return } print("Object: \(oid.hashValue) Index \(index) Item: \(i) Parent: \(i.parent) Detail: \(detailItem)") collectionView.performBatchUpdates({ var newItems = [IndexPath]() var j = 0 if detail.children.count > index { let path = IndexPath(item: 0, section: index) self.collectionView.reloadItems(at: [path]) for _ in detail.children[index].children { if j >= 1 { newItems.append(IndexPath(item: j, section: index)) } j += 1 } self.collectionView.insertItems(at: newItems) } return }, completion: nil) } } } // delete item @objc func handleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer) { if (gestureRecognizer.state != UIGestureRecognizer.State.ended) { return; } let p = gestureRecognizer.location(in: self.collectionView); let indexPath = self.collectionView.indexPathForItem(at: p); if (indexPath == nil) { print("couldn't find index path"); } else { if let detail: MediaItem = self.detailItem { let refreshAlert = UIAlertController(title: "Delete", message: "All data will be lost.", preferredStyle: UIAlertController.Style.alert) refreshAlert.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (action: UIAlertAction!) in let items = detail.children[indexPath!.section] if (items.loaded) { if (items.root == "/tags") { // } else { if items.children.count == 0 { } else { if indexPath!.item >= items.children.count { } else { let c = items.children.remove(at: indexPath!.item) self.delegate!.deleteThumb(selectedItem: c) self.collectionView.reloadData() } } } } else if items.local { // self.delegate!.deleteLocal(selectedItem: items) } })) refreshAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (action: UIAlertAction!) in print("Handle Cancel Logic here") })) present(refreshAlert, animated: true, completion: nil) } } } func numberOfSections(in collectionView: UICollectionView) -> Int { if let detail: MediaItem = self.detailItem { let cnt = detail.children.count return cnt } return 0 } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { if let detail: MediaItem = self.detailItem { let n = detail.children[section].children.count if n < 2 && showFavoritesOnly { return 0 } if n == 0 && !showFavoritesOnly { return 1 } return n } return 0 } // show cell func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! ItemCell if let detail: MediaItem = self.detailItem { let items = detail.children[indexPath.section] if items.children.count == 0 { cell.setItem(items) } else { if indexPath.item >= items.children.count { cell.setItem(items) } else { let item = items.children[indexPath.item] cell.setItem(item) } } } return cell } // show Section header func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { switch kind { case UICollectionView.elementKindSectionHeader: let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "HeaderView", for: indexPath) as! HeaderCell let items = detailItem!.children[indexPath.section] headerView.setItem(items) return headerView default: fatalError("Unexpected element kind") } } // select item func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { if let detail: MediaItem = self.detailItem { print(detail.toJSON()) let sectionItem = detail.children[indexPath.section] currentItem = sectionItem if currentItem!.type == .PICS { currentItem = sectionItem.clone() } if currentItem!.type == .FOLDER { currentItem = sectionItem.children[indexPath.item] } var selectedItem = sectionItem let weiter: () -> Void = { // if (sectionItem.type == ItemType.VIDEO || sectionItem.loaded) { if indexPath.item >= sectionItem.children.count { selectedItem = sectionItem print(sectionItem.name) } else { selectedItem = sectionItem.children[indexPath.item] print(selectedItem.name) } // } self.showDetails(sectionItem: self.currentItem!, selectedItem: selectedItem) } delegate!.loadDetails(selectedItem: currentItem!, completionHandler: weiter) } } // Drag and drop func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] { if let detail: MediaItem = self.detailItem { var selectedItem = detail.children[indexPath.section] if selectedItem.children.count > indexPath.item { selectedItem = selectedItem.children[indexPath.item] } if !selectedItem.local { // return [] } let itemProvider = NSItemProvider(object: selectedItem.toJSON() as NSString) return [UIDragItem(itemProvider: itemProvider)] } return [] } func collectionView(_ collectionView: UICollectionView, dragSessionDidEnd session: UIDragSession) { collectionView.reloadData() } }