Răsfoiți Sursa

Merge pull request #425 from deltachat/voice_recording

voice recording
björn petersen 5 ani în urmă
părinte
comite
cf832e7dfd
37 a modificat fișierele cu 1680 adăugiri și 860 ștergeri
  1. 1 1
      Podfile
  2. 5 1
      Podfile.lock
  3. 5 1
      Pods/Manifest.lock
  4. 868 841
      Pods/Pods.xcodeproj/project.pbxproj
  5. 24 0
      Pods/SCSiriWaveformView/LICENSE
  6. 21 0
      Pods/SCSiriWaveformView/README.md
  7. 74 0
      Pods/SCSiriWaveformView/SCSiriWaveformView/SCSiriWaveformView.h
  8. 115 0
      Pods/SCSiriWaveformView/SCSiriWaveformView/SCSiriWaveformView.m
  9. 27 0
      Pods/Target Support Files/Pods-deltachat-ios/Pods-deltachat-ios-acknowledgements.markdown
  10. 33 0
      Pods/Target Support Files/Pods-deltachat-ios/Pods-deltachat-ios-acknowledgements.plist
  11. 2 0
      Pods/Target Support Files/Pods-deltachat-ios/Pods-deltachat-ios-frameworks.sh
  12. 4 4
      Pods/Target Support Files/Pods-deltachat-ios/Pods-deltachat-ios.debug.xcconfig
  13. 4 4
      Pods/Target Support Files/Pods-deltachat-ios/Pods-deltachat-ios.release.xcconfig
  14. 3 3
      Pods/Target Support Files/Pods-deltachat-iosTests/Pods-deltachat-iosTests.debug.xcconfig
  15. 3 3
      Pods/Target Support Files/Pods-deltachat-iosTests/Pods-deltachat-iosTests.release.xcconfig
  16. 26 0
      Pods/Target Support Files/SCSiriWaveformView/SCSiriWaveformView-Info.plist
  17. 5 0
      Pods/Target Support Files/SCSiriWaveformView/SCSiriWaveformView-dummy.m
  18. 12 0
      Pods/Target Support Files/SCSiriWaveformView/SCSiriWaveformView-prefix.pch
  19. 17 0
      Pods/Target Support Files/SCSiriWaveformView/SCSiriWaveformView-umbrella.h
  20. 6 0
      Pods/Target Support Files/SCSiriWaveformView/SCSiriWaveformView.modulemap
  21. 10 0
      Pods/Target Support Files/SCSiriWaveformView/SCSiriWaveformView.xcconfig
  22. 6 0
      deltachat-ios.xcodeproj/project.pbxproj
  23. 23 0
      deltachat-ios/Assets.xcassets/audio_record.imageset/Contents.json
  24. BIN
      deltachat-ios/Assets.xcassets/audio_record.imageset/audio_record.png
  25. BIN
      deltachat-ios/Assets.xcassets/audio_record.imageset/audio_record@2x.png
  26. BIN
      deltachat-ios/Assets.xcassets/audio_record.imageset/audio_record@3x.png
  27. 6 0
      deltachat-ios/Assets.xcassets/ic_voice_chat_white_36dp/Contents.json
  28. 23 0
      deltachat-ios/Assets.xcassets/microphone_access.imageset/Contents.json
  29. BIN
      deltachat-ios/Assets.xcassets/microphone_access.imageset/microphone_access.png
  30. BIN
      deltachat-ios/Assets.xcassets/microphone_access.imageset/microphone_access@2x.png
  31. BIN
      deltachat-ios/Assets.xcassets/microphone_access.imageset/microphone_access@3x.png
  32. 293 0
      deltachat-ios/Controller/AudioRecorderController.swift
  33. 19 1
      deltachat-ios/Controller/ChatViewController.swift
  34. 4 0
      deltachat-ios/Coordinator/AppCoordinator.swift
  35. 13 0
      deltachat-ios/Extensions/String+Extension.swift
  36. 7 0
      deltachat-ios/Extensions/UIView+Extensions.swift
  37. 21 1
      deltachat-ios/Helper/MediaPicker.swift

+ 1 - 1
Podfile

@@ -17,7 +17,7 @@ target 'deltachat-ios' do
   pod 'SwiftyBeaver'
   pod 'DBDebugToolkit'
   pod 'InputBarAccessoryView'
-
+  pod 'SCSiriWaveformView'
   target 'deltachat-iosTests' do
     inherit! :search_paths
     # Pods for testing

+ 5 - 1
Podfile.lock

@@ -7,6 +7,7 @@ PODS:
   - JGProgressHUD (2.0.3)
   - QuickTableViewController (1.1.1)
   - ReachabilitySwift (4.3.1)
+  - SCSiriWaveformView (1.1.1)
   - SwiftFormat/CLI (0.40.9)
   - SwiftLint (0.32.0)
   - SwiftyBeaver (1.7.0)
@@ -19,6 +20,7 @@ DEPENDENCIES:
   - JGProgressHUD
   - QuickTableViewController
   - ReachabilitySwift
+  - SCSiriWaveformView
   - SwiftFormat/CLI
   - SwiftLint
   - SwiftyBeaver
@@ -32,6 +34,7 @@ SPEC REPOS:
     - JGProgressHUD
     - QuickTableViewController
     - ReachabilitySwift
+    - SCSiriWaveformView
     - SwiftFormat
     - SwiftLint
     - SwiftyBeaver
@@ -44,11 +47,12 @@ SPEC CHECKSUMS:
   JGProgressHUD: 12b20a8f4ffe05258f8635c1ab92816e451f904d
   QuickTableViewController: 30f689d314a7c1fb726c6dab6fa5ad53c6bc9e94
   ReachabilitySwift: 4032e2f59586e11e3b0ebe15b167abdd587a388b
+  SCSiriWaveformView: 15b9dd6f94c7536e2032b34a35c6ff74d38c7411
   SwiftFormat: 6b67b6e7fe73d664f0cbb4f13721f130462c86a5
   SwiftLint: 009a898ef2a1c851f45e1b59349bf6ff2ddc990d
   SwiftyBeaver: 4cc0080d2e23f980652e28978db11a5c9da39165
   UICircularProgressRing: 0ff679b05a17f15ad6301a7886686837b8c301a9
 
-PODFILE CHECKSUM: 37ab88c96ba5352ae1d3f997dc2615856fbd7e4c
+PODFILE CHECKSUM: 4fb877c35817d6aa88e7199c2635c724cfdcf87a
 
 COCOAPODS: 1.8.4

+ 5 - 1
Pods/Manifest.lock

@@ -7,6 +7,7 @@ PODS:
   - JGProgressHUD (2.0.3)
   - QuickTableViewController (1.1.1)
   - ReachabilitySwift (4.3.1)
+  - SCSiriWaveformView (1.1.1)
   - SwiftFormat/CLI (0.40.9)
   - SwiftLint (0.32.0)
   - SwiftyBeaver (1.7.0)
@@ -19,6 +20,7 @@ DEPENDENCIES:
   - JGProgressHUD
   - QuickTableViewController
   - ReachabilitySwift
