diff --git a/LightshowManager/AppDelegate.swift b/LightshowManager/AppDelegate.swift new file mode 100644 index 0000000..8930273 --- /dev/null +++ b/LightshowManager/AppDelegate.swift @@ -0,0 +1,39 @@ +// +// AppDelegate.swift +// LightshowManager +// +// Created by Quentin Millardet on 20/04/2024. +// + +import UIKit + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + + var model : LightshowModel?; + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + Thread.sleep(forTimeInterval: 3.0) + model = LightshowModel() + + return true + } + + // MARK: UISceneSession Lifecycle + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } + + func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they will not return. + } + + +} + diff --git a/LightshowManager/Assets.xcassets/AccentColor.colorset/Contents.json b/LightshowManager/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/LightshowManager/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/LightshowManager/Assets.xcassets/AppIcon.appiconset/1024.png b/LightshowManager/Assets.xcassets/AppIcon.appiconset/1024.png new file mode 100644 index 0000000..fdb6437 Binary files /dev/null and b/LightshowManager/Assets.xcassets/AppIcon.appiconset/1024.png differ diff --git a/LightshowManager/Assets.xcassets/AppIcon.appiconset/Contents.json b/LightshowManager/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..cff1680 --- /dev/null +++ b/LightshowManager/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,14 @@ +{ + "images" : [ + { + "filename" : "1024.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/LightshowManager/Assets.xcassets/Contents.json b/LightshowManager/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/LightshowManager/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/LightshowManager/Base.lproj/LaunchScreen.storyboard b/LightshowManager/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..00f8a82 --- /dev/null +++ b/LightshowManager/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LightshowManager/Base.lproj/Main.storyboard b/LightshowManager/Base.lproj/Main.storyboard new file mode 100644 index 0000000..16a3826 --- /dev/null +++ b/LightshowManager/Base.lproj/Main.storyboard @@ -0,0 +1,259 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LightshowManager/DTO/ExampleDTO.swift b/LightshowManager/DTO/ExampleDTO.swift new file mode 100644 index 0000000..b9cfcab --- /dev/null +++ b/LightshowManager/DTO/ExampleDTO.swift @@ -0,0 +1,8 @@ +// +// ExampleDTO.swift +// LightshowManager +// +// Created by Quentin Millardet on 05/05/2024. +// + +import Foundation diff --git a/LightshowManager/ExempleDTO/ExempleDTO.swift b/LightshowManager/ExempleDTO/ExempleDTO.swift new file mode 100644 index 0000000..2d57386 --- /dev/null +++ b/LightshowManager/ExempleDTO/ExempleDTO.swift @@ -0,0 +1,8 @@ +// +// ExempleDTO.swift +// LightshowManager +// +// Created by Quentin Millardet on 05/05/2024. +// + +import Foundation diff --git a/LightshowManager/Info.plist b/LightshowManager/Info.plist new file mode 100644 index 0000000..dd3c9af --- /dev/null +++ b/LightshowManager/Info.plist @@ -0,0 +1,25 @@ + + + + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + + + diff --git a/LightshowManager/LightshowDownloadCell.swift b/LightshowManager/LightshowDownloadCell.swift new file mode 100644 index 0000000..1c88734 --- /dev/null +++ b/LightshowManager/LightshowDownloadCell.swift @@ -0,0 +1,14 @@ +// +// LightshowDownloadCell.swift +// LightshowManager +// +// Created by Quentin Millardet on 21/04/2024. +// + +import UIKit + +class LightshowDownloadCell : UITableViewCell{ + + @IBOutlet weak var warningMessage: UIImageView! + @IBOutlet weak var LightshowName: UILabel! +} diff --git a/LightshowManager/LightshowDownloadView.swift b/LightshowManager/LightshowDownloadView.swift new file mode 100644 index 0000000..19c7812 --- /dev/null +++ b/LightshowManager/LightshowDownloadView.swift @@ -0,0 +1,53 @@ +// +// StudentTableViewController.swift +// SchoolList8 +// +// Created by Quentin Millardet on 14/10/2020. +// + +import UIKit + +class LightshowDownloadView: UITableViewController{ + + var model:LightshowModel? + + override func viewDidLoad() { + super.viewDidLoad() + model = (UIApplication.shared.delegate as! AppDelegate).model + } + + // Return the number of rows for the table. + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return model!.getStudentCount() + } + + // Provide a cell object for each row. + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + // Fetch a cell of the appropriate type. + let cell = tableView.dequeueReusableCell(withIdentifier: "lightshowDownloadCell") + let model = model?.getStudentAtIndex(indexPath.row); + (cell as! LightshowDownloadCell).LightshowName.text = model?.name + (cell as! LightshowDownloadCell).warningMessage.isHidden = model?.isOkFiles() ?? false; + return cell! + } + + + // Permet de passer des informations à une vue avant que celle-ci ne soit créee + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + + } + + @IBAction func unwindFromCancel(_ unwindSegue: UIStoryboardSegue) { + //let sourceViewController : EditController = unwindSegue.source as! EditController + //NSLog(sourceViewController.nameField.text!) + // Use data from the view controller which initiated the unwind segue + } + + @IBAction func unwindFromOk(_ unwindSegue: UIStoryboardSegue) { + //let sourceViewController : EditController = unwindSegue.source as! EditController + let newName : String = "sourceViewController.nameField.text!" + let row : Int = 1; + model?.setStudentAtIndex(row , withdraw: newName) + tableView.reloadData() + } +} diff --git a/LightshowManager/LightshowManager.entitlements b/LightshowManager/LightshowManager.entitlements new file mode 100644 index 0000000..0c67376 --- /dev/null +++ b/LightshowManager/LightshowManager.entitlements @@ -0,0 +1,5 @@ + + + + + diff --git a/LightshowManager/LightshowModel.swift b/LightshowManager/LightshowModel.swift new file mode 100644 index 0000000..c615111 --- /dev/null +++ b/LightshowManager/LightshowModel.swift @@ -0,0 +1,102 @@ +// +// LightshowModel.swift +// LightshowManager +// +// Created by Quentin Millardet on 21/04/2024. +// + +import UIKit + + +class Lightshow { + + + var name : String; + var urls : URLLightshow = URLLightshow(); + + init(_ name : String){ + self.name = name; + } + + func isOkFiles() -> Bool { + return self.urls.fseq != nil && self.urls.mp3 != nil; + } + +} + +struct URLLightshow { + + var fseq : String! = nil ; + var mp3 : String! = nil; + +} + + +class LightshowModel{ + var names : Array = [] ; + + init(){ + + } + + func getStudentAtIndex(_ i :Int) -> Lightshow{ + +// let url = URL(string: "https://bit.ly/3sspdFO")! +// +// var request = URLRequest(url: url) +// +// request.setValue( +// "application/json", +// forHTTPHeaderField: "Content-Type" +// ) +// let task = URLSession.shared.dataTask(with: request) { data, response, error in +// if let data = data { +// if let books = try? JSONDecoder().decode([Book].self, from: data) { +// self.names = []; +// for book in books{ +// self.names.append(book.title) +// } +// } else { +// print("Invalid Response") +// } +// } else if let error = error { +// print("HTTP Request Failed \(error)") +// } +// } +// +// task.resume() + return names[i]; + } + + func getStudentCount() -> Int{ + return names.count; + } + + func setStudentAtIndex(_ index: Int, withdraw value : String){ + var filenameArray = value.split(separator: ".") + filenameArray.remove(at: filenameArray.count - 1) + + let valueNomalized = filenameArray.joined() + + var foundLightshow : Lightshow! = nil; + + for lightshow in names { + if (lightshow.name == valueNomalized ){ + foundLightshow = lightshow; + } + } + if (foundLightshow == nil){ + foundLightshow = Lightshow(valueNomalized); + names.append(foundLightshow) + } + if (value.contains(".mp3")){ + foundLightshow.urls.mp3 = value; + } else if (value.contains(".fseq")){ + foundLightshow.urls.fseq = value; + } + } + + func resetStundent() -> Void { + self.names = []; + } +} diff --git a/LightshowManager/SceneDelegate.swift b/LightshowManager/SceneDelegate.swift new file mode 100644 index 0000000..286102a --- /dev/null +++ b/LightshowManager/SceneDelegate.swift @@ -0,0 +1,52 @@ +// +// SceneDelegate.swift +// LightshowManager +// +// Created by Quentin Millardet on 20/04/2024. +// + +import UIKit + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. + // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. + // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). + guard let _ = (scene as? UIWindowScene) else { return } + } + + func sceneDidDisconnect(_ scene: UIScene) { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + // Release any resources associated with this scene that can be re-created the next time the scene connects. + // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). + } + + func sceneDidBecomeActive(_ scene: UIScene) { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + } + + func sceneWillResignActive(_ scene: UIScene) { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + } + + func sceneWillEnterForeground(_ scene: UIScene) { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. + } + + func sceneDidEnterBackground(_ scene: UIScene) { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // to restore the scene back to its current state. + } + + +} + diff --git a/LightshowManager/ViewController.swift b/LightshowManager/ViewController.swift new file mode 100644 index 0000000..7406e0f --- /dev/null +++ b/LightshowManager/ViewController.swift @@ -0,0 +1,98 @@ +// +// ViewController.swift +// LightshowManager +// +// Created by Quentin Millardet on 20/04/2024. +// + +import UIKit +import os + +class ViewController: UIViewController, UIDocumentPickerDelegate { + + var startingDirectory : URL? + var model : LightshowModel? + + override func viewDidLoad() { + super.viewDidLoad() + model = (UIApplication.shared.delegate as! AppDelegate).model + + // Do any additional setup after loading the view. + } + + + @IBAction func selectFolder(_ sender: Any) { + + // Create a document picker for directories. + let documentPicker = + UIDocumentPickerViewController(forOpeningContentTypes: [.folder]) + documentPicker.delegate = self + + + // Set the initial directory. + documentPicker.directoryURL = startingDirectory + + + // Present the document picker. + present(documentPicker, animated: true, completion: nil) + } + + func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) { + // Start accessing a security-scoped resource. + guard url.startAccessingSecurityScopedResource() else { + // Handle the failure here. + return + } + + + // Make sure you release the security-scoped resource when you finish. + defer { url.stopAccessingSecurityScopedResource() } + + + // Use file coordination for reading and writing any of the URL’s content. + var error: NSError? = nil + NSFileCoordinator().coordinate(readingItemAt: url, error: &error) { (url) in + + let keys : [URLResourceKey] = [.nameKey, .isDirectoryKey] + + // Get an enumerator for the directory's content. + guard let fileList = + FileManager.default.enumerator(at: url, includingPropertiesForKeys: keys) else { + Swift.debugPrint("*** Unable to access the contents of \(url.path) ***\n") + return + } + + model?.resetStundent() + + for case let file as URL in fileList { + + + let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "network") + logger.debug("chosen file: \(file.relativeString)") + + let filename = file.lastPathComponent; + + if (filename.contains(".mp3") || filename.contains(".fseq") ){ + model?.setStudentAtIndex(model?.getStudentCount() ?? 0, withdraw: filename ) + } + + // Start accessing the content's security-scoped URL. + guard file.startAccessingSecurityScopedResource() else { + logger.error("Not accessing Security Scoped Ressource") + // Handle the failure here. + continue + } + + + // Do something with the file here. +// Swift.debugPrint("chosen file: \(file.lastPathComponent)") + + // Make sure you release the security-scoped resource when you finish. + file.stopAccessingSecurityScopedResource() + } + } + } + + +} + diff --git a/LightshowManager/en.lproj/Main.strings b/LightshowManager/en.lproj/Main.strings new file mode 100644 index 0000000..316ea40 --- /dev/null +++ b/LightshowManager/en.lproj/Main.strings @@ -0,0 +1,33 @@ + +/* Class = "UIButton"; configuration.title = "Télécharger des lightshows"; ObjectID = "F3I-Qt-ocD"; */ +"F3I-Qt-ocD.configuration.title" = "Télécharger des lightshows"; + +/* Class = "UIButton"; normalTitle = "Button"; ObjectID = "F3I-Qt-ocD"; */ +"F3I-Qt-ocD.normalTitle" = "Button"; + +/* Class = "UITabBarItem"; title = "Lightshow"; ObjectID = "PNd-MR-eNj"; */ +"PNd-MR-eNj.title" = "Lightshow"; + +/* Class = "UILabel"; text = "Ghostbuster"; ObjectID = "VB9-5v-hUx"; */ +"VB9-5v-hUx.text" = "Ghostbuster"; + +/* Class = "UIButton"; configuration.title = "Selectionner"; ObjectID = "a3c-YA-PpV"; */ +"a3c-YA-PpV.configuration.title" = "Selectionner"; + +/* Class = "UIButton"; normalTitle = "Button"; ObjectID = "a3c-YA-PpV"; */ +"a3c-YA-PpV.normalTitle" = "Button"; + +/* Class = "UILabel"; text = "Close Door"; ObjectID = "b5x-1u-uNl"; */ +"b5x-1u-uNl.text" = "Close Door"; + +/* Class = "UILabel"; text = "Choose your drive on popup"; ObjectID = "dWe-Wl-ozX"; */ +"dWe-Wl-ozX.text" = "Choose your drive on popup"; + +/* Class = "UIButton"; configuration.title = "Selectionner les lightshows à ajouter"; ObjectID = "kej-Ch-CaP"; */ +"kej-Ch-CaP.configuration.title" = "Selectionner les lightshows à ajouter"; + +/* Class = "UIButton"; normalTitle = "Button"; ObjectID = "kej-Ch-CaP"; */ +"kej-Ch-CaP.normalTitle" = "Button"; + +/* Class = "UITabBarItem"; title = "Close Sound"; ObjectID = "mv0-ae-zyi"; */ +"mv0-ae-zyi.title" = "Close Sound"; diff --git a/LightshowManagerTests/LightshowManagerTests.swift b/LightshowManagerTests/LightshowManagerTests.swift new file mode 100644 index 0000000..53d0a10 --- /dev/null +++ b/LightshowManagerTests/LightshowManagerTests.swift @@ -0,0 +1,36 @@ +// +// LightshowManagerTests.swift +// LightshowManagerTests +// +// Created by Quentin Millardet on 20/04/2024. +// + +import XCTest +@testable import LightshowManager + +final class LightshowManagerTests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/LightshowManagerUITests/LightshowManagerUITests.swift b/LightshowManagerUITests/LightshowManagerUITests.swift new file mode 100644 index 0000000..d2d0447 --- /dev/null +++ b/LightshowManagerUITests/LightshowManagerUITests.swift @@ -0,0 +1,41 @@ +// +// LightshowManagerUITests.swift +// LightshowManagerUITests +// +// Created by Quentin Millardet on 20/04/2024. +// + +import XCTest + +final class LightshowManagerUITests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = false + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // UI tests must launch the application that they test. + let app = XCUIApplication() + app.launch() + + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testLaunchPerformance() throws { + if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { + // This measures how long it takes to launch your application. + measure(metrics: [XCTApplicationLaunchMetric()]) { + XCUIApplication().launch() + } + } + } +} diff --git a/LightshowManagerUITests/LightshowManagerUITestsLaunchTests.swift b/LightshowManagerUITests/LightshowManagerUITestsLaunchTests.swift new file mode 100644 index 0000000..231cf01 --- /dev/null +++ b/LightshowManagerUITests/LightshowManagerUITestsLaunchTests.swift @@ -0,0 +1,32 @@ +// +// LightshowManagerUITestsLaunchTests.swift +// LightshowManagerUITests +// +// Created by Quentin Millardet on 20/04/2024. +// + +import XCTest + +final class LightshowManagerUITestsLaunchTests: XCTestCase { + + override class var runsForEachTargetApplicationUIConfiguration: Bool { + true + } + + override func setUpWithError() throws { + continueAfterFailure = false + } + + func testLaunch() throws { + let app = XCUIApplication() + app.launch() + + // Insert steps here to perform after app launch but before taking a screenshot, + // such as logging into a test account or navigating somewhere in the app + + let attachment = XCTAttachment(screenshot: app.screenshot()) + attachment.name = "Launch Screen" + attachment.lifetime = .keepAlways + add(attachment) + } +}