Jelajahi Sumber

Merge pull request #116 from deltachat/videoFeature

DC iOS can now send videos
nayooti 6 tahun lalu
induk
melakukan
02150b0045

+ 3 - 3
Pods/MessageKit/Sources/Views/Cells/MediaMessageCell.swift

@@ -67,14 +67,14 @@ open class MediaMessageCell: MessageContentCell {
         guard let displayDelegate = messagesCollectionView.messagesDisplayDelegate else {
             fatalError(MessageKitError.nilMessagesDisplayDelegate)
         }
-
         switch message.kind {
         case .photo(let mediaItem):
             imageView.image = mediaItem.image ?? mediaItem.placeholderImage
             playButtonView.isHidden = true
         case .video(let mediaItem):
-            imageView.image = mediaItem.image ?? mediaItem.placeholderImage
-            playButtonView.isHidden = false
+			let image = mediaItem.image ?? mediaItem.placeholderImage
+			imageView.image = image //mediaItem.image ?? mediaItem.placeholderImage
+           // playButtonView.isHidden = false
         default:
             break
         }

+ 2 - 2
Pods/MessageKit/Sources/Views/Cells/MessageContentCell.swift

@@ -106,6 +106,7 @@ open class MessageContentCell: MessageCollectionViewCell {
 
     // MARK: - Configuration
 
+
     open override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
         super.apply(layoutAttributes)
         guard let attributes = layoutAttributes as? MessagesCollectionViewLayoutAttributes else { return }
@@ -260,8 +261,7 @@ open class MessageContentCell: MessageCollectionViewCell {
         case .natural:
             fatalError(MessageKitError.avatarPositionUnresolved)
         }
-
-        messageContainerView.frame = CGRect(origin: origin, size: attributes.messageContainerSize)
+		messageContainerView.frame = CGRect(origin: origin, size: attributes.messageContainerSize)
     }
 
     /// Positions the cell's top label.

+ 4 - 8
deltachat-ios.xcodeproj/project.pbxproj

@@ -52,7 +52,7 @@
 		AE851AC5227C755A00ED86F0 /* Protocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE851AC4227C755A00ED86F0 /* Protocols.swift */; };
 		AE851AC7227C776400ED86F0 /* Location.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE851AC6227C776400ED86F0 /* Location.swift */; };
 		AE851AC9227C77CF00ED86F0 /* Media.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE851AC8227C77CF00ED86F0 /* Media.swift */; };
-		AE851ACE227CA54400ED86F0 /* InitialsLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE851ACD227CA54300ED86F0 /* InitialsLabel.swift */; };
+		AE851ACE227CA54400ED86F0 /* InitialsBadge.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE851ACD227CA54300ED86F0 /* InitialsBadge.swift */; };
 		AE851AD0227DF50900ED86F0 /* GroupChatDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE851ACF227DF50900ED86F0 /* GroupChatDetailViewController.swift */; };
 		AEACE2DD1FB323CA00DCDD78 /* ChatViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEACE2DC1FB323CA00DCDD78 /* ChatViewController.swift */; };
 		AEACE2DF1FB3246400DCDD78 /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEACE2DE1FB3246400DCDD78 /* Message.swift */; };
@@ -61,7 +61,6 @@
 		AEE56D762253431E007DC082 /* AccountSetupController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE56D752253431E007DC082 /* AccountSetupController.swift */; };
 		AEE56D7D2253ADB4007DC082 /* HudHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE56D7C2253ADB4007DC082 /* HudHandler.swift */; };
 		AEE56D80225504DB007DC082 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE56D7F225504DB007DC082 /* Extensions.swift */; };
-		AEE6EC382281AF2D00EDC689 /* InitialsBadge.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE6EC372281AF2D00EDC689 /* InitialsBadge.swift */; };
 		AEE6EC3F2282C59C00EDC689 /* GroupMembersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE6EC3E2282C59C00EDC689 /* GroupMembersViewController.swift */; };
 		AEE6EC412282DF5700EDC689 /* MailboxViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE6EC402282DF5700EDC689 /* MailboxViewController.swift */; };
 		AEE6EC482283045D00EDC689 /* EditSettingsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE6EC472283045D00EDC689 /* EditSettingsController.swift */; };