+  - SCSiriWaveformView
   - SwiftFormat/CLI
   - SwiftLint
   - SwiftyBeaver
@@ -32,6 +34,7 @@ SPEC REPOS:
     - JGProgressHUD
     - QuickTableViewController
     - ReachabilitySwift
+    - SCSiriWaveformView
     - SwiftFormat
     - SwiftLint
     - SwiftyBeaver
@@ -44,11 +47,12 @@ SPEC CHECKSUMS:
   JGProgressHUD: 12b20a8f4ffe05258f8635c1ab92816e451f904d
   QuickTableViewController: 30f689d314a7c1fb726c6dab6fa5ad53c6bc9e94
   ReachabilitySwift: 4032e2f59586e11e3b0ebe15b167abdd587a388b
+  SCSiriWaveformView: 15b9dd6f94c7536e2032b34a35c6ff74d38c7411
   SwiftFormat: 6b67b6e7fe73d664f0cbb4f13721f130462c86a5
   SwiftLint: 009a898ef2a1c851f45e1b59349bf6ff2ddc990d
   SwiftyBeaver: 4cc0080d2e23f980652e28978db11a5c9da39165
   UICircularProgressRing: 0ff679b05a17f15ad6301a7886686837b8c301a9
 
-PODFILE CHECKSUM: 37ab88c96ba5352ae1d3f997dc2615856fbd7e4c
+PODFILE CHECKSUM: 4fb877c35817d6aa88e7199c2635c724cfdcf87a
 
 COCOAPODS: 1.8.4

Fișier diff suprimat deoarece este prea mare
+ 868 - 841
Pods/Pods.xcodeproj/project.pbxproj


+ 24 - 0
Pods/SCSiriWaveformView/LICENSE

@@ -0,0 +1,24 @@
+
+The MIT License (MIT)
+
+Copyright (c) [2013] [Stefan Ceriu]
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+        
+          

+ 21 - 0
Pods/SCSiriWaveformView/README.md

