From 647eca310fb3355f7bc168beb4b3d88eb59fb196 Mon Sep 17 00:00:00 2001 From: relikd Date: Mon, 6 Apr 2020 23:37:46 +0200 Subject: [PATCH] Previous recordings detail view template --- AppCheck.xcodeproj/project.pbxproj | 4 + main/Base.lproj/LaunchScreen.storyboard | 2 +- main/Base.lproj/Main.storyboard | 175 +++++++++++++++------- main/Recordings/TVCPreviousRecords.swift | 4 + main/Recordings/TVCRecordingDetails.swift | 29 ++++ main/Recordings/VCEditRecording.swift | 35 +++-- main/Recordings/VCRecordings.swift | 21 ++- 7 files changed, 197 insertions(+), 73 deletions(-) create mode 100644 main/Recordings/TVCRecordingDetails.swift diff --git a/AppCheck.xcodeproj/project.pbxproj b/AppCheck.xcodeproj/project.pbxproj index ca8b524..273538c 100644 --- a/AppCheck.xcodeproj/project.pbxproj +++ b/AppCheck.xcodeproj/project.pbxproj @@ -21,6 +21,7 @@ 543CDB2023EEE61900B7F323 /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 543CDB1F23EEE61900B7F323 /* PacketTunnelProvider.swift */; }; 543CDB2523EEE61900B7F323 /* GlassVPN.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 543CDB1D23EEE61900B7F323 /* GlassVPN.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 544C95262407B1C700AB89D0 /* SharedState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 544C95252407B1C700AB89D0 /* SharedState.swift */; }; + 5458EBC0243A3F2200CFEB15 /* TVCRecordingDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5458EBBF243A3F2200CFEB15 /* TVCRecordingDetails.swift */; }; 546063E523FEFAFE008F505A /* SQDB.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54B7562223D7B2DC008F0C41 /* SQDB.swift */; }; 54751E512423955100168273 /* FileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54751E502423955000168273 /* FileManager.swift */; }; 54751E522423955100168273 /* FileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54751E502423955000168273 /* FileManager.swift */; }; @@ -172,6 +173,7 @@ 543CDB2123EEE61900B7F323 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 543CDB2223EEE61900B7F323 /* GlassVPN.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = GlassVPN.entitlements; sourceTree = ""; }; 544C95252407B1C700AB89D0 /* SharedState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedState.swift; sourceTree = ""; }; + 5458EBBF243A3F2200CFEB15 /* TVCRecordingDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVCRecordingDetails.swift; sourceTree = ""; }; 54751E502423955000168273 /* FileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileManager.swift; sourceTree = ""; }; 548B1F9423D338EC005B047C /* main.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = main.entitlements; sourceTree = ""; }; 54953E5E23DEBE840054345C /* TVCDomains.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVCDomains.swift; sourceTree = ""; }; @@ -325,6 +327,7 @@ 540E677F242D2CF100871BBE /* VCRecordings.swift */, 540E67832433FAFE00871BBE /* TVCPreviousRecords.swift */, 540E67812433483D00871BBE /* VCEditRecording.swift */, + 5458EBBF243A3F2200CFEB15 /* TVCRecordingDetails.swift */, ); path = Recordings; sourceTree = ""; @@ -807,6 +810,7 @@ 54953E6F23E44CD00054345C /* TVCHostDetails.swift in Sources */, 54C056DD23E9EEF700214A3F /* BundleIcon.swift in Sources */, 542E2A982404973F001462DC /* TBCMain.swift in Sources */, + 5458EBC0243A3F2200CFEB15 /* TVCRecordingDetails.swift in Sources */, 541AC5D82399498A00A769D7 /* AppDelegate.swift in Sources */, 54B345992414F491004C53CC /* DBWrapper.swift in Sources */, 540E67822433483D00871BBE /* VCEditRecording.swift in Sources */, diff --git a/main/Base.lproj/LaunchScreen.storyboard b/main/Base.lproj/LaunchScreen.storyboard index 9a22346..0e1cb74 100644 --- a/main/Base.lproj/LaunchScreen.storyboard +++ b/main/Base.lproj/LaunchScreen.storyboard @@ -27,7 +27,7 @@ - + diff --git a/main/Base.lproj/Main.storyboard b/main/Base.lproj/Main.storyboard index 918c3d3..0d8a9dc 100644 --- a/main/Base.lproj/Main.storyboard +++ b/main/Base.lproj/Main.storyboard @@ -163,7 +163,7 @@ - + @@ -171,63 +171,74 @@ - + - + - - - + + - + + + + + + + - + - + - + + + + - + - + - + + + + @@ -235,10 +246,10 @@ - + - + - + - + @@ -407,26 +420,12 @@ - + - - - - - - - - - - - - + + + + @@ -442,6 +441,7 @@ + @@ -499,11 +499,31 @@ - + + + + + + + + + + + + + + + + + + + + + - + @@ -531,6 +551,9 @@ + + + @@ -538,20 +561,21 @@ + - + - + @@ -576,7 +600,7 @@ - + @@ -604,7 +628,7 @@ - + - + 1. Line 2. Line @@ -638,7 +662,7 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/main/Recordings/TVCPreviousRecords.swift b/main/Recordings/TVCPreviousRecords.swift index de2e257..c03e5ec 100644 --- a/main/Recordings/TVCPreviousRecords.swift +++ b/main/Recordings/TVCPreviousRecords.swift @@ -53,6 +53,10 @@ class TVCPreviousRecords: UITableViewController { let target = segue.destination as! VCEditRecording target.record = record target.deleteOnCancel = newlyCreated + } else if segue.identifier == "openRecordDetailsSegue" { + if let i = tableView.indexPathForSelectedRow { + (segue.destination as? TVCRecordingDetails)?.record = dataSource[i.row] + } } } diff --git a/main/Recordings/TVCRecordingDetails.swift b/main/Recordings/TVCRecordingDetails.swift new file mode 100644 index 0000000..cc3bfe9 --- /dev/null +++ b/main/Recordings/TVCRecordingDetails.swift @@ -0,0 +1,29 @@ +import UIKit + +class TVCRecordingDetails: UITableViewController { + var record: Recording! + private var dataSource: [(domain: String, count: Int)] = [ + ("apple.com", 3), + ("cdn.apple.com", 1) + ] + + override func viewDidLoad() { + title = record.title ?? record.fallbackTitle + // TODO: load db entries + } + + + // MARK: - Table View Data Source + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + dataSource.count + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "PreviousRecordDetailCell")! + let x = dataSource[indexPath.row] + cell.textLabel?.text = x.domain + cell.detailTextLabel?.text = "\(x.count)" + return cell + } +} diff --git a/main/Recordings/VCEditRecording.swift b/main/Recordings/VCEditRecording.swift index cfda235..53b9aa4 100644 --- a/main/Recordings/VCEditRecording.swift +++ b/main/Recordings/VCEditRecording.swift @@ -16,9 +16,9 @@ class VCEditRecording: UIViewController, UITextFieldDelegate, UITextViewDelegate inputTitle.text = record.title inputNotes.text = record.notes inputDetails.text = """ - Start:\t\t\(record.start.asDateTime()) - End:\t\t\(record.stop?.asDateTime() ?? "?") - Duration:\t\(record.durationString ?? "?") + Start: \(record.start.asDateTime()) + End: \(record.stop?.asDateTime() ?? "?") + Duration: \(record.durationString ?? "?") """ validateSaveButton() if deleteOnCancel { // mark as destructive @@ -28,13 +28,8 @@ class VCEditRecording: UIViewController, UITextFieldDelegate, UITextViewDelegate UIResponder.keyboardWillHideNotification.observe(call: #selector(keyboardWillHide), on: self) } - func textFieldDidChangeSelection(_ _: UITextField) { validateSaveButton() } - func textViewDidChange(_ _: UITextView) { validateSaveButton() } - private func validateSaveButton() { - let changed = (inputTitle.text != record.title ?? "" || inputNotes.text != record.notes ?? "") - buttonSave.isEnabled = changed || deleteOnCancel // always allow save for new recordings - } + // MARK: Save & Cancel Buttons @IBAction func didTapSave(_ sender: UIBarButtonItem) { if deleteOnCancel { // aka newly created @@ -63,13 +58,6 @@ class VCEditRecording: UIViewController, UITextFieldDelegate, UITextViewDelegate } } - func textFieldShouldReturn(_ textField: UITextField) -> Bool { - if textField == inputTitle { - return inputNotes.becomeFirstResponder() - } - return true - } - // MARK: Handle Keyboard & Notes Frame @@ -116,4 +104,19 @@ class VCEditRecording: UIViewController, UITextFieldDelegate, UITextViewDelegate noteBottom.constant = adjust ? view.frame.height - stack.frame.maxY - keyboardHeight : 0 } + + + // MARK: TextField & TextView Delegate + + func textFieldDidChangeSelection(_ _: UITextField) { validateSaveButton() } + func textViewDidChange(_ _: UITextView) { validateSaveButton() } + + private func validateSaveButton() { + let changed = (inputTitle.text != record.title ?? "" || inputNotes.text != record.notes ?? "") + buttonSave.isEnabled = changed || deleteOnCancel // always allow save for new recordings + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + textField == inputTitle ? inputNotes.becomeFirstResponder() : true + } } diff --git a/main/Recordings/VCRecordings.swift b/main/Recordings/VCRecordings.swift index 2778cee..3f0916a 100644 --- a/main/Recordings/VCRecordings.swift +++ b/main/Recordings/VCRecordings.swift @@ -1,13 +1,17 @@ import UIKit -class VCRecordings: UIViewController { +class VCRecordings: UIViewController, UINavigationControllerDelegate { private var currentRecording: Recording? private var recordingTimer: Timer? @IBOutlet private var timeLabel: UILabel! @IBOutlet private var startButton: UIButton! + @IBOutlet private var startNewRecView: UIView! + private var prevRecController: UINavigationController! override func viewDidLoad() { + prevRecController = (children.first as! UINavigationController) + prevRecController.delegate = self // Duplicate font attributes but set monospace let traits = timeLabel.font.fontDescriptor.object(forKey: .traits) as? [UIFontDescriptor.TraitKey: Any] ?? [:] let weight = traits[.weight] as? CGFloat ?? UIFont.Weight.regular.rawValue @@ -25,14 +29,25 @@ class VCRecordings: UIViewController { stopTimer(animate: false) } - @IBAction private func recordingButtonTapped(_ sender: UIButton) { + func navigationController(_ navigationController: UINavigationController, willShow vc: UIViewController, animated: Bool) { + let isRoot = (vc == navigationController.viewControllers.first) + UIView.animate(withDuration: 0.3) { + self.startNewRecView.isHidden = !isRoot // hide "new recording" if details open + } + } + + + // MARK: Start New Recording + + @IBAction private func startRecordingButtonTapped(_ sender: UIButton) { if recordingTimer == nil { currentRecording = DBWrp.recordingStartNew() startTimer(animate: true) } else { stopTimer(animate: true) DBWrp.recordingStopAll() - (children.first as! TVCPreviousRecords).stopRecording(currentRecording!) + prevRecController.popToRootViewController(animated: true) + (prevRecController.topViewController as! TVCPreviousRecords).stopRecording(currentRecording!) currentRecording = nil // otherwise it will restart } }