Contribute recording
This commit is contained in:
@@ -70,6 +70,7 @@
|
|||||||
545DDDD124436983003B6544 /* QuickUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 545DDDD024436983003B6544 /* QuickUI.swift */; };
|
545DDDD124436983003B6544 /* QuickUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 545DDDD024436983003B6544 /* QuickUI.swift */; };
|
||||||
545DDDD424466D37003B6544 /* AutoLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 545DDDD324466D37003B6544 /* AutoLayout.swift */; };
|
545DDDD424466D37003B6544 /* AutoLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 545DDDD324466D37003B6544 /* AutoLayout.swift */; };
|
||||||
546063E523FEFAFE008F505A /* DBCore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54B7562223D7B2DC008F0C41 /* DBCore.swift */; };
|
546063E523FEFAFE008F505A /* DBCore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54B7562223D7B2DC008F0C41 /* DBCore.swift */; };
|
||||||
|
54686A7624F8062C0084934D /* NotificationBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54686A7524F8062C0084934D /* NotificationBanner.swift */; };
|
||||||
54751E512423955100168273 /* URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54751E502423955000168273 /* URL.swift */; };
|
54751E512423955100168273 /* URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54751E502423955000168273 /* URL.swift */; };
|
||||||
54751E522423955100168273 /* URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54751E502423955000168273 /* URL.swift */; };
|
54751E522423955100168273 /* URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54751E502423955000168273 /* URL.swift */; };
|
||||||
54953E3323DC752E0054345C /* DBCore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54B7562223D7B2DC008F0C41 /* DBCore.swift */; };
|
54953E3323DC752E0054345C /* DBCore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54B7562223D7B2DC008F0C41 /* DBCore.swift */; };
|
||||||
@@ -268,6 +269,7 @@
|
|||||||
545DDDCE243E6267003B6544 /* TutorialSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TutorialSheet.swift; sourceTree = "<group>"; };
|
545DDDCE243E6267003B6544 /* TutorialSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TutorialSheet.swift; sourceTree = "<group>"; };
|
||||||
545DDDD024436983003B6544 /* QuickUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickUI.swift; sourceTree = "<group>"; };
|
545DDDD024436983003B6544 /* QuickUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickUI.swift; sourceTree = "<group>"; };
|
||||||
545DDDD324466D37003B6544 /* AutoLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoLayout.swift; sourceTree = "<group>"; };
|
545DDDD324466D37003B6544 /* AutoLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoLayout.swift; sourceTree = "<group>"; };
|
||||||
|
54686A7524F8062C0084934D /* NotificationBanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationBanner.swift; sourceTree = "<group>"; };
|
||||||
54751E502423955000168273 /* URL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URL.swift; sourceTree = "<group>"; };
|
54751E502423955000168273 /* URL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URL.swift; sourceTree = "<group>"; };
|
||||||
548B1F9423D338EC005B047C /* main.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = main.entitlements; sourceTree = "<group>"; };
|
548B1F9423D338EC005B047C /* main.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = main.entitlements; sourceTree = "<group>"; };
|
||||||
54953E5E23DEBE840054345C /* TVCDomains.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVCDomains.swift; sourceTree = "<group>"; };
|
54953E5E23DEBE840054345C /* TVCDomains.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVCDomains.swift; sourceTree = "<group>"; };
|
||||||
@@ -565,6 +567,7 @@
|
|||||||
541FC47524A12D01009154D8 /* IBViews.swift */,
|
541FC47524A12D01009154D8 /* IBViews.swift */,
|
||||||
5404AEEC24A95F3F003B2F54 /* SlideInAnimation.swift */,
|
5404AEEC24A95F3F003B2F54 /* SlideInAnimation.swift */,
|
||||||
541075D024CDBA0000D6F1BF /* ThrottledBatchQueue.swift */,
|
541075D024CDBA0000D6F1BF /* ThrottledBatchQueue.swift */,
|
||||||
|
54686A7524F8062C0084934D /* NotificationBanner.swift */,
|
||||||
);
|
);
|
||||||
path = "Common Classes";
|
path = "Common Classes";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -1017,6 +1020,7 @@
|
|||||||
54B345A6241BB982004C53CC /* Notifications.swift in Sources */,
|
54B345A6241BB982004C53CC /* Notifications.swift in Sources */,
|
||||||
54448A2E2486464F00771C96 /* Array.swift in Sources */,
|
54448A2E2486464F00771C96 /* Array.swift in Sources */,
|
||||||
54E67E4B24A8C6370025D261 /* GlassVPN.swift in Sources */,
|
54E67E4B24A8C6370025D261 /* GlassVPN.swift in Sources */,
|
||||||
|
54686A7624F8062C0084934D /* NotificationBanner.swift in Sources */,
|
||||||
541FC47824A1453F009154D8 /* VCCoOccurrence.swift in Sources */,
|
541FC47824A1453F009154D8 /* VCCoOccurrence.swift in Sources */,
|
||||||
54B345AB241BBA5B004C53CC /* AlertSheet.swift in Sources */,
|
54B345AB241BBA5B004C53CC /* AlertSheet.swift in Sources */,
|
||||||
541DCA6124A6B0F6005F1A4B /* Color.swift in Sources */,
|
541DCA6124A6B0F6005F1A4B /* Color.swift in Sources */,
|
||||||
|
|||||||
BIN
main/Assets.xcassets/.DS_Store
vendored
BIN
main/Assets.xcassets/.DS_Store
vendored
Binary file not shown.
26
main/Assets.xcassets/circle-check.imageset/Contents.json
vendored
Normal file
26
main/Assets.xcassets/circle-check.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "img.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "img@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "img@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
},
|
||||||
|
"properties" : {
|
||||||
|
"template-rendering-intent" : "template"
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
main/Assets.xcassets/circle-check.imageset/img.png
vendored
Normal file
BIN
main/Assets.xcassets/circle-check.imageset/img.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 247 B |
BIN
main/Assets.xcassets/circle-check.imageset/img@2x.png
vendored
Normal file
BIN
main/Assets.xcassets/circle-check.imageset/img@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 423 B |
BIN
main/Assets.xcassets/circle-check.imageset/img@3x.png
vendored
Normal file
BIN
main/Assets.xcassets/circle-check.imageset/img@3x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 572 B |
26
main/Assets.xcassets/circle-x.imageset/Contents.json
vendored
Normal file
26
main/Assets.xcassets/circle-x.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "img.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "img@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "img@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
},
|
||||||
|
"properties" : {
|
||||||
|
"template-rendering-intent" : "template"
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
main/Assets.xcassets/circle-x.imageset/img.png
vendored
Normal file
BIN
main/Assets.xcassets/circle-x.imageset/img.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 235 B |
BIN
main/Assets.xcassets/circle-x.imageset/img@2x.png
vendored
Normal file
BIN
main/Assets.xcassets/circle-x.imageset/img@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 400 B |
BIN
main/Assets.xcassets/circle-x.imageset/img@3x.png
vendored
Normal file
BIN
main/Assets.xcassets/circle-x.imageset/img@3x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 530 B |
63
main/Common Classes/NotificationBanner.swift
Normal file
63
main/Common Classes/NotificationBanner.swift
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import UIKit
|
||||||
|
|
||||||
|
struct NotificationBanner {
|
||||||
|
enum Style {
|
||||||
|
case fail, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
let view: UIView
|
||||||
|
|
||||||
|
init(_ msg: String, style: Style) {
|
||||||
|
let bg, fg: UIColor
|
||||||
|
let imgName: String
|
||||||
|
switch style {
|
||||||
|
case .fail:
|
||||||
|
bg = .systemRed
|
||||||
|
fg = UIColor.black.withAlphaComponent(0.80)
|
||||||
|
imgName = "circle-x"
|
||||||
|
case .ok:
|
||||||
|
bg = .systemGreen
|
||||||
|
fg = UIColor.black.withAlphaComponent(0.65)
|
||||||
|
imgName = "circle-check"
|
||||||
|
}
|
||||||
|
view = UIView()
|
||||||
|
view.backgroundColor = bg
|
||||||
|
let lbl = QuickUI.label(msg, style: .callout)
|
||||||
|
lbl.textColor = fg
|
||||||
|
lbl.numberOfLines = 0
|
||||||
|
lbl.font = lbl.font.bold()
|
||||||
|
let img = QuickUI.image(UIImage(named: imgName))
|
||||||
|
img.tintColor = fg
|
||||||
|
view.addSubview(lbl)
|
||||||
|
view.addSubview(img)
|
||||||
|
img.anchor([.leading, .centerY], to: view.layoutMarginsGuide)
|
||||||
|
lbl.anchor([.top, .bottom, .trailing], to: view.layoutMarginsGuide)
|
||||||
|
img.widthAnchor =&= 25
|
||||||
|
img.heightAnchor =&= 25
|
||||||
|
lbl.leadingAnchor =&= img.trailingAnchor + 8
|
||||||
|
img.bottomAnchor =<= view.bottomAnchor - 8
|
||||||
|
lbl.bottomAnchor =<= view.bottomAnchor - 8
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Animate header banner from the top of the view. Show for `delay` seconds and then hide again.
|
||||||
|
/// - Parameter onClose: Run after the close animation finishes.
|
||||||
|
func present(in vc: UIViewController, hideAfter delay: TimeInterval = 3, onClose: (() -> Void)? = nil) {
|
||||||
|
vc.view.addSubview(view)
|
||||||
|
view.anchor([.leading, .trailing], to: vc.view!)
|
||||||
|
vc.view.layoutIfNeeded() // sets the height
|
||||||
|
let h = view.frame.height
|
||||||
|
let constraint = view.topAnchor =&= vc.view.topAnchor - h
|
||||||
|
vc.view.layoutIfNeeded() // hide view
|
||||||
|
UIView.animate(withDuration: 0.3, animations: {
|
||||||
|
constraint.constant = 0
|
||||||
|
vc.view.layoutIfNeeded() // animate view
|
||||||
|
UIView.animate(withDuration: 0.3, delay: delay, options: .curveLinear, animations: {
|
||||||
|
constraint.constant = -h
|
||||||
|
vc.view.layoutIfNeeded() // hide again
|
||||||
|
}, completion: { _ in
|
||||||
|
self.view.removeFromSuperview()
|
||||||
|
onClose?()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,7 +33,9 @@ extension FilterOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension Recording {
|
extension Recording {
|
||||||
var fallbackTitle: String { get { "Unnamed Recording #\(id)" } }
|
var fallbackTitle: String { get {
|
||||||
|
isLongTerm ? "Background Recording" : "Unnamed Recording #\(id)"
|
||||||
|
} }
|
||||||
var duration: Timestamp? { get { stop == nil ? nil : stop! - start } }
|
var duration: Timestamp? { get { stop == nil ? nil : stop! - start } }
|
||||||
var isLongTerm: Bool { (duration ?? 0) > Timestamp.hours(1) }
|
var isLongTerm: Bool { (duration ?? 0) > Timestamp.hours(1) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,9 +39,13 @@ func AskAlert(title: String?, text: String?, buttonText: String = "Continue", bu
|
|||||||
|
|
||||||
/// Show alert hinting the user to go to system settings and re-enable notifications.
|
/// Show alert hinting the user to go to system settings and re-enable notifications.
|
||||||
func NotificationsDisabledAlert(presentIn viewController: UIViewController) {
|
func NotificationsDisabledAlert(presentIn viewController: UIViewController) {
|
||||||
Alert(title: "Notifications Disabled",
|
AskAlert(title: "Notifications Disabled",
|
||||||
text: "Go to System Settings > Notifications > AppCheck to re-enable notifications."
|
text: "Go to System Settings > Notifications > AppCheck to re-enable notifications.",
|
||||||
).presentIn(viewController)
|
buttonText: "Open settings") { _ in
|
||||||
|
if let url = URL(string: UIApplication.openSettingsURLString) {
|
||||||
|
UIApplication.shared.openURL(url)
|
||||||
|
}
|
||||||
|
}.presentIn(viewController)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Alert with multiple options
|
// MARK: Alert with multiple options
|
||||||
|
|||||||
@@ -260,7 +260,7 @@
|
|||||||
</barButtonItem>
|
</barButtonItem>
|
||||||
<barButtonItem key="rightBarButtonItem" title="Send" style="done" id="PWY-06-ykI">
|
<barButtonItem key="rightBarButtonItem" title="Send" style="done" id="PWY-06-ykI">
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="shareRecording" destination="P0a-ZP-uEV" id="lSZ-8V-ANw"/>
|
<action selector="shareRecording:" destination="P0a-ZP-uEV" id="vCR-9d-91D"/>
|
||||||
</connections>
|
</connections>
|
||||||
</barButtonItem>
|
</barButtonItem>
|
||||||
</navigationItem>
|
</navigationItem>
|
||||||
@@ -274,6 +274,9 @@
|
|||||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||||
</textView>
|
</textView>
|
||||||
|
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eWC-xB-CJe">
|
||||||
|
<rect key="frame" x="292" y="12" width="20" height="20"/>
|
||||||
|
</activityIndicatorView>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
@@ -283,11 +286,14 @@
|
|||||||
<constraint firstItem="dN0-a9-t4G" firstAttribute="leading" secondItem="lie-9P-DtH" secondAttribute="leading" id="BWF-aS-ah3"/>
|
<constraint firstItem="dN0-a9-t4G" firstAttribute="leading" secondItem="lie-9P-DtH" secondAttribute="leading" id="BWF-aS-ah3"/>
|
||||||
<constraint firstItem="lie-9P-DtH" firstAttribute="trailing" secondItem="fFm-v5-DGy" secondAttribute="trailing" id="GRg-BF-rYE"/>
|
<constraint firstItem="lie-9P-DtH" firstAttribute="trailing" secondItem="fFm-v5-DGy" secondAttribute="trailing" id="GRg-BF-rYE"/>
|
||||||
<constraint firstItem="lie-9P-DtH" firstAttribute="bottom" secondItem="fFm-v5-DGy" secondAttribute="bottom" id="IE3-o5-suZ"/>
|
<constraint firstItem="lie-9P-DtH" firstAttribute="bottom" secondItem="fFm-v5-DGy" secondAttribute="bottom" id="IE3-o5-suZ"/>
|
||||||
|
<constraint firstItem="eWC-xB-CJe" firstAttribute="trailing" secondItem="dN0-a9-t4G" secondAttribute="trailingMargin" id="NgN-7W-Ecm"/>
|
||||||
<constraint firstItem="lie-9P-DtH" firstAttribute="trailing" secondItem="dN0-a9-t4G" secondAttribute="trailing" id="UuJ-xj-xBK"/>
|
<constraint firstItem="lie-9P-DtH" firstAttribute="trailing" secondItem="dN0-a9-t4G" secondAttribute="trailing" id="UuJ-xj-xBK"/>
|
||||||
|
<constraint firstItem="eWC-xB-CJe" firstAttribute="centerY" secondItem="dN0-a9-t4G" secondAttribute="centerY" id="jvl-OA-Vdr"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<viewLayoutGuide key="safeArea" id="lie-9P-DtH"/>
|
<viewLayoutGuide key="safeArea" id="lie-9P-DtH"/>
|
||||||
</view>
|
</view>
|
||||||
<connections>
|
<connections>
|
||||||
|
<outlet property="sendActivity" destination="eWC-xB-CJe" id="rx3-Jz-ppT"/>
|
||||||
<outlet property="text" destination="fFm-v5-DGy" id="fwm-RE-gHu"/>
|
<outlet property="text" destination="fFm-v5-DGy" id="fwm-RE-gHu"/>
|
||||||
</connections>
|
</connections>
|
||||||
</viewController>
|
</viewController>
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ class TVCAppSearch: UITableViewController, UISearchBarDelegate {
|
|||||||
let alert = AskAlert(title: "App Name",
|
let alert = AskAlert(title: "App Name",
|
||||||
text: "Be as descriptive as possible. Preferably use app bundle id if available. Alternatively use app name or a link to a public repository.",
|
text: "Be as descriptive as possible. Preferably use app bundle id if available. Alternatively use app name or a link to a public repository.",
|
||||||
buttonText: "Set") {
|
buttonText: "Set") {
|
||||||
self.delegate?.appSearch(didSelect: "un.known", appName: $0.textFields?.first?.text, developer: nil)
|
self.delegate?.appSearch(didSelect: "_manually", appName: $0.textFields?.first?.text, developer: nil)
|
||||||
self.closeThis()
|
self.closeThis()
|
||||||
}
|
}
|
||||||
alert.addTextField { $0.placeholder = "com.apple.notes" }
|
alert.addTextField { $0.placeholder = "com.apple.notes" }
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class VCEditRecording: UIViewController, UITextFieldDelegate, UITextViewDelegate
|
|||||||
if record.isLongTerm {
|
if record.isLongTerm {
|
||||||
appId = nil
|
appId = nil
|
||||||
appIcon.image = nil
|
appIcon.image = nil
|
||||||
appTitle.text = "Background Recording"
|
appTitle.text = record.fallbackTitle
|
||||||
appDeveloper.text = nil
|
appDeveloper.text = nil
|
||||||
chooseAppTap.isEnabled = false
|
chooseAppTap.isEnabled = false
|
||||||
} else {
|
} else {
|
||||||
@@ -158,7 +158,7 @@ class VCEditRecording: UIViewController, UITextFieldDelegate, UITextViewDelegate
|
|||||||
|
|
||||||
private func validateSaveButton() {
|
private func validateSaveButton() {
|
||||||
let changed = (appId != record.appId
|
let changed = (appId != record.appId
|
||||||
|| (appTitle.text != record.title && appTitle.text != "Tap here to choose app")
|
|| (appTitle.text != record.title && appTitle.text != "Tap here to choose app" && appTitle.text != record.fallbackTitle)
|
||||||
|| appDeveloper.text != record.subtitle
|
|| appDeveloper.text != record.subtitle
|
||||||
|| inputNotes.text != record.notes ?? "")
|
|| inputNotes.text != record.notes ?? "")
|
||||||
buttonSave.isEnabled = changed || deleteOnCancel // always allow save for new recordings
|
buttonSave.isEnabled = changed || deleteOnCancel // always allow save for new recordings
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ class VCShareRecording : UIViewController {
|
|||||||
private var jsonData: Data?
|
private var jsonData: Data?
|
||||||
|
|
||||||
@IBOutlet private var text : UITextView!
|
@IBOutlet private var text : UITextView!
|
||||||
|
@IBOutlet private var sendActivity : UIActivityIndicatorView!
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
@@ -59,8 +60,68 @@ class VCShareRecording : UIViewController {
|
|||||||
dismiss(animated: true)
|
dismiss(animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction private func shareRecording() {
|
@IBAction private func shareRecording(_ sender: UIBarButtonItem) {
|
||||||
print("\(String(data: jsonData!, encoding: .utf8)!)")
|
sender.isEnabled = false
|
||||||
Alert(title: "Not implemented yet", text: nil).presentIn(self)
|
sendActivity.startAnimating()
|
||||||
|
|
||||||
|
let url = URL(string: "http://127.0.0.1/api/v1/contribute/")!
|
||||||
|
var request = URLRequest(url: url)
|
||||||
|
request.httpMethod = "POST"
|
||||||
|
request.httpBody = jsonData
|
||||||
|
|
||||||
|
URLSession.shared.dataTask(with: request) { data, response, error in
|
||||||
|
DispatchQueue.main.async { [weak self] in
|
||||||
|
sender.isEnabled = true
|
||||||
|
self?.sendActivity.stopAnimating()
|
||||||
|
|
||||||
|
guard error == nil, let data = data,
|
||||||
|
let response = response as? HTTPURLResponse else {
|
||||||
|
self?.banner(.fail, "\(error?.localizedDescription ?? "Unkown error occurred")")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let json = (try? JSONSerialization.jsonObject(with: data, options: [])) as? [String: Any]
|
||||||
|
let status = json?["status"] as? String
|
||||||
|
let v = json?["v"] as? Int ?? 0
|
||||||
|
guard v > 0, (200 ... 299) ~= response.statusCode else {
|
||||||
|
QLog.Warning("Couldn't contribute: \(status ?? "unkown reason")")
|
||||||
|
self?.banner(.fail, "Server couldn't parse request.\nTry again later.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var autoHide = true
|
||||||
|
if v == 1, let urlStr = json?["url"] as? String {
|
||||||
|
let nextUpdateIn = json?["when"] as? Int
|
||||||
|
self?.showOpenResultsAlert(urlStr, when: nextUpdateIn)
|
||||||
|
autoHide = false
|
||||||
|
}
|
||||||
|
self?.banner(.ok, "Thank you for your contribution.",
|
||||||
|
autoHide ? { [weak self] in self?.closeView() } : nil)
|
||||||
|
}
|
||||||
|
}.resume()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func banner(_ style: NotificationBanner.Style, _ msg: String, _ closure: (() -> Void)? = nil) {
|
||||||
|
NotificationBanner(msg, style: style).present(in: self, onClose: closure)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func showOpenResultsAlert(_ urlStr: String, when: Int?) {
|
||||||
|
var msg = "Your contribution is being processed and will be available "
|
||||||
|
if let when = when {
|
||||||
|
if when < 61 {
|
||||||
|
msg += "in approx. \(when) sec. "
|
||||||
|
} else {
|
||||||
|
let fmt = TimeFormat.from(Timestamp(when))
|
||||||
|
msg += "in \(fmt) min. "
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
msg += "shortly. "
|
||||||
|
}
|
||||||
|
msg += "Open results webpage now?"
|
||||||
|
let alert = Alert(title: "Thank you", text: msg, buttonText: "Not now")
|
||||||
|
alert.addAction(UIAlertAction(title: "Show results", style: .default) { _ in
|
||||||
|
if let url = URL(string: urlStr) {
|
||||||
|
UIApplication.shared.openURL(url)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
alert.presentIn(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,6 +84,31 @@ br.vet
|
|||||||
br.vlog
|
br.vlog
|
||||||
br.wiki
|
br.wiki
|
||||||
br.zlg
|
br.zlg
|
||||||
|
co.a
|
||||||
|
co.b
|
||||||
|
co.com
|
||||||
|
co.edu
|
||||||
|
co.g
|
||||||
|
co.gov
|
||||||
|
co.inf
|
||||||
|
co.m
|
||||||
|
co.mil
|
||||||
|
co.net
|
||||||
|
co.ngo
|
||||||
|
co.nom
|
||||||
|
co.o
|
||||||
|
co.org
|
||||||
|
co.s
|
||||||
|
co.t
|
||||||
|
co.x
|
||||||
|
co.y
|
||||||
|
er.com
|
||||||
|
er.edu
|
||||||
|
er.gov
|
||||||
|
er.mil
|
||||||
|
er.net
|
||||||
|
er.org
|
||||||
|
er.ind
|
||||||
es.com
|
es.com
|
||||||
es.edu
|
es.edu
|
||||||
es.gob
|
es.gob
|
||||||
@@ -553,4 +578,4 @@ za.nom
|
|||||||
za.org
|
za.org
|
||||||
za.school
|
za.school
|
||||||
za.tm
|
za.tm
|
||||||
za.web
|
za.web
|
||||||
|
|||||||
Reference in New Issue
Block a user