@@ -0,0 +1,21 @@
+## SCSiriWaveformView
+
+UIView subclass that reproduces the waveform effect seen in Siri on iOS 7.
+
+##### Screenshots
+
+![SCSiriWaveformView](https://drive.google.com/uc?export=download&id=0ByLCkUO90ltoSVloLXRKSC1DbEk)
+
+### Usage
+
+Check out the demo project for details.
+
+### Attributions
+A big thanks goes out to [Raffael Hannemann](https://twitter.com/raffael_me/) for his [SISinusWaveView](https://github.com/raffael/SISinusWaveView)
+
+### License
+SCSiriWaveformView is released under the MIT License (MIT) (see the LICENSE file)
+
+### Contact
+Any suggestions or improvements are more than welcome.<br>
+Feel free to contact me at [stefan.ceriu@yahoo.com](mailto:stefan.ceriu@yahoo.com) or [@stefanceriu](https://twitter.com/stefanceriu).

+ 74 - 0
Pods/SCSiriWaveformView/SCSiriWaveformView/SCSiriWaveformView.h

@@ -0,0 +1,74 @@
+//
+//  SCSiriWaveformView.h
+//  SCSiriWaveformView
+//
+//  Created by Stefan Ceriu on 12/04/2014.
+//  Copyright (c) 2014 Stefan Ceriu. All rights reserved.
+//
+
+@import UIKit;
+
+IB_DESIGNABLE
+@interface SCSiriWaveformView : UIView
+
+/*
+ * Tells the waveform to redraw itself using the given level (normalized value)
+ */
+- (void)updateWithLevel:(CGFloat)level;
+
+/*
+ * The total number of waves
+ * Default: 5
+ */
+@property (nonatomic, assign) NSUInteger numberOfWaves;
+
+/*
+ * Color to use when drawing the waves
+ * Default: white
+ */
+@property (nonatomic, strong) IBInspectable UIColor *waveColor;
+
+/*
+ * Line width used for the proeminent wave
+ * Default: 3.0f
+ */
+@property (nonatomic, assign)  IBInspectable CGFloat primaryWaveLineWidth;
+
+/*
+ * Line width used for all secondary waves
+ * Default: 1.0f
+ */
+@property (nonatomic, assign) IBInspectable CGFloat secondaryWaveLineWidth;
+
+/*
+ * The amplitude that is used when the incoming amplitude is near zero.
+ * Setting a value greater 0 provides a more vivid visualization.
+ * Default: 0.01
+ */
+@property (nonatomic, assign) IBInspectable CGFloat idleAmplitude;
+
+/*
+ * The frequency of the sinus wave. The higher the value, the more sinus wave peaks you will have.
+ * Default: 1.5
+ */
+@property (nonatomic, assign) IBInspectable CGFloat frequency;
+
+/*
+ * The current amplitude
+ */
+@property (nonatomic, assign, readonly) IBInspectable CGFloat amplitude;
+
+/*
+ * The lines are joined stepwise, the more dense you draw, the more CPU power is used.
+ * Default: 5
+ */
+@property (nonatomic, assign) IBInspectable CGFloat density;
+
+/*
+ * The phase shift that will be applied with each level setting
+ * Change this to modify the animation speed or direction
+ * Default: -0.15
+ */
+@property (nonatomic, assign) IBInspectable CGFloat phaseShift;
+
+@end

+ 115 - 0
Pods/SCSiriWaveformView/SCSiriWaveformView/SCSiriWaveformView.m

@@ -0,0 +1,115 @@
+//
+//  SCSiriWaveformView.m
+//  SCSiriWaveformView
+//
+//  Created by Stefan Ceriu on 12/04/2014.
+//  Copyright (c) 2014 Stefan Ceriu. All rights reserved.
+//
+
+#import "SCSiriWaveformView.h"
+
+static const CGFloat kDefaultFrequency          = 1.5f;
+static const CGFloat kDefaultAmplitude          = 1.0f;
+static const CGFloat kDefaultIdleAmplitude      = 0.01f;
+static const CGFloat kDefaultNumberOfWaves      = 5.0f;
+static const CGFloat kDefaultPhaseShift         = -0.15f;
+static const CGFloat kDefaultDensity            = 5.0f;
+static const CGFloat kDefaultPrimaryLineWidth   = 3.0f;
+static const CGFloat kDefaultSecondaryLineWidth = 1.0f;
+
+@interface SCSiriWaveformView ()
+
+@property (nonatomic, assign) CGFloat phase;
+@property (nonatomic, assign) CGFloat amplitude;
+
+@end
+
+@implementation SCSiriWaveformView
+
+- (instancetype)initWithFrame:(CGRect)frame
+{
+	if (self = [super initWithFrame:frame]) {
+		[self setup];
+	}
+	
+	return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder
+{
+	if (self = [super initWithCoder:aDecoder]) {
+		[self setup];
+	}
+	
+	return self;
+}
+
+- (void)setup
+{
+	self.waveColor = [UIColor whiteColor];
+	
+	self.frequency = kDefaultFrequency;
+	
+	self.amplitude = kDefaultAmplitude;
+	self.idleAmplitude = kDefaultIdleAmplitude;
+	
+	self.numberOfWaves = kDefaultNumberOfWaves;
+	self.phaseShift = kDefaultPhaseShift;
+	self.density = kDefaultDensity;
+	
+	self.primaryWaveLineWidth = kDefaultPrimaryLineWidth;
+	self.secondaryWaveLineWidth = kDefaultSecondaryLineWidth;
+}
+
+- (void)updateWithLevel:(CGFloat)level
+{
+	self.phase += self.phaseShift;
+	self.amplitude = fmax(level, self.idleAmplitude);
+	
+	[self setNeedsDisplay];
+}
+
+// Thanks to Raffael Hannemann https://github.com/raffael/SISinusWaveView
+- (void)drawRect:(CGRect)rect
+{
+	CGContextRef context = UIGraphicsGetCurrentContext();
+	CGContextClearRect(context, self.bounds);
+	
+	[self.backgroundColor set];
+	CGContextFillRect(context, rect);
+	
+	// We draw multiple sinus waves, with equal phases but altered amplitudes, multiplied by a parable function.
+	for (int i = 0; i < self.numberOfWaves; i++) {
+		CGFloat strokeLineWidth = (i == 0 ? self.primaryWaveLineWidth : self.secondaryWaveLineWidth);
+		CGContextSetLineWidth(context, strokeLineWidth);
+		
+		CGFloat halfHeight = CGRectGetHeight(self.bounds) / 2.0f;
+		CGFloat width = CGRectGetWidth(self.bounds);
+		CGFloat mid = width / 2.0f;
+		
+		const CGFloat maxAmplitude = halfHeight - (strokeLineWidth * 2);
+		
+		CGFloat progress = 1.0f - (CGFloat)i / self.numberOfWaves;
+		CGFloat normedAmplitude = (1.5f * progress - (2.0f / self.numberOfWaves)) * self.amplitude;
+		
+		CGFloat multiplier = MIN(1.0, (progress / 3.0f * 2.0f) + (1.0f / 3.0f));
+		[[self.waveColor colorWithAlphaComponent:multiplier * CGColorGetAlpha(self.waveColor.CGColor)] set];
+		
+		for (CGFloat x = 0; x < (width + self.density); x += self.density) {
+			// We use a parable to scale the sinus wave, that has its peak in the middle of the view.
+			CGFloat scaling = -pow(1 / mid * (x - mid), 2) + 1;
+			
+			CGFloat y = scaling * maxAmplitude * normedAmplitude * sinf(2 * M_PI *(x / width) * self.frequency + self.phase) + halfHeight;
+			
+			if (x == 0) {
+				CGContextMoveToPoint(context, x, y);
+			} else {
+				CGContextAddLineToPoint(context, x, y);
+			}
+		}
+		
+		CGContextStrokePath(context);
+	}
+}
+
+@end

+ 27 - 0
Pods/Target Support Files/Pods-deltachat-ios/Pods-deltachat-ios-acknowledgements.markdown

@@ -148,6 +148,33 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 
 
+## SCSiriWaveformView
+
+
+The MIT License (MIT)
+
+Copyright (c) [2013] [Stefan Ceriu]
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+        
+          
+
 ## SwiftFormat
 
 MIT License

+ 33 - 0
Pods/Target Support Files/Pods-deltachat-ios/Pods-deltachat-ios-acknowledgements.plist

@@ -195,6 +195,39 @@ THE SOFTWARE.
 			<key>Type</key>
 			<string>PSGroupSpecifier</string>
 		</dict>
+		<dict>
+			<key>FooterText</key>
+			<string>
+The MIT License (MIT)
+
+Copyright (c) [2013] [Stefan Ceriu]
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+        
+          </string>
+			<key>License</key>
+			<string>MIT License</string>
+			<key>Title</key>
+			<string>SCSiriWaveformView</string>
+			<key>Type</key>
+			<string>PSGroupSpecifier</string>
+		</dict>
 		<dict>
 			<key>FooterText</key>
 			<string>MIT License

+ 2 - 0
Pods/Target Support Files/Pods-deltachat-ios/Pods-deltachat-ios-frameworks.sh

@@ -167,6 +167,7 @@ if [[ "$CONFIGURATION" == "Debug" ]]; then
   install_framework "${BUILT_PRODUCTS_DIR}/JGProgressHUD/JGProgressHUD.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/QuickTableViewController/QuickTableViewController.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/ReachabilitySwift/Reachability.framework"
+  install_framework "${BUILT_PRODUCTS_DIR}/SCSiriWaveformView/SCSiriWaveformView.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/SwiftyBeaver/SwiftyBeaver.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/UICircularProgressRing/UICircularProgressRing.framework"
 fi
@@ -177,6 +178,7 @@ if [[ "$CONFIGURATION" == "Release" ]]; then
   install_framework "${BUILT_PRODUCTS_DIR}/JGProgressHUD/JGProgressHUD.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/QuickTableViewController/QuickTableViewController.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/ReachabilitySwift/Reachability.framework"
+  install_framework "${BUILT_PRODUCTS_DIR}/SCSiriWaveformView/SCSiriWaveformView.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/SwiftyBeaver/SwiftyBeaver.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/UICircularProgressRing/UICircularProgressRing.framework"
 fi

+ 4 - 4
Pods/Target Support Files/Pods-deltachat-ios/Pods-deltachat-ios.debug.xcconfig

@@ -1,10 +1,10 @@
 ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
-FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController" "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit" "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView" "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController" "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver" "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing"
+FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController" "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit" "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView" "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController" "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift" "${PODS_CONFIGURATION_BUILD_DIR}/SCSiriWaveformView" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver" "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing"
 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
-HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController/ALCameraViewController.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit/DBDebugToolkit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView/InputBarAccessoryView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD/JGProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController/QuickTableViewController.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift/Reachability.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver/SwiftyBeaver.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing/UICircularProgressRing.framework/Headers"
+HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController/ALCameraViewController.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit/DBDebugToolkit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView/InputBarAccessoryView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD/JGProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController/QuickTableViewController.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift/Reachability.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SCSiriWaveformView/SCSiriWaveformView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver/SwiftyBeaver.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing/UICircularProgressRing.framework/Headers"
 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
-OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController/ALCameraViewController.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit/DBDebugToolkit.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView/InputBarAccessoryView.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD/JGProgressHUD.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController/QuickTableViewController.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift/Reachability.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver/SwiftyBeaver.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing/UICircularProgressRing.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing"
-OTHER_LDFLAGS = $(inherited) -framework "ALCameraViewController" -framework "CoreTelephony" -framework "DBDebugToolkit" -framework "Foundation" -framework "InputBarAccessoryView" -framework "JGProgressHUD" -framework "QuartzCore" -framework "QuickTableViewController" -framework "Reachability" -framework "SwiftyBeaver" -framework "SystemConfiguration" -framework "UICircularProgressRing" -framework "UIKit"
+OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController/ALCameraViewController.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit/DBDebugToolkit.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView/InputBarAccessoryView.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD/JGProgressHUD.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController/QuickTableViewController.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift/Reachability.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/SCSiriWaveformView/SCSiriWaveformView.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver/SwiftyBeaver.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing/UICircularProgressRing.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/SCSiriWaveformView" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing"
+OTHER_LDFLAGS = $(inherited) -framework "ALCameraViewController" -framework "AVFoundation" -framework "CoreGraphics" -framework "CoreTelephony" -framework "DBDebugToolkit" -framework "Foundation" -framework "InputBarAccessoryView" -framework "JGProgressHUD" -framework "QuartzCore" -framework "QuickTableViewController" -framework "Reachability" -framework "SCSiriWaveformView" -framework "SwiftyBeaver" -framework "SystemConfiguration" -framework "UICircularProgressRing" -framework "UIKit"
 OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
 PODS_BUILD_DIR = ${BUILD_DIR}
 PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)

+ 4 - 4
Pods/Target Support Files/Pods-deltachat-ios/Pods-deltachat-ios.release.xcconfig

@@ -1,10 +1,10 @@
 ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
-FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController" "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit" "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView" "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController" "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver" "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing"
+FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController" "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit" "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView" "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController" "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift" "${PODS_CONFIGURATION_BUILD_DIR}/SCSiriWaveformView" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver" "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing"
 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
-HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController/ALCameraViewController.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit/DBDebugToolkit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView/InputBarAccessoryView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD/JGProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController/QuickTableViewController.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift/Reachability.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver/SwiftyBeaver.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing/UICircularProgressRing.framework/Headers"
+HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController/ALCameraViewController.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit/DBDebugToolkit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView/InputBarAccessoryView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD/JGProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController/QuickTableViewController.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift/Reachability.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SCSiriWaveformView/SCSiriWaveformView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver/SwiftyBeaver.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing/UICircularProgressRing.framework/Headers"
 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
-OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController/ALCameraViewController.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit/DBDebugToolkit.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView/InputBarAccessoryView.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD/JGProgressHUD.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController/QuickTableViewController.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift/Reachability.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver/SwiftyBeaver.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing/UICircularProgressRing.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing"
-OTHER_LDFLAGS = $(inherited) -framework "ALCameraViewController" -framework "CoreTelephony" -framework "DBDebugToolkit" -framework "Foundation" -framework "InputBarAccessoryView" -framework "JGProgressHUD" -framework "QuartzCore" -framework "QuickTableViewController" -framework "Reachability" -framework "SwiftyBeaver" -framework "SystemConfiguration" -framework "UICircularProgressRing" -framework "UIKit"
+OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController/ALCameraViewController.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit/DBDebugToolkit.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView/InputBarAccessoryView.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD/JGProgressHUD.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController/QuickTableViewController.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift/Reachability.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/SCSiriWaveformView/SCSiriWaveformView.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver/SwiftyBeaver.framework/Headers" -isystem "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing/UICircularProgressRing.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/SCSiriWaveformView" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing"
+OTHER_LDFLAGS = $(inherited) -framework "ALCameraViewController" -framework "AVFoundation" -framework "CoreGraphics" -framework "CoreTelephony" -framework "DBDebugToolkit" -framework "Foundation" -framework "InputBarAccessoryView" -framework "JGProgressHUD" -framework "QuartzCore" -framework "QuickTableViewController" -framework "Reachability" -framework "SCSiriWaveformView" -framework "SwiftyBeaver" -framework "SystemConfiguration" -framework "UICircularProgressRing" -framework "UIKit"
 OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
 PODS_BUILD_DIR = ${BUILD_DIR}
 PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)

+ 3 - 3
Pods/Target Support Files/Pods-deltachat-iosTests/Pods-deltachat-iosTests.debug.xcconfig

@@ -1,7 +1,7 @@
-FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController" "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit" "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView" "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController" "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver" "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing"
+FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController" "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit" "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView" "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController" "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift" "${PODS_CONFIGURATION_BUILD_DIR}/SCSiriWaveformView" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver" "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing"
 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
-HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController/ALCameraViewController.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit/DBDebugToolkit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView/InputBarAccessoryView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD/JGProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController/QuickTableViewController.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift/Reachability.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver/SwiftyBeaver.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing/UICircularProgressRing.framework/Headers"
-OTHER_LDFLAGS = $(inherited) -framework "ALCameraViewController" -framework "CoreTelephony" -framework "DBDebugToolkit" -framework "Foundation" -framework "InputBarAccessoryView" -framework "JGProgressHUD" -framework "QuartzCore" -framework "QuickTableViewController" -framework "Reachability" -framework "SwiftyBeaver" -framework "SystemConfiguration" -framework "UICircularProgressRing" -framework "UIKit"
+HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController/ALCameraViewController.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit/DBDebugToolkit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView/InputBarAccessoryView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD/JGProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController/QuickTableViewController.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift/Reachability.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SCSiriWaveformView/SCSiriWaveformView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver/SwiftyBeaver.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing/UICircularProgressRing.framework/Headers"
+OTHER_LDFLAGS = $(inherited) -framework "ALCameraViewController" -framework "AVFoundation" -framework "CoreGraphics" -framework "CoreTelephony" -framework "DBDebugToolkit" -framework "Foundation" -framework "InputBarAccessoryView" -framework "JGProgressHUD" -framework "QuartzCore" -framework "QuickTableViewController" -framework "Reachability" -framework "SCSiriWaveformView" -framework "SwiftyBeaver" -framework "SystemConfiguration" -framework "UICircularProgressRing" -framework "UIKit"
 PODS_BUILD_DIR = ${BUILD_DIR}
 PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
 PODS_PODFILE_DIR_PATH = ${SRCROOT}/.

+ 3 - 3
Pods/Target Support Files/Pods-deltachat-iosTests/Pods-deltachat-iosTests.release.xcconfig

@@ -1,7 +1,7 @@
-FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController" "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit" "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView" "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController" "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver" "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing"
+FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController" "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit" "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView" "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController" "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift" "${PODS_CONFIGURATION_BUILD_DIR}/SCSiriWaveformView" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver" "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing"
 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
-HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController/ALCameraViewController.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit/DBDebugToolkit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView/InputBarAccessoryView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD/JGProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController/QuickTableViewController.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift/Reachability.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver/SwiftyBeaver.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing/UICircularProgressRing.framework/Headers"
-OTHER_LDFLAGS = $(inherited) -framework "ALCameraViewController" -framework "CoreTelephony" -framework "DBDebugToolkit" -framework "Foundation" -framework "InputBarAccessoryView" -framework "JGProgressHUD" -framework "QuartzCore" -framework "QuickTableViewController" -framework "Reachability" -framework "SwiftyBeaver" -framework "SystemConfiguration" -framework "UICircularProgressRing" -framework "UIKit"
+HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ALCameraViewController/ALCameraViewController.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DBDebugToolkit/DBDebugToolkit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/InputBarAccessoryView/InputBarAccessoryView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/JGProgressHUD/JGProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/QuickTableViewController/QuickTableViewController.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift/Reachability.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SCSiriWaveformView/SCSiriWaveformView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyBeaver/SwiftyBeaver.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/UICircularProgressRing/UICircularProgressRing.framework/Headers"
+OTHER_LDFLAGS = $(inherited) -framework "ALCameraViewController" -framework "AVFoundation" -framework "CoreGraphics" -framework "CoreTelephony" -framework "DBDebugToolkit" -framework "Foundation" -framework "InputBarAccessoryView" -framework "JGProgressHUD" -framework "QuartzCore" -framework "QuickTableViewController" -framework "Reachability" -framework "SCSiriWaveformView" -framework "SwiftyBeaver" -framework "SystemConfiguration" -framework "UICircularProgressRing" -framework "UIKit"
 PODS_BUILD_DIR = ${BUILD_DIR}
 PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
 PODS_PODFILE_DIR_PATH = ${SRCROOT}/.

+ 26 - 0
Pods/Target Support Files/SCSiriWaveformView/SCSiriWaveformView-Info.plist

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>en</string>
+  <key>CFBundleExecutable</key>
+  <string>${EXECUTABLE_NAME}</string>
+  <key>CFBundleIdentifier</key>
+  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>${PRODUCT_NAME}</string>
+  <key>CFBundlePackageType</key>
+  <string>FMWK</string>
+  <key>CFBundleShortVersionString</key>
+  <string>1.1.1</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>${CURRENT_PROJECT_VERSION}</string>
+  <key>NSPrincipalClass</key>
+  <string></string>
+</dict>
+</plist>

+ 5 - 0
Pods/Target Support Files/SCSiriWaveformView/SCSiriWaveformView-dummy.m

@@ -0,0 +1,5 @@
+#import <Foundation/Foundation.h>
+@interface PodsDummy_SCSiriWaveformView : NSObject
+@end
+@implementation PodsDummy_SCSiriWaveformView
+@end

+ 12 - 0
Pods/Target Support Files/SCSiriWaveformView/SCSiriWaveformView-prefix.pch

@@ -0,0 +1,12 @@
+#ifdef __OBJC__
+#import <UIKit/UIKit.h>
+#else
+#ifndef FOUNDATION_EXPORT
+#if defined(__cplusplus)
+#define FOUNDATION_EXPORT extern "C"
+#else
+#define FOUNDATION_EXPORT extern
+#endif
+#endif
+#endif
+

+ 17 - 0
Pods/Target Support Files/SCSiriWaveformView/SCSiriWaveformView-umbrella.h

@@ -0,0 +1,17 @@
+#ifdef __OBJC__
+#import <UIKit/UIKit.h>
+#else
+#ifndef FOUNDATION_EXPORT
+#if defined(__cplusplus)
+#define FOUNDATION_EXPORT extern "C"
+#else
+#define FOUNDATION_EXPORT extern
+#endif
+#endif
+#endif
+
+#import "SCSiriWaveformView.h"
+
+FOUNDATION_EXPORT double SCSiriWaveformViewVersionNumber;
+FOUNDATION_EXPORT const unsigned char SCSiriWaveformViewVersionString[];
+

+ 6 - 0
Pods/Target Support Files/SCSiriWaveformView/SCSiriWaveformView.modulemap

@@ -0,0 +1,6 @@
+framework module SCSiriWaveformView {
+  umbrella header "SCSiriWaveformView-umbrella.h"
+
+  export *
+  module * { export * }
+}

+ 10 - 0
Pods/Target Support Files/SCSiriWaveformView/SCSiriWaveformView.xcconfig

@@ -0,0 +1,10 @@
+CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SCSiriWaveformView
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+OTHER_LDFLAGS = $(inherited) -framework "AVFoundation" -framework "CoreGraphics" -framework "Foundation" -framework "QuartzCore" -framework "UIKit"
+PODS_BUILD_DIR = ${BUILD_DIR}
+PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
+PODS_ROOT = ${SRCROOT}
+PODS_TARGET_SRCROOT = ${PODS_ROOT}/SCSiriWaveformView
+PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
+SKIP_INSTALL = YES
+USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

+ 6 - 0
deltachat-ios.xcodeproj/project.pbxproj

@@ -10,6 +10,7 @@
 		300C509D234B551900F8AE22 /* TextMediaMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 300C509C234B551900F8AE22 /* TextMediaMessageCell.swift */; };
 		300C50A1234BDAB800F8AE22 /* TextMediaMessageSizeCalculator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 300C50A0234BDAB800F8AE22 /* TextMediaMessageSizeCalculator.swift */; };
 		30149D9322F21129003C12B5 /* QrViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30149D9222F21129003C12B5 /* QrViewController.swift */; };