@@ -134,7 +133,7 @@
 		AE851AC4227C755A00ED86F0 /* Protocols.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Protocols.swift; sourceTree = "<group>"; };
 		AE851AC6227C776400ED86F0 /* Location.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Location.swift; sourceTree = "<group>"; };
 		AE851AC8227C77CF00ED86F0 /* Media.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Media.swift; sourceTree = "<group>"; };
-		AE851ACD227CA54300ED86F0 /* InitialsLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InitialsLabel.swift; sourceTree = "<group>"; };
+		AE851ACD227CA54300ED86F0 /* InitialsBadge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InitialsBadge.swift; sourceTree = "<group>"; };
 		AE851ACF227DF50900ED86F0 /* GroupChatDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupChatDetailViewController.swift; sourceTree = "<group>"; };
 		AEACE2DC1FB323CA00DCDD78 /* ChatViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatViewController.swift; sourceTree = "<group>"; };
 		AEACE2DE1FB3246400DCDD78 /* Message.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Message.swift; sourceTree = "<group>"; };
@@ -143,7 +142,6 @@
 		AEE56D752253431E007DC082 /* AccountSetupController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountSetupController.swift; sourceTree = "<group>"; };
 		AEE56D7C2253ADB4007DC082 /* HudHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HudHandler.swift; sourceTree = "<group>"; };
 		AEE56D7F225504DB007DC082 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
-		AEE6EC372281AF2D00EDC689 /* InitialsBadge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InitialsBadge.swift; sourceTree = "<group>"; };
 		AEE6EC3E2282C59C00EDC689 /* GroupMembersViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupMembersViewController.swift; sourceTree = "<group>"; };
 		AEE6EC402282DF5700EDC689 /* MailboxViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MailboxViewController.swift; sourceTree = "<group>"; };
 		AEE6EC472283045D00EDC689 /* EditSettingsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditSettingsController.swift; sourceTree = "<group>"; };
@@ -332,9 +330,8 @@
 				78E45E3B21D3D03700D4B15E /* TextFieldTableViewCell.swift */,
 				789E879C21D6DF86003ED1C5 /* ProgressHud.swift */,
 				AE38B31722672DFC00EC37A1 /* ActionCell.swift */,
-				AE851ACD227CA54300ED86F0 /* InitialsLabel.swift */,
+				AE851ACD227CA54300ED86F0 /* InitialsBadge.swift */,
 				AE25F08F22807AD800CDEA66 /* GroupNameCell.swift */,
-				AEE6EC372281AF2D00EDC689 /* InitialsBadge.swift */,
 				AE728F14229D5C390047565B /* PhotoPickerAlertAction.swift */,
 				AE52EA18229EB53C00C586C9 /* ContactDetailHeader.swift */,
 			);
@@ -652,8 +649,7 @@
 				AE38B31A2267328200EC37A1 /* Colors.swift in Sources */,
 				789E879621D6CB58003ED1C5 /* QrCodeReaderController.swift in Sources */,
 				7A451DBE1FB4AD0700177250 /* Wrapper.swift in Sources */,
-				AE851ACE227CA54400ED86F0 /* InitialsLabel.swift in Sources */,
-				AEE6EC382281AF2D00EDC689 /* InitialsBadge.swift in Sources */,
+				AE851ACE227CA54400ED86F0 /* InitialsBadge.swift in Sources */,
 				70B8882E2091B8550074812E /* ContactCell.swift in Sources */,
 				7A451D941FB1B1DB00177250 /* wrapper.c in Sources */,
 				7092474120B3869500AF8799 /* ContactDetailViewController.swift in Sources */,

+ 20 - 23
deltachat-ios/Controller/ChatViewController.swift

@@ -11,6 +11,16 @@ import QuickLook
 import UIKit
 import InputBarAccessoryView
 
