-
Notifications
You must be signed in to change notification settings - Fork 12
Create a File Browser
Maximilian Mackh edited this page Apr 17, 2020
·
2 revisions
//
// FileBrowserViewController.swift
// BaseComponents Playground
//
// Created by mmackh on 21/03/2020.
// Copyright © 2020 proconsult.at gmbh. All rights reserved.
//
import UIKit
import QuickLook
import BaseComponents
class FileBrowserCell: UITableViewCell {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: .subtitle, reuseIdentifier: reuseIdentifier)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func bindObject(_ obj: AnyObject) {
let diskData = obj as? DiskData
textLabel?.text = diskData?.name
detailTextLabel?.text = diskData is Directory ? "Folder" : "File"
}
}
class DirectoryRender: UIView {
lazy var render: DataRender = {
let config: DataRenderConfiguration = .init(cellClass: FileBrowserCell.self)
let render = DataRender(configuration: config)
render.adjustInsets = true
return render
}()
let directory: Directory
init(_ directory: Directory) {
self.directory = directory
super.init(frame: .zero)
self.addSplitView { (splitView) in
splitView.direction = .horizontal
splitView.addSubview(render, layoutType: .equal)
splitView.addSubview(UIView().color(.background, .lightGray), layoutType: .fixed, value: SplitView.onePixelHeight)
}
reloadData()
}
func reloadData() {
render.renderArray(directory.contents().sorted(by: { $0.name.localizedStandardCompare($1.name) == .orderedAscending }))
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class FileBrowserViewController: UIViewController, QLPreviewControllerDataSource {
var scrollingView: ScrollingView?
var directoryRenders: Array<DirectoryRender> = []
var currentSelectedFile: File?
override func viewDidLoad() {
super.viewDidLoad()
title = "App Documents"
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, { [unowned self] (barButtonItem) in
UIAlertController.show(style: .alert, title: nil, message: nil, options: ["Create File", "New Folder"], dismiss: "Cancel") { (idx) in
let directoryRender = self.directoryRenders.last!
let directory = directoryRender.directory
if (idx == 0) {
let file = directory.newFile(name: "New File.txt", createIfNeeded: false)
if file.exists() {
var fileNr = 1
let fileNameTemplate = "New File %i.txt"
while directory.newFile(name: String(format: fileNameTemplate, fileNr), createIfNeeded: false).exists() {
fileNr += 1
}
_ = directory.newFile(name: String(format: fileNameTemplate, fileNr), createIfNeeded: true)
} else {
file.create()
}
} else {
let createdDirectory = directory.newDirectory(name: "New Folder", createIfNeeded: false)
if (createdDirectory.exists()) {
var dirNr = 1
let dirNameTemplate = "New Folder %i"
while directory.newDirectory(name: String(format: dirNameTemplate, dirNr), createIfNeeded: false).exists() {
dirNr += 1
}
_ = directory.newDirectory(name: String(format: dirNameTemplate, dirNr), createIfNeeded: true)
} else {
createdDirectory.create()
}
}
directoryRender.reloadData()
}
})
view.color(.background, .white)
view.addSplitView { [unowned self] (splitView) in
self.scrollingView = ScrollingView(frame: .zero)
self.scrollingView?.direction = .horizontal
self.scrollingView?.alwaysBounceHorizontal = true
self.scrollingView?.contentInsetAdjustmentBehavior = .never
splitView.addSubview(self.scrollingView!, layoutType: .percentage, value: 100)
}
showDirectory(Directory(searchPathDirectory: .documentDirectory))
}
func showDirectory(_ directory: Directory) {
let directoryRender = DirectoryRender(directory)
directoryRender.render.onSelect { [unowned self] (itemRenderProperties) in
let diskData = itemRenderProperties.object as? DiskData
if diskData is Directory {
if let idx = self.directoryRenders.firstIndex(of: itemRenderProperties.render?.superview?.superview as! DirectoryRender) {
var iidx = 0
let directoryRendersCopy = self.directoryRenders
for directoryRender in directoryRendersCopy {
if iidx > idx {
directoryRender.removeFromSuperview()
self.directoryRenders.remove(at: self.directoryRenders.firstIndex(of: directoryRender)!)
}
iidx += 1
}
}
self.showDirectory(diskData as! Directory)
}
if diskData is File {
self.currentSelectedFile = diskData as? File
let previewController = QLPreviewController()
previewController.dataSource = self
self.present(previewController, animated: true)
}
}
directoryRenders.append(directoryRender)
if let scrollingView = self.scrollingView {
scrollingView.addSubview(directoryRender, layoutType: .fixed, value: 320, edgeInsets: .zero)
scrollingView.invalidateLayout()
scrollingView.setContentOffset(CGPoint(x: max(0, (scrollingView.contentSize.width - scrollingView.bounds.size.width)), y: 0), animated: true)
}
}
func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
1
}
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
return currentSelectedFile!.pathURL as QLPreviewItem
}
}