This repository has been archived on 2025-03-19. You can view files and clone it, but cannot push or open issues or pull requests.
TapeDeck/grandfatherrock/FourthViewController.swift
Micah Gomez 5b5f914513 1.2 & 1.2.1
launch screen update
more responsive buttons
added external file support
etc
2021-07-31 13:39:30 -06:00

451 lines
16 KiB
Swift

//
// SecondViewController.swift
// grandfatherrock
//
// Created by Micah Gomez on 4/15/20.
// Copyright © 2020 Micah Gomez. All rights reserved.
//
import UIKit
import Zip
import SwiftyJSON
import MediaPlayer
class fileDataCell : UITableViewCell {
@IBOutlet weak var filetypeLabel: UILabel!
@IBOutlet weak var filenameLabel : UILabel!
}
extension FileManager {
func urls(for directory: FileManager.SearchPathDirectory, skipsHiddenFiles: Bool = true ) -> [URL]? {
let documentsURL = urls(for: directory, in: .userDomainMask)[0]
let fileURLs = try? contentsOfDirectory(at: documentsURL, includingPropertiesForKeys: nil, options: skipsHiddenFiles ? .skipsHiddenFiles : [] )
return fileURLs
}
}
class FourthViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, MPMediaPickerControllerDelegate {
var refreshControl = UIRefreshControl()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var resourcesContent = FileManager.default.urls(for: .documentDirectory) ?? []
resourcesContent.sort {
$0.lastPathComponent < $1.lastPathComponent
}
print(FileManager.default.urls(for: .documentDirectory) ?? "none")
return resourcesContent.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "filecell", for: indexPath) as! fileDataCell
var resourcesContent = FileManager.default.urls(for: .documentDirectory) ?? []
resourcesContent.sort {
$0.lastPathComponent < $1.lastPathComponent
}
cell.filenameLabel?.text = resourcesContent[indexPath.row].lastPathComponent
cell.filetypeLabel?.text = resourcesContent[indexPath.row].pathExtension
cell.selectionStyle = .none
return cell
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool
{
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath){
var resourcesContent = FileManager.default.urls(for: .documentDirectory) ?? []
resourcesContent.sort {
$0.lastPathComponent < $1.lastPathComponent
}
let dirs : [String] = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.allDomainsMask, true)
let filePathToDelete = dirs[0].appendingFormat("/" + resourcesContent[indexPath.row].lastPathComponent)
let fileManager = FileManager.default
if editingStyle == .delete
{
do {
//Check if file exists
if fileManager.fileExists(atPath: filePathToDelete) {
//Delete file
try fileManager.removeItem(atPath: filePathToDelete)
} else {
print("File does not exist: \(resourcesContent[indexPath.row].absoluteString)")
}
}
catch let error as NSError {
print("An error took place: \(error)")
}
filesTable.reloadData()
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
var resourcesContent = FileManager.default.urls(for: .documentDirectory) ?? []
resourcesContent.sort {
$0.lastPathComponent < $1.lastPathComponent
}
print(resourcesContent[indexPath.row].lastPathComponent)
print(resourcesContent[indexPath.row])
GlobalVars.musicSelection[GlobalVars.selectedMusicList][GlobalVars.selectedCell!] = resourcesContent[indexPath.row].lastPathComponent
GlobalVars.musicSelectionID[GlobalVars.selectedMusicList][GlobalVars.selectedCell!] = 0
GlobalVars.musicFileURL[GlobalVars.selectedMusicList][GlobalVars.selectedCell!] = resourcesContent[indexPath.row].lastPathComponent
//print("PATH FROM IS \(resourcesContent[indexPath.row].absoluteString)")
print("PATH SAVED IS \(GlobalVars.musicFileURL[GlobalVars.selectedMusicList][GlobalVars.selectedCell!])")
GlobalVars.musicFormatType[GlobalVars.selectedMusicList][GlobalVars.selectedCell!] = false
GlobalVars.selectedCell = nil
self.dismiss(animated: true, completion: nil)
}
let defaults = UserDefaults.standard
@IBOutlet var filesTable: UITableView!
@IBOutlet var gradientView: UIView!
@IBOutlet var selectListControl: UISegmentedControl!
@IBAction func selectListControlChanged(_ sender: Any) {
MPMusicPlayerController.applicationMusicPlayer.stop()
GlobalVars.selectedMusicList = selectListControl.selectedSegmentIndex
//print(GlobalVars.selectedMusicList)
filesTable.reloadData()
/*var noSongs = false
switch GlobalVars.selectedMusicList {
case 0:
for i in GlobalVars.musicSelectionID0 {
if (i == 0){
noSongs = true
}
}
case 1:
for i in GlobalVars.musicSelectionID1 {
if (i == 0){
noSongs = true
}
}
case 2:
for i in GlobalVars.musicSelectionID2 {
if (i == 0){
noSongs = true
}
}
case 3:
for i in GlobalVars.musicSelectionID3 {
if (i == 0){
noSongs = true
}
}
case 4:
for i in GlobalVars.musicSelectionID4 {
if (i == 0){
noSongs = true
}
}
default:
for i in GlobalVars.musicSelectionID0 {
if (i == 0){
noSongs = true
}
}
}
if noSongs {
MPMusicPlayerController.applicationMusicPlayer.pause()
//print("pausing")
}*/
musicHandler.updateMusic()
//print("updating")
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
filesTable.delegate = self
filesTable.dataSource = self
filesTable.alwaysBounceVertical = true
let refresher = UIRefreshControl()
refresher.addTarget(self, action: #selector(refreshStream), for: .valueChanged)
refreshControl = refresher
filesTable.addSubview(refreshControl)
}
@objc func refreshStream() {
print("refresh")
filesTable?.reloadData()
refreshControl.endRefreshing()
}
override func viewWillAppear(_ animated: Bool) {
let prevHour = GlobalVars.hour
GlobalVars.hour = Calendar.current.component(.hour, from: Date())
if GlobalVars.hour != prevHour {
musicHandler.updateMusic()
}
// create the gradient layer
let gradient = CAGradientLayer()
gradient.frame = self.view.bounds
//print("time: ", GlobalVars.hour)
if((GlobalVars.hour >= 8) && (GlobalVars.hour <= 19)){ //Daytime
//print("day")
gradient.colors = [UIColor(red: 0.39, green: 0.69, blue: 1.00, alpha: 1).cgColor, UIColor(red: 0.07, green: 0.45, blue: 0.87, alpha: 1).cgColor]
} else if((GlobalVars.hour >= 20) && (GlobalVars.hour <= 21)){//Sunset
//print("sunset")
gradient.colors = [UIColor(red: 0.00, green: 0.31, blue: 0.59, alpha: 1).cgColor, UIColor(red: 1.00, green: 0.78, blue: 0.88, alpha: 1).cgColor]
} else if((GlobalVars.hour >= 22) || (GlobalVars.hour <= 5)){//Night
//print("night")
gradient.colors = [UIColor(red: 0.08, green: 0.27, blue: 0.59, alpha: 1).cgColor, UIColor(red: 0.00, green: 0.20, blue: 0.29, alpha: 1).cgColor]
} else if((GlobalVars.hour >= 6) && (GlobalVars.hour <= 7)){//Sunrise
//print("sunrise")
gradient.colors = [UIColor(red: 0.02, green: 0.26, blue: 0.49, alpha: 1).cgColor, UIColor(red: 0.89, green: 0.68, blue: 0.60, alpha: 1).cgColor]
}
gradient.locations = [0.00, 1.00]
/*let gradientChangeAnimation = CABasicAnimation(keyPath: "colors")
gradientChangeAnimation.duration = 5.0
if((GlobalVars.hour >= 8) && (GlobalVars.hour <= 19)){ //Daytime
//print("day")
gradientChangeAnimation.toValue = [UIColor(red: 0.00, green: 0.31, blue: 0.59, alpha: 1).cgColor, UIColor(red: 0.07, green: 0.45, blue: 0.87, alpha: 1).cgColor]
} else if((GlobalVars.hour >= 20) && (GlobalVars.hour <= 21)){//Sunset
//print("sunset")
gradientChangeAnimation.toValue = [UIColor(red: 0.00, green: 0.31, blue: 0.59, alpha: 1).cgColor, UIColor(red: 1.00, green: 0.61, blue: 0.43, alpha: 1).cgColor]
} else if((GlobalVars.hour >= 22) || (GlobalVars.hour <= 5)){//Night
//print("night")
gradientChangeAnimation.toValue = [
UIColor(red: 0.68, green: 0.67, blue: 1.0, alpha: 1).cgColor,
UIColor(red: 1.00, green: 0.00, blue: 0.09, alpha: 1).cgColor
]
} else if((GlobalVars.hour >= 6) && (GlobalVars.hour <= 7)){//Sunrise
//print("sunrise")
gradientChangeAnimation.toValue = [UIColor(red: 0.02, green: 0.26, blue: 0.49, alpha: 1).cgColor, UIColor(red: 0.89, green: 0.68, blue: 0.60, alpha: 1).cgColor]
}
gradientChangeAnimation.autoreverses = true
gradientChangeAnimation.fillMode = CAMediaTimingFillMode.forwards
gradientChangeAnimation.isRemovedOnCompletion = false
gradient.add(gradientChangeAnimation, forKey: "colorChange")
*/
// add the gradient to the view
gradientView.layer.addSublayer(gradient)
/*switch GlobalVars.selectedMusicList {
case 0:
//print(GlobalVars.musicSelectionID0)
print(GlobalVars.musicSelection0)
case 1:
//print(GlobalVars.musicSelectionID1)
print(GlobalVars.musicSelection1)
case 2:
//print(GlobalVars.musicSelectionID2)
print(GlobalVars.musicSelection2)
case 3:
//print(GlobalVars.musicSelectionID3)
print(GlobalVars.musicSelection3)
case 4:
//print(GlobalVars.musicSelectionID4)
print(GlobalVars.musicSelection4)
default:
//print(GlobalVars.musicSelectionID0)
print(GlobalVars.musicSelection0)
}*/
}
override func viewDidDisappear(_ animated: Bool) {
gradientView.layer.sublayers?.forEach { $0.removeFromSuperlayer() }
}
@IBAction func importPopup(_ sender: Any) {
//1. Create the alert controller.
let alert = UIAlertController(title: "Download Music", message: "Enter a link to an MP3, ZIP, or properly formatted JSON file \n If your files aren't visible after entering the link, try pulling down to refresh", preferredStyle: .alert)
//2. Add the text field. You can configure it however you need.
alert.addTextField { (textField) in
textField.text = "https://downloads.khinsider.com"
}
// 3. Grab the value from the text field, and print it when the user clicks OK.
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: {_ in
let textField = alert.textFields![0] // Force unwrapping because we know it exists.
print("Text field: \(textField.text)")
if (!textField.text!.isEmpty) {
let fileURL = URL(string: textField.text!)
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig)
let request = URLRequest(url:fileURL!)
if ((fileURL?.pathExtension == "mp3") || (fileURL?.pathExtension == "zip")) {
let documentsUrl:URL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!) as URL
let destinationFileUrl = documentsUrl.appendingPathComponent(fileURL?.lastPathComponent ?? "fileerr")
self.downloadSong(request: request, destination: destinationFileUrl, runFrom: "Default")
} else if (fileURL?.pathExtension == "json") {
print("file is json")
let documentsUrl:URL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!) as URL
let task = session.dataTask(with: request) { (data, response, error) in
if error == nil {
do{
let jsonData = try JSON(data: data!)
print(jsonData)
//print(jsonURL)
for (index,subJson):(String, JSON) in jsonData {
let hour:Int = subJson["hour"].intValue
print(hour)
let url:URL = subJson["url"].url!
//let url:URL = URL(fileURLWithPath: urlAsString)
let urlRequest = URLRequest(url:url)
print(url)
var DLHourPadding:String = ""
if(hour < 10){
DLHourPadding = "0"
}
let destinationFileUrl = documentsUrl.appendingPathComponent((fileURL!.deletingPathExtension().lastPathComponent) + " - " + DLHourPadding + String(hour) + " - " + url.lastPathComponent)
print(destinationFileUrl)
self.downloadSong(request: urlRequest, destination: destinationFileUrl, runFrom: "JSON")
GlobalVars.musicFormatType[GlobalVars.selectedMusicList][hour] = false
GlobalVars.musicSelectionID[GlobalVars.selectedMusicList][hour] = 0
GlobalVars.musicSelection[GlobalVars.selectedMusicList][hour] = destinationFileUrl.lastPathComponent
GlobalVars.musicFileURL[GlobalVars.selectedMusicList][hour] = destinationFileUrl.lastPathComponent
}
}
catch {
print(error)
}
}
}
task.resume()
} else {
let unsupportedAlert = UIAlertController(title: "", message: "Please make sure your url links to an mp3, zip, or json file", preferredStyle: UIAlertController.Style.alert)
unsupportedAlert.addAction(UIAlertAction(title: "Okay", style: UIAlertAction.Style.default, handler: nil))
self.present(unsupportedAlert, animated: true, completion: nil)
}
}
}))
// 4. Present the alert.
self.present(alert, animated: true, completion: nil)
}
@IBAction func close(_ sender: Any) {
dismiss(animated: true)
}
func downloadSong(request:URLRequest,destination:URL,runFrom:String) -> Void {
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig)
let task = session.downloadTask(with: request) { (tempLocalUrl, response, error) in
if let tempLocalUrl = tempLocalUrl, error == nil {
do {
try FileManager.default.copyItem(at: tempLocalUrl, to: destination)
} catch (let writeError) {
print("Error creating a file \(destination) : \(writeError)")
DispatchQueue.main.async {
let writeErrAlert = UIAlertController(title: "Error Saving File '\(destination.lastPathComponent)'", message: "Check to make sure another file with the same name doesn't already exist", preferredStyle: UIAlertController.Style.alert)
writeErrAlert.addAction(UIAlertAction(title: "Okay", style: UIAlertAction.Style.default, handler: nil))
self.present(writeErrAlert, animated: true, completion: nil)
self.filesTable.reloadData()
}
}
// Success
if (runFrom == "Default") {
if let statusCode = (response as? HTTPURLResponse)?.statusCode {
print("Successfully downloaded. Status code: \(statusCode)")
DispatchQueue.main.async {
let dlAlert = UIAlertController(title: "Successfully Downloaded", message: "\(destination.lastPathComponent)", preferredStyle: UIAlertController.Style.alert)
dlAlert.addAction(UIAlertAction(title: "Okay", style: UIAlertAction.Style.default, handler: nil))
self.present(dlAlert, animated: true, completion: nil)
self.filesTable.reloadData()
}
}
}
} else {
print("Error took place while downloading a file. Error description: %@", error?.localizedDescription as Any);
DispatchQueue.main.async {
let networkErrAlert = UIAlertController(title: "Error Downloading File '\(destination.lastPathComponent)'", message: "Check to make sure your internet connection is stable and that the URL is correct", preferredStyle: UIAlertController.Style.alert)
networkErrAlert.addAction(UIAlertAction(title: "Okay", style: UIAlertAction.Style.default, handler: nil))
self.present(networkErrAlert, animated: true, completion: nil)
self.filesTable.reloadData()
}
}
if destination.pathExtension == "zip" {
print("it's a zip!")
if runFrom == "Default" {
let dirs : [String] = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.allDomainsMask, true)
let filePathToDelete = dirs[0].appendingFormat("/" + destination.lastPathComponent)
do {
//let unzipDirectory = try Zip.quickUnzipFile(destination) // Unzip
let unzipDirectory = try Zip.unzipFile(destination, destination: URL(fileURLWithPath: dirs[0]), overwrite: false, password: nil)
}
catch {
print("Something went wrong: \(error)")
}
do {
let fileManager = FileManager.default
// Check if file exists
if fileManager.fileExists(atPath: filePathToDelete) {
// Delete file
try fileManager.removeItem(atPath: filePathToDelete)
} else {
print("File does not exist")
}
}
catch let error as NSError {
print("An error took place: \(error)")
}
} else if runFrom == "JSON" {
print("Cannot download zip in json!")
}
}
}
task.resume()
}
}