+protocol MediaSendHandler {
+	func onSuccess()
+}
+
+extension ChatViewController: MediaSendHandler {
+	func onSuccess() {
+		refreshMessages()
+	}
+}
+
 class ChatViewController: MessagesViewController {
 	weak var coordinator: ChatViewCoordinator?
 
@@ -84,7 +94,7 @@ class ChatViewController: MessagesViewController {
 		if let image = chat.profileImage {
 			navigationItem.rightBarButtonItem = UIBarButtonItem(image: image, style: .done, target: self, action: #selector(chatProfilePressed))
 		} else {
-			let initialsLabel = InitialsLabel(name: chat.name, color: chat.color, size: 28)
+			let initialsLabel =  InitialsBadge(name: chat.name, color: chat.color, size: 28)
 			navigationItem.rightBarButtonItem = UIBarButtonItem(customView: initialsLabel)
 		}
 
@@ -342,21 +352,6 @@ class ChatViewController: MessagesViewController {
 				}.onTouchUpInside { _ in
 					self.clipperButtonPressed()
 			}
-			/*
-			InputBarButtonItem()
-			.configure {
-			$0.spacing = .fixed(0)
-			$0.image = UIImage(named: "camera")?.withRenderingMode(.alwaysTemplate)
-			$0.setSize(CGSize(width: 36, height: 36), animated: false)
-			$0.tintColor = UIColor(white: 0.8, alpha: 1)
-			}.onSelected {
-			$0.tintColor = DCColors.primary
-			}.onDeselected {
-			$0.tintColor = UIColor(white: 0.8, alpha: 1)
-			}.onTouchUpInside { _ in
-			self.didPressPhotoButton()
-			},
-			*/
 		]
 
 		messageInputBar.setStackViewItems(leftItems, forStack: .left, animated: false)
@@ -373,11 +368,7 @@ class ChatViewController: MessagesViewController {
 				})
 		}
 	}
-	/*
-	let rightItems = [
-	let sendButtonImage = UIImage(named: "paper_plane")?.withRenderingMode(.alwaysTemplate)
-	]
-	*/
+
 	@objc private func chatProfilePressed() {
 		coordinator?.showChatDetail(chatId: chatId)
 	}
@@ -770,9 +761,11 @@ extension ChatViewController: MessagesLayoutDelegate {
 
 	private func showClipperOptions() {
 		let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
-
 		let photoAction = PhotoPickerAlertAction(title: "Photo", style: .default, handler: photoButtonPressed(_:))
+		let videoAction = PhotoPickerAlertAction(title: "Video", style: .default, handler: videoButtonPressed(_:))
+
 		alert.addAction(photoAction)
+		alert.addAction(videoAction)
 		alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
 		self.present(alert, animated: true, completion: nil)
 	}
@@ -781,6 +774,10 @@ extension ChatViewController: MessagesLayoutDelegate {
 		coordinator?.showCameraViewController()
 	}
 
+	private func videoButtonPressed(_ action: UIAlertAction) {
+		coordinator?.showVideoLibrary()
+	}
+
 }
 
 // MARK: - MessageCellDelegate
@@ -812,8 +809,8 @@ extension ChatViewController: MessageCellDelegate {
 					next = Int(dc_get_next_media(mailboxPointer, UInt32(nextMessage.id), 1, Int32(nextMessage.type), 0, 0))
 				}
 
+				// these are the files user will be able to swipe trough
 				let mediaUrls: [URL] = previousUrls + [url] + nextUrls
-
 				previewController = PreviewController(currentIndex: previousUrls.count, urls: mediaUrls)
 				present(previewController!.qlController, animated: true)
 			}

+ 1 - 1
deltachat-ios/Controller/EditGroupViewController.swift

@@ -35,7 +35,7 @@ class EditGroupViewController: UITableViewController {
 		self.chat = chat
 		super.init(style: .grouped)
 		groupNameCell.inputField.text = chat.name
-		groupNameCell.groupBadge.setText(chat.name)
+		groupNameCell.groupBadge.setName(chat.name)
 		groupNameCell.groupBadge.setColor(chat.color)
 	}
 

+ 88 - 20
deltachat-ios/Coordinator/AppCoordinator.swift

@@ -8,6 +8,8 @@
 
 import UIKit
 import ALCameraViewController
+import Photos
+import MobileCoreServices
 
 
 class AppCoordinator: NSObject, Coordinator, UITabBarControllerDelegate {
@@ -105,8 +107,8 @@ class AppCoordinator: NSObject, Coordinator, UITabBarControllerDelegate {
 
 	func presentLoginController() {
 		let accountSetupController = AccountSetupController()
-		let accountSetupNavigationController = DCNavigationController(rootViewController: accountSetupController)
-		rootViewController.present(accountSetupNavigationController, animated: false, completion: nil)
+		let accountSetupNav = DCNavigationController(rootViewController: accountSetupController)
+		rootViewController.present(accountSetupNav, animated: false, completion: nil)
 	}
 }
 
@@ -117,7 +119,7 @@ extension AppCoordinator: UITabBarDelegate {
 
 	func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
 		print("shouldSelect")
-		return true 
+		return true
 	}
 }
 
@@ -370,9 +372,10 @@ class GroupChatDetailCoordinator: Coordinator {
 	}
 }
 
-class ChatViewCoordinator: Coordinator {
+class ChatViewCoordinator: NSObject, Coordinator {
 	let navigationController: UINavigationController
 	let chatId: Int
+	var chatViewController: ChatViewController!
 
 	var childCoordinators: [Coordinator] = []
 
@@ -412,25 +415,49 @@ class ChatViewCoordinator: Coordinator {
 		// navigationController.present(nav, animated: true, completion: nil)
 	}
 
+	private func sendImage(_ image:UIImage) {
+		DispatchQueue.global().async {
+			if let compressedImage = image.dcCompress() {
+				// at this point image is compressed by 85% by default
+				let pixelSize = compressedImage.imageSizeInPixel()
+				let width = Int32(exactly: pixelSize.width)!
+				let height =  Int32(exactly: pixelSize.height)!
+				let path = Utils.saveImage(image: compressedImage)
+				let msg = dc_msg_new(mailboxPointer, DC_MSG_IMAGE)
+				dc_msg_set_file(msg, path, "image/jpeg")
+				dc_msg_set_dimension(msg, width, height)
+				dc_send_msg(mailboxPointer, UInt32(self.chatId), msg)
+				// cleanup
+				dc_msg_unref(msg)
+			}
+		}
+	}
+
+	private func sendVideo(url: NSURL) {
+		let msg = dc_msg_new(mailboxPointer, DC_MSG_VIDEO)
+		if let path = url.relativePath?.cString(using: .utf8) { //absoluteString?.cString(using: .utf8) {
+			dc_msg_set_file(msg, path, "video/mov")
+			dc_send_msg(mailboxPointer, UInt32(chatId), msg)
+			dc_msg_unref(msg)
+		}
+	}
+
+	private func handleMediaMessageSuccess() {
+		if let chatViewController = self.navigationController.visibleViewController as? MediaSendHandler {
+			DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
+				chatViewController.onSuccess()
+			}
+		}
+	}
+
 	func showCameraViewController() {
 		if UIImagePickerController.isSourceTypeAvailable(.camera) {
 			let cameraViewController = CameraViewController { [weak self] image, _ in
-				self?.navigationController.dismiss(animated: true, completion: nil)
-
-				DispatchQueue.global().async {
-					if let compressedImage = image?.dcCompress() {
-						// at this point image is compressed by 85% by default
-						let pixelSize = compressedImage.imageSizeInPixel()
-						let width = Int32(exactly: pixelSize.width)!
-						let height =  Int32(exactly: pixelSize.height)!
-						let path = Utils.saveImage(image: compressedImage)
-						let msg = dc_msg_new(mailboxPointer, DC_MSG_IMAGE)
-						dc_msg_set_file(msg, path, "image/jpeg")
-						dc_msg_set_dimension(msg, width, height)
-						dc_send_msg(mailboxPointer, UInt32(self!.chatId), msg)
-						// cleanup
-						dc_msg_unref(msg)
-					}
+				self?.navigationController.dismiss(animated: true, completion: {
+					self?.handleMediaMessageSuccess()
+				})
+				if let image = image {
+					self?.sendImage(image)
 				}
 			}
 
@@ -444,6 +471,46 @@ class ChatViewCoordinator: Coordinator {
 		}
 
 	}
+	func showVideoLibrary() {
+		if PHPhotoLibrary.authorizationStatus() != .authorized {
+			PHPhotoLibrary.requestAuthorization { status in
+				DispatchQueue.main.async {
+					[weak self] in
+					switch status {
+					case  .denied, .notDetermined, .restricted:
+						print("denied")
+					case .authorized:
+						self?.presentVideoLibrary()
+					}
+				}
+			}
+		} else {
+			presentVideoLibrary()
+		}
+	}
+
+	private func presentVideoLibrary() {
+		if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
+			let videoPicker = UIImagePickerController()
+			videoPicker.title = "Videos"
+			videoPicker.delegate = self
+			videoPicker.sourceType = .photoLibrary
+			videoPicker.mediaTypes = [kUTTypeMovie as String, kUTTypeVideo as String]
+			navigationController.present(videoPicker, animated: true, completion: nil)
+		}
+	}
+}
+
+extension ChatViewCoordinator: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
+
+	func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
+		if let videoUrl = info[UIImagePickerController.InfoKey.mediaURL] as? NSURL {
+			sendVideo(url: videoUrl)
+		}
+		navigationController.dismiss(animated: true) {
+				self.handleMediaMessageSuccess()
+		}
+	}
 }
 
 class NewGroupCoordinator: Coordinator {
@@ -539,6 +606,7 @@ class EditContactCoordinator: Coordinator, EditContactCoordinatorProtocol {
 	func showChat(chatId: Int) {
 		let chatViewController = ChatViewController(chatId: chatId)
 		let coordinator = ChatViewCoordinator(navigationController: navigationController, chatId: chatId)
+		coordinator.chatViewController = chatViewController
 		childCoordinators.append(coordinator)
 		chatViewController.coordinator = coordinator
 		navigationController.popToRootViewController(animated: false)

+ 1 - 1
deltachat-ios/DC/Wrapper.swift

@@ -208,7 +208,7 @@ class MRMessage: MessageType {
     return nil
   }
 
-  lazy var image: UIImage? = { [unowned self] in
+  private lazy var image: UIImage? = { [unowned self] in
     let filetype = dc_msg_get_viewtype(messagePointer)
     if let path = fileURL, filetype == DC_MSG_IMAGE {
       if path.isFileURL {

+ 67 - 0
deltachat-ios/Helper/Extensions.swift

@@ -193,3 +193,70 @@ extension UIView {
 		self.layer.borderWidth = 2
 	}
 }
+
+extension UIImage {
+func resizeImage(targetSize: CGSize) -> UIImage {
+	let size = self.size
+
+	let widthRatio  = targetSize.width  / size.width
+	let heightRatio = targetSize.height / size.height
+
+	var newSize: CGSize
+	if(widthRatio > heightRatio) {
+		newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
+	} else {
+		newSize = CGSize(width: size.width * widthRatio, height: size.height *      widthRatio)
+	}
+
+	let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)
+
+	UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
+	draw(in: rect)
+	let newImage = UIGraphicsGetImageFromCurrentImageContext()
+	UIGraphicsEndImageContext()
+
+	return newImage!
+}
+}
+
+
+extension UIColor {
+	convenience init(alpha: Int, red: Int, green: Int, blue: Int) {
+		assert(red >= 0 && red <= 255, "Invalid red component")
+		assert(green >= 0 && green <= 255, "Invalid green component")
+		assert(blue >= 0 && blue <= 255, "Invalid blue component")
+
+		self.init(red: CGFloat(red) / 255, green: CGFloat(green) / 255, blue: CGFloat(blue) / 255, alpha: CGFloat(alpha) / 255)
+	}
+
+	convenience init(netHex: Int) {
+		var alpha = (netHex >> 24) & 0xFF
+		if alpha == 0 {
+			alpha = 255
+		}
+
+		self.init(alpha: alpha, red: (netHex >> 16) & 0xFF, green: (netHex >> 8) & 0xFF, blue: netHex & 0xFF)
+	}
+
+	// see: https://stackoverflow.com/a/33397427
+	convenience init(hexString: String) {
+		let hex = hexString.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
+		var int = UInt32()
+		Scanner(string: hex).scanHexInt32(&int)
+		let a, r, g, b: UInt32
+		switch hex.count {
+		case 3: // RGB (12-bit)
+			(a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
+		case 6: // RGB (24-bit)
+			(a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
+		case 8: // ARGB (32-bit)
+			(a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
+		default:
+			(a, r, g, b) = (255, 0, 0, 0)
+		}
+		self.init(red: CGFloat(r) / 255, green: CGFloat(g) / 255, blue: CGFloat(b) / 255, alpha: CGFloat(a) / 255)
+	}
+
+
+}
+

+ 18 - 37
deltachat-ios/Helper/Utils.swift

@@ -8,6 +8,7 @@
 
 import Foundation
 import UIKit
+import AVFoundation
 
 struct Utils {
   static func getContactIds() -> [Int] {
@@ -137,44 +138,24 @@ struct Utils {
       return nil
     }
   }
-}
-
-extension UIColor {
-  convenience init(alpha: Int, red: Int, green: Int, blue: Int) {
-    assert(red >= 0 && red <= 255, "Invalid red component")
-    assert(green >= 0 && green <= 255, "Invalid green component")
-    assert(blue >= 0 && blue <= 255, "Invalid blue component")
-
-    self.init(red: CGFloat(red) / 255, green: CGFloat(green) / 255, blue: CGFloat(blue) / 255, alpha: CGFloat(alpha) / 255)
-  }
-
-  convenience init(netHex: Int) {
-    var alpha = (netHex >> 24) & 0xFF
-    if alpha == 0 {
-      alpha = 255
-    }
 
-    self.init(alpha: alpha, red: (netHex >> 16) & 0xFF, green: (netHex >> 8) & 0xFF, blue: netHex & 0xFF)
-  }
-
-  // see: https://stackoverflow.com/a/33397427
-  convenience init(hexString: String) {
-    let hex = hexString.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
-    var int = UInt32()
-    Scanner(string: hex).scanHexInt32(&int)
-    let a, r, g, b: UInt32
-    switch hex.count {
-    case 3: // RGB (12-bit)
-      (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
-    case 6: // RGB (24-bit)
-      (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
-    case 8: // ARGB (32-bit)
-      (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
-    default:
-      (a, r, g, b) = (255, 0, 0, 0)
-    }
-    self.init(red: CGFloat(r) / 255, green: CGFloat(g) / 255, blue: CGFloat(b) / 255, alpha: CGFloat(a) / 255)
-  }
+	static func generateThumbnailFromVideo(url: URL) -> UIImage? {
+		do {
+			let asset = AVURLAsset(url: url)
+			let imageGenerator = AVAssetImageGenerator(asset: asset)
+			imageGenerator.appliesPreferredTrackTransform = true
+			// Select the right one based on which version you are using
+			// Swift 4.2
+			//let cgImage = try imageGenerator.copyCGImage(at: .zero, actualTime: nil)
+			// Swift 4.0
+			let cgImage = try imageGenerator.copyCGImage(at: CMTime.zero, actualTime: nil)
+			return UIImage(cgImage: cgImage)
+		} catch {
+			print(error.localizedDescription)
+
+			return nil
+		}
+	}
 }
 
 class DateUtils {

+ 1 - 0
deltachat-ios/View/CustomMessageCell.swift

@@ -45,3 +45,4 @@ open class CustomMessageCell: UICollectionViewCell {
   }
 }
 
+

+ 3 - 3
deltachat-ios/View/GroupNameCell.swift

@@ -14,10 +14,10 @@ class GroupLabelCell: UITableViewCell {
   var onTextChanged: ((String) -> Void)? // use this callback to update editButton in navigationController
 
   lazy var groupBadge: InitialsBadge = {
-    let badge = InitialsBadge(frame: .zero)
+    let badge = InitialsBadge(size: groupBadgeSize)
     badge.layer.cornerRadius = groupBadgeSize / 2
     badge.clipsToBounds = true
-    badge.setColor(UIColor.lightGray)
+		badge.setColor(UIColor.lightGray)
     return badge
   }()
 
@@ -61,7 +61,7 @@ class GroupLabelCell: UITableViewCell {
 
   @objc func nameFieldChanged() {
     let groupName = inputField.text ?? ""
-    groupBadge.setText(groupName)
+    groupBadge.setName(groupName)
     onTextChanged?(groupName)
   }
 

+ 19 - 30
deltachat-ios/View/InitialsBadge.swift

@@ -1,30 +1,28 @@
 //
-//  IntitialsBadge.swift
+//  InitialsLabel.swift
 //  deltachat-ios
 //
-//  Created by Bastian van de Wetering on 07.05.19.
+//  Created by Bastian van de Wetering on 03.05.19.
 //  Copyright © 2019 Jonas Reinsch. All rights reserved.
 //
 
-import UIKit
-
-// shall be used for contactCell/ groups
 
-class InitialsBadge: UIView {
-  private lazy var label: UILabel = {
-    let label = UILabel()
-    label.textAlignment = NSTextAlignment.center
-    label.textColor = UIColor.white
-    label.font = UIFont.systemFont(ofSize: 22)
-    // label.adjustsFontSizeToFitWidth = true
-    return label
-  }()
+import UIKit
 
-  override init(frame: CGRect) {
-    super.init(frame: frame)
-    setupSubviews()
+class InitialsBadge: UILabel {
+  convenience init(name: String, color: UIColor, size: CGFloat) {
+    self.init(size: size)
+    setName(name)
+    setColor(color)
+  }
 
-    layer.cornerRadius = frame.width / 2
+  init(size: CGFloat) {
+    super.init(frame: CGRect(x: 0, y: 0, width: size, height: size))
+    textAlignment = NSTextAlignment.center
+    textColor = UIColor.white
+    adjustsFontSizeToFitWidth = true
+    let initialsLabelCornerRadius = size / 2
+    layer.cornerRadius = initialsLabelCornerRadius
     clipsToBounds = true
   }
 
@@ -32,21 +30,12 @@ class InitialsBadge: UIView {
     fatalError("init(coder:) has not been implemented")
   }
 
-  private func setupSubviews() {
-    addSubview(label)
-    label.translatesAutoresizingMaskIntoConstraints = false
-    label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 2).isActive = true
-    label.topAnchor.constraint(equalTo: topAnchor, constant: 2).isActive = true
-    label.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -2).isActive = true
-    label.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -2).isActive = true
+  func setName(_ name: String) {
+    text = Utils.getInitials(inputName: name)
   }
 
   func setColor(_ color: UIColor) {
     backgroundColor = color
   }
-
-  func setText(_ text: String) {
-    let initials = Utils.getInitials(inputName: text)
-    label.text = initials
-  }
 }
+

+ 0 - 39
deltachat-ios/View/InitialsLabel.swift

@@ -1,39 +0,0 @@
-//
-//  InitialsLabel.swift
-//  deltachat-ios
-//
-//  Created by Bastian van de Wetering on 03.05.19.
-//  Copyright © 2019 Jonas Reinsch. All rights reserved.
-//
-
-import UIKit
-
-class InitialsLabel: UILabel {
-  convenience init(name: String, color: UIColor, size: CGFloat) {
-    self.init(size: size)
-    set(name: name)
-    set(color: color)
-  }
-
-  init(size: CGFloat) {
-    super.init(frame: CGRect(x: 0, y: 0, width: size, height: size))
-    textAlignment = NSTextAlignment.center
-    textColor = UIColor.white
-    adjustsFontSizeToFitWidth = true
-    let initialsLabelCornerRadius = size / 2
-    layer.cornerRadius = initialsLabelCornerRadius
-    clipsToBounds = true
-  }
-
-  required init?(coder _: NSCoder) {
-    fatalError("init(coder:) has not been implemented")
-  }
-
-  func set(name: String) {
-    text = Utils.getInitials(inputName: name)
-  }
-
-  func set(color: UIColor) {
-    backgroundColor = color
-  }
-}