+		3015634423A003BA00E9DEF4 /* AudioRecorderController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3015634323A003BA00E9DEF4 /* AudioRecorderController.swift */; };
 		3022E6BE22E8768800763272 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3022E6C022E8768800763272 /* InfoPlist.strings */; };
 		30260CA7238F02F700D8D52C /* MultilineTextFieldCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30260CA6238F02F700D8D52C /* MultilineTextFieldCell.swift */; };
 		302B84C6239676F0001C261F /* AvatarHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30AC265E237F1807002A943F /* AvatarHelper.swift */; };
@@ -164,6 +165,7 @@
 		300C509C234B551900F8AE22 /* TextMediaMessageCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextMediaMessageCell.swift; sourceTree = "<group>"; };
 		300C50A0234BDAB800F8AE22 /* TextMediaMessageSizeCalculator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextMediaMessageSizeCalculator.swift; sourceTree = "<group>"; };
 		30149D9222F21129003C12B5 /* QrViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QrViewController.swift; sourceTree = "<group>"; };
+		3015634323A003BA00E9DEF4 /* AudioRecorderController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRecorderController.swift; sourceTree = "<group>"; };
 		3022E6BF22E8768800763272 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
 		3022E6C122E8768C00763272 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = "<group>"; };
 		3022E6C222E8768E00763272 /* sq */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sq; path = sq.lproj/InfoPlist.strings; sourceTree = "<group>"; };
@@ -660,6 +662,7 @@
 		AE851AC0227C693B00ED86F0 /* Controller */ = {
 			isa = PBXGroup;
 			children = (
+				3015634323A003BA00E9DEF4 /* AudioRecorderController.swift */,
 				AE18F28B228C17630007B1BE /* AccountSetup */,
 				AEE56D752253431E007DC082 /* AccountSetupController.swift */,
 				AE0D26FC1FB1FE88002FAFCE /* ChatListController.swift */,
@@ -908,6 +911,7 @@
 				"${BUILT_PRODUCTS_DIR}/JGProgressHUD/JGProgressHUD.framework",
 				"${BUILT_PRODUCTS_DIR}/QuickTableViewController/QuickTableViewController.framework",
 				"${BUILT_PRODUCTS_DIR}/ReachabilitySwift/Reachability.framework",
+				"${BUILT_PRODUCTS_DIR}/SCSiriWaveformView/SCSiriWaveformView.framework",
 				"${BUILT_PRODUCTS_DIR}/SwiftyBeaver/SwiftyBeaver.framework",
 				"${BUILT_PRODUCTS_DIR}/UICircularProgressRing/UICircularProgressRing.framework",
 			);
@@ -919,6 +923,7 @@
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/JGProgressHUD.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/QuickTableViewController.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Reachability.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SCSiriWaveformView.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyBeaver.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/UICircularProgressRing.framework",
 			);
@@ -1069,6 +1074,7 @@
 				305961E52346125100C80F33 /* LabelAlignment.swift in Sources */,
 				305961E82346125100C80F33 /* Sender.swift in Sources */,
 				305961EE2346125100C80F33 /* AvatarPosition.swift in Sources */,
+				3015634423A003BA00E9DEF4 /* AudioRecorderController.swift in Sources */,
 				AE25F09022807AD800CDEA66 /* AvatarSelectionCell.swift in Sources */,
 				302B84C6239676F0001C261F /* AvatarHelper.swift in Sources */,
 				305961E62346125100C80F33 /* LocationMessageSnapshotOptions.swift in Sources */,

+ 23 - 0
deltachat-ios/Assets.xcassets/audio_record.imageset/Contents.json

@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "audio_record.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "audio_record@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "audio_record@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

BIN
deltachat-ios/Assets.xcassets/audio_record.imageset/audio_record.png


BIN
deltachat-ios/Assets.xcassets/audio_record.imageset/audio_record@2x.png


BIN
deltachat-ios/Assets.xcassets/audio_record.imageset/audio_record@3x.png


+ 6 - 0
deltachat-ios/Assets.xcassets/ic_voice_chat_white_36dp/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

+ 23 - 0
deltachat-ios/Assets.xcassets/microphone_access.imageset/Contents.json

@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "microphone_access.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "microphone_access@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "microphone_access@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

BIN
deltachat-ios/Assets.xcassets/microphone_access.imageset/microphone_access.png


BIN
deltachat-ios/Assets.xcassets/microphone_access.imageset/microphone_access@2x.png


BIN
deltachat-ios/Assets.xcassets/microphone_access.imageset/microphone_access@3x.png


+ 293 - 0
deltachat-ios/Controller/AudioRecorderController.swift

@@ -0,0 +1,293 @@
+import Foundation
+import SCSiriWaveformView
+import AVKit
+
+protocol AudioRecorderControllerDelegate: class {
+    func didFinishAudioAtPath(path: String)
+}
+
+class AudioRecorderController: UIViewController, AVAudioRecorderDelegate {
+
+    weak var delegate: AudioRecorderControllerDelegate?
+
+    //Recording...
+    var meterUpdateDisplayLink: CADisplayLink?
+    var isRecordingPaused: Bool = false
+
+    // maximumRecordDuration > 0 -> restrict max time period for one take
+    var maximumRecordDuration = 0.0
+
+    //Private variables
+    var oldSessionCategory: AVAudioSession.Category?
+    var wasIdleTimerDisabled: Bool = false
+
+    var recordingFilePath: String = ""
+    var audioRecorder: AVAudioRecorder?
+
+    var normalTintColor: UIColor = UIColor.sendButtonBlue
+    var highlightedTintColor = UIColor.red
+
+    var isFirstUsage: Bool = true
+
+    lazy var waveFormView: SCSiriWaveformView = {
+        let view = SCSiriWaveformView()
+        view.alpha = 1.0
+        view.backgroundColor = .clear
+        view.translatesAutoresizingMaskIntoConstraints = false
+        view.primaryWaveLineWidth = 3.0
+        view.secondaryWaveLineWidth = 1.0
+        return view
+    }()
+
+    lazy var noRecordingPermissionView: UIImageView = {
+        let view = UIImageView(image: UIImage(named: "microphone_access"))
+        view.translatesAutoresizingMaskIntoConstraints = false
+        view.alpha = 0.0
+        view.contentMode = UIView.ContentMode.scaleAspectFit
+        return view
+    }()
+
+    var navigationTitle: NSString?
+
+    lazy var cancelButton: UIBarButtonItem = {
+        let button = UIBarButtonItem.init(barButtonSystemItem: UIBarButtonItem.SystemItem.cancel,
+                                          target: self,
+                                          action: #selector(cancelAction))
+        return button
+    }()
+
+    lazy var doneButton: UIBarButtonItem = {
+        let button = UIBarButtonItem.init(barButtonSystemItem: UIBarButtonItem.SystemItem.done,
+                                          target: self,
+                                          action: #selector(doneAction))
+        return button
+    }()
+
+    lazy var cancelRecordingButton: UIBarButtonItem = {
+        let button = UIBarButtonItem.init(barButtonSystemItem: UIBarButtonItem.SystemItem.cancel,
+                                                 target: self,
+                                                 action: #selector(cancelRecordingAction))
+        button.tintColor = highlightedTintColor
+        return button
+    }()
+
+    lazy var pauseButton: UIBarButtonItem = {
+        let button = UIBarButtonItem.init(barButtonSystemItem: UIBarButtonItem.SystemItem.pause,
+                                          target: self,
+                                          action: #selector(pauseRecordingButtonAction))
+        button.tintColor = highlightedTintColor
+        return button
+    }()
+
+    lazy var startRecordingButton: UIBarButtonItem = {
+        let button =  UIBarButtonItem.init(image: UIImage(named: "audio_record"),
+                                           style: UIBarButtonItem.Style.plain,
+                                           target: self,
+                                           action: #selector(recordingButtonAction))
+        button.tintColor = normalTintColor
+        return button
+    }()
+
+    lazy var continueRecordingButton: UIBarButtonItem = {
+        let button = UIBarButtonItem.init(image: UIImage(named: "audio_record"),
+                                          style: UIBarButtonItem.Style.plain,
+                                          target: self,
+                                          action: #selector(continueRecordingButtonAction))
+        button.tintColor = highlightedTintColor
+        return button
+    }()
+
+    lazy var flexItem = {
+        return UIBarButtonItem.init(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)
+    }()
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        self.view.backgroundColor = UIColor.themeColor(light: .white, dark: .black)
+        self.navigationController?.isToolbarHidden = false
+        self.navigationController?.toolbar.isTranslucent = true
+        self.navigationController?.navigationBar.isTranslucent = true
+
+        self.navigationItem.title = String.localized("voice_message")
+        self.navigationItem.leftBarButtonItem = cancelButton
+        self.navigationItem.rightBarButtonItem = doneButton
+        waveFormView.frame = self.view.bounds
+        self.view.addSubview(waveFormView)
+        self.view.addSubview(noRecordingPermissionView)
+
+        waveFormView.fill(view: view)
+        noRecordingPermissionView.fill(view: view, paddingLeading: 100, paddingTrailing: 100, paddingTop: 200, paddingBottom: 200)
+
+        self.navigationController?.toolbar.tintColor = normalTintColor
+        self.navigationController?.navigationBar.tintColor = normalTintColor
+        self.navigationController?.navigationBar.isTranslucent = true
+        self.navigationController?.toolbar.isTranslucent = true
+
+        //Define the recorder setting
+        let recordSettings = [AVFormatIDKey: kAudioFormatMPEG4AAC,
+                              AVSampleRateKey: 44100.0,
+                              AVNumberOfChannelsKey: 1] as [String: Any]
+        let globallyUniqueString = ProcessInfo.processInfo.globallyUniqueString
+        recordingFilePath = NSTemporaryDirectory().appending(globallyUniqueString).appending(".m4a")
+        _ = try? audioRecorder = AVAudioRecorder.init(url: URL(fileURLWithPath: recordingFilePath), settings: recordSettings)
+        audioRecorder?.delegate = self
+        audioRecorder?.isMeteringEnabled = true
+    }
+
+
+    override func viewWillAppear(_ animated: Bool) {
+        super.viewWillAppear(animated)
+
+        startUpdatingMeter()
+
+        wasIdleTimerDisabled = UIApplication.shared.isIdleTimerDisabled
+        NotificationCenter.default.addObserver(self,
+                                               selector: #selector(didBecomeActiveNotification),
+                                               name: UIApplication.didBecomeActiveNotification,
+                                               object: nil)
+        validateMicrophoneAccess()
+    }
+
+    override func viewWillDisappear(_ animated: Bool) {
+        super.viewWillDisappear(animated)
+
+        NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)
+        audioRecorder?.delegate = nil
+        audioRecorder?.stop()
+        audioRecorder = nil
+        stopUpdatingMeter()
+        UIApplication.shared.isIdleTimerDisabled = wasIdleTimerDisabled
+    }
+
+    func startUpdatingMeter() {
+        meterUpdateDisplayLink?.invalidate()
+        meterUpdateDisplayLink = CADisplayLink.init(target: self, selector: #selector(updateMeters))
+        meterUpdateDisplayLink?.add(to: RunLoop.current, forMode: RunLoop.Mode.common)
+    }
+
+    func stopUpdatingMeter() {
+        meterUpdateDisplayLink?.invalidate()
+        meterUpdateDisplayLink = nil
+    }
+
+    @objc func updateMeters() {
+        if let audioRecorder = audioRecorder {
+            if audioRecorder.isRecording || isRecordingPaused {
+                audioRecorder.updateMeters()
+                let normalizedValue: Float = pow(10, audioRecorder.averagePower(forChannel: 0) / 20)
+                waveFormView.waveColor = highlightedTintColor
+                waveFormView.update(withLevel: CGFloat(normalizedValue))
+                self.navigationItem.title = String.timeStringForInterval(audioRecorder.currentTime)
+            } else {
+                waveFormView.waveColor = normalTintColor
+                waveFormView.update(withLevel: 0)
+            }
+        }
+    }
+
+    @objc func recordingButtonAction() {
+        logger.debug("start recording")
+        self.setToolbarItems([flexItem, pauseButton, flexItem], animated: true)
+        self.navigationItem.setLeftBarButton(cancelRecordingButton, animated: true)
+        if FileManager.default.fileExists(atPath: recordingFilePath) {
+            _ = try? FileManager.default.removeItem(atPath: recordingFilePath)
+        }
+        let session = AVAudioSession.sharedInstance()
+        oldSessionCategory = session.category
+        _ = try? session.setCategory(AVAudioSession.Category.record)
+        UIApplication.shared.isIdleTimerDisabled = true
+        audioRecorder?.prepareToRecord()
+        isRecordingPaused = false
+
+        if maximumRecordDuration <= 0 {
+            audioRecorder?.record()
+        } else {
+            audioRecorder?.record(forDuration: maximumRecordDuration)
+        }
+    }
+
+    @objc func continueRecordingButtonAction() {
+        logger.debug("continue recording")
+        self.setToolbarItems([flexItem, pauseButton, flexItem], animated: true)
+        isRecordingPaused = false
+        audioRecorder?.record()
+    }
+
+    @objc func pauseRecordingButtonAction() {
+        logger.debug("pause")
+        isRecordingPaused = true
+        audioRecorder?.pause()
+        self.setToolbarItems([flexItem, continueRecordingButton, flexItem], animated: true)
+    }
+
+    @objc func cancelRecordingAction() {
+        logger.debug("cancel recording")
+        isRecordingPaused = false
+        audioRecorder?.stop()
+        _ = try? FileManager.default.removeItem(atPath: recordingFilePath)
+        self.navigationItem.title = String.localized("voice_message")
+    }
+
+    @objc func cancelAction() {
+        logger.debug("cancel Action")
+        dismiss(animated: true, completion: nil)
+    }
+
+    @objc func doneAction() {
+        logger.debug("done with Action")
+        isRecordingPaused = false
+        audioRecorder?.stop()
+        if let delegate = self.delegate {
+            delegate.didFinishAudioAtPath(path: recordingFilePath)
+        }
+        dismiss(animated: true, completion: nil)
+    }
+
+    @objc func didBecomeActiveNotification() {
+        validateMicrophoneAccess()
+    }
+
+    func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
+        if flag {
+            self.setToolbarItems([flexItem, startRecordingButton, flexItem], animated: true)
+            if let oldSessionCategory = oldSessionCategory {
+               _ = try? AVAudioSession.sharedInstance().setCategory(oldSessionCategory)
+               UIApplication.shared.isIdleTimerDisabled = wasIdleTimerDisabled
+            }
+        } else {
+            try? FileManager.default.removeItem(at: URL(fileURLWithPath: recordingFilePath))
+        }
+         self.navigationItem.setLeftBarButton(cancelButton, animated: true)
+    }
+
+    func audioRecorderEncodeErrorDidOccur(_ recorder: AVAudioRecorder, error: Error?) {
+        logger.error("audio recording failed: \(error?.localizedDescription ?? "unknown")")
+    }
+
+    func validateMicrophoneAccess() {
+        let audioSession = AVAudioSession.sharedInstance()
+        audioSession.requestRecordPermission({(granted: Bool) -> Void in
+            DispatchQueue.main.async { [weak self] in
+                if let self = self {
+                    self.noRecordingPermissionView.alpha = granted ? 0.0 : 1.0
+                    self.waveFormView.alpha = granted ? 1.0 : 0.0
+                    self.doneButton.isEnabled = granted
+
+                    if self.isFirstUsage {
+                        if !granted {
+                            self.setToolbarItems([self.flexItem, self.startRecordingButton, self.flexItem], animated: true)
+                            self.startRecordingButton.isEnabled = false
+                        } else {
+                            self.pauseButton.isEnabled = granted
+                            self.recordingButtonAction()
+                        }
+
+                        self.isFirstUsage = false
+                    } else {
+                        self.startRecordingButton.isEnabled = granted
+                    }
+                }
+            }
+        })
+    }
+}

+ 19 - 1
deltachat-ios/Controller/ChatViewController.swift

@@ -26,6 +26,10 @@ extension ChatViewController: MediaPickerDelegate {
     func onImageSelected(image: UIImage) {
         sendImage(image)
     }
+
+    func onVoiceMessageRecorded(url: NSURL) {
+        sendVoiceMessage(url: url)
+    }
 }
 
 class ChatViewController: MessagesViewController {
@@ -64,7 +68,7 @@ class ChatViewController: MessagesViewController {
     }
 
     init(dcContext: DcContext, chatId: Int) {
-        let dcChat = DcChat(id: chatId);
+        let dcChat = DcChat(id: chatId)
         self.dcContext = dcContext
         self.chatId = chatId
         self.disableWriting = !dcChat.canSend
@@ -786,6 +790,14 @@ extension ChatViewController: MessagesDataSource {
         }
     }
 
+    private func sendVoiceMessage(url: NSURL) {
+        DispatchQueue.global().async {
+            let msg = DcMsg(viewType: DC_MSG_VOICE)
+            msg.setFile(filepath: url.relativePath, mimeType: "audio/m4a")
+            msg.sendInChat(id: self.chatId)
+        }
+    }
+
     private func sendVideo(url: NSURL) {
         DispatchQueue.global().async {
             let msg = DcMsg(viewType: DC_MSG_VIDEO)
@@ -942,13 +954,19 @@ extension ChatViewController: MessagesLayoutDelegate {
         let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
         let galleryAction = PhotoPickerAlertAction(title: String.localized("gallery"), style: .default, handler: galleryButtonPressed(_:))
         let cameraAction = PhotoPickerAlertAction(title: String.localized("camera"), style: .default, handler: cameraButtonPressed(_:))
+        let voiceMessageAction = UIAlertAction(title: String.localized("voice_message"), style: .default, handler: voiceMessageButtonPressed(_:))
 
         alert.addAction(cameraAction)
         alert.addAction(galleryAction)
+        alert.addAction(voiceMessageAction)
         alert.addAction(UIAlertAction(title: String.localized("cancel"), style: .cancel, handler: nil))
         self.present(alert, animated: true, completion: nil)
     }
 
+    private func voiceMessageButtonPressed(_ action: UIAlertAction) {
+        coordinator?.showVoiceMessageRecorder(delegate: self)
+    }
+
     private func cameraButtonPressed(_ action: UIAlertAction) {
         coordinator?.showCameraViewController(delegate: self)
     }

+ 4 - 0
deltachat-ios/Coordinator/AppCoordinator.swift

@@ -441,6 +441,10 @@ class ChatViewCoordinator: NSObject, Coordinator {
         navigationController.pushViewController(chatViewController, animated: true)
     }
 
+    func showVoiceMessageRecorder(delegate: MediaPickerDelegate) {
+        mediaPicker.showVoiceRecorder(delegate: delegate)
+    }
+
     func showCameraViewController(delegate: MediaPickerDelegate) {
         mediaPicker.showCamera(delegate: delegate, allowCropping: false)
     }

+ 13 - 0
deltachat-ios/Extensions/String+Extension.swift

@@ -73,4 +73,17 @@ extension String {
         let resultString: String = String.localizedStringWithFormat(formatString, count)
         return resultString
     }
+
+    static func timeStringForInterval(_ interval: TimeInterval) -> String {
+        let time = NSInteger(interval)
+        let seconds = time % 60
+        let minutes = (time / 60) % 60
+        let hours = time / 3600
+
+        if hours > 0 {
+            return NSString.localizedStringWithFormat("%02li:%02li:%02li", hours, minutes, seconds) as String
+        } else {
+            return NSString.localizedStringWithFormat("%02li:%02li", minutes, seconds) as String
+        }
+    }
 }

+ 7 - 0
deltachat-ios/Extensions/UIView+Extensions.swift

@@ -49,6 +49,13 @@ internal extension UIView {
         self.bottomAnchor.constraint(equalTo: anchor, constant: -paddingBottom).isActive = true
     }
 
+    func fill(view: UIView, paddingLeading: CGFloat? = 0.0, paddingTrailing: CGFloat? = 0.0, paddingTop: CGFloat? = 0.0, paddingBottom: CGFloat? = 0.0) {
+        alignLeadingToAnchor(view.leadingAnchor, paddingLeading: paddingLeading ??  0.0)
+        alignTrailingToAnchor(view.trailingAnchor, paddingTrailing: paddingTrailing ?? 0.0)
+        alignTopToAnchor(view.topAnchor, paddingTop: paddingTop ?? 0.0)
+        alignBottomToAnchor(view.bottomAnchor, paddingBottom: paddingBottom ?? 0.0)
+    }
+
     func constraintAlignTopTo(_ view: UIView) -> NSLayoutConstraint {
         return constraintAlignTopTo(view, paddingTop: 0.0)
     }

+ 21 - 1
deltachat-ios/Helper/MediaPicker.swift

@@ -7,6 +7,7 @@ protocol MediaPickerDelegate: class {
     func onImageSelected(image: UIImage)
     func onImageSelected(url: NSURL)
     func onVideoSelected(url: NSURL)
+    func onVoiceMessageRecorded(url: NSURL)
 }
 
 extension MediaPickerDelegate {
@@ -16,9 +17,13 @@ extension MediaPickerDelegate {
     func onVideoSelected(url: NSURL) {
         logger.debug("video selected: ", url.path ?? "unknown")
     }
+    func onVoiceMessageRecorded(url: NSURL) {
+        logger.debug("voice message recorded: \(url)")
+    }
 }
 
-class MediaPicker: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
+class MediaPicker: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate, AudioRecorderControllerDelegate {
+
     private let navigationController: UINavigationController
     private weak var delegate: MediaPickerDelegate?
 
@@ -27,6 +32,16 @@ class MediaPicker: NSObject, UINavigationControllerDelegate, UIImagePickerContro
     }
 
 
+    func showVoiceRecorder(delegate: MediaPickerDelegate) {
+        self.delegate = delegate
+        let audioRecorderController = AudioRecorderController()
+        audioRecorderController.delegate = self
+        //audioRecorderController.maximumRecordDuration = 1200
+        let audioRecorderNavController = UINavigationController(rootViewController: audioRecorderController)
+
+        navigationController.present(audioRecorderNavController, animated: true, completion: nil)
+ }
+
     func showPhotoVideoLibrary(delegate: MediaPickerDelegate) {
         if PHPhotoLibrary.authorizationStatus() != .authorized {
             PHPhotoLibrary.requestAuthorization { status in
@@ -129,4 +144,9 @@ class MediaPicker: NSObject, UINavigationControllerDelegate, UIImagePickerContro
         navigationController.dismiss(animated: true, completion: nil)
     }
 
+    func didFinishAudioAtPath(path: String) {
+        let url = NSURL(fileURLWithPath: path)
+        self.delegate?.onVoiceMessageRecorded(url: url)
+    }
+
 }

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff