Utils.swift 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. import Foundation
  2. import UIKit
  3. import AVFoundation
  4. struct Utils {
  5. static func getContactIds() -> [Int] {
  6. let cContacts = dc_get_contacts(mailboxPointer, 0, nil)
  7. return Utils.copyAndFreeArray(inputArray: cContacts)
  8. }
  9. static func getInitials(inputName: String) -> String {
  10. var nameParts = inputName.split(separator: " ")
  11. // this limits initials to max 2, otherwise just takes first letter to avoid messy badges
  12. if nameParts.count > 2 {
  13. nameParts = [nameParts[0]]
  14. }
  15. let initials: [Character] = nameParts.compactMap { part in part.capitalized.first }
  16. let initialsString: String = String(initials)
  17. return initialsString
  18. }
  19. static func copyAndFreeArray(inputArray: OpaquePointer?) -> [Int] {
  20. var acc: [Int] = []
  21. let len = dc_array_get_cnt(inputArray)
  22. for i in 0 ..< len {
  23. let e = dc_array_get_id(inputArray, i)
  24. acc.append(Int(e))
  25. }
  26. dc_array_unref(inputArray)
  27. return acc
  28. }
  29. static func copyAndFreeArrayWithLen(inputArray: OpaquePointer?, len: Int = 0) -> [Int] {
  30. var acc: [Int] = []
  31. let arrayLen = dc_array_get_cnt(inputArray)
  32. let start = max(0, arrayLen - len)
  33. for i in start ..< arrayLen {
  34. let e = dc_array_get_id(inputArray, i)
  35. acc.append(Int(e))
  36. }
  37. dc_array_unref(inputArray)
  38. return acc
  39. }
  40. static func copyAndFreeArrayWithOffset(inputArray: OpaquePointer?, len: Int = 0, from: Int = 0, skipEnd: Int = 0) -> [Int] {
  41. let lenArray = dc_array_get_cnt(inputArray)
  42. if lenArray <= skipEnd || lenArray == 0 {
  43. dc_array_unref(inputArray)
  44. return []
  45. }
  46. let start = lenArray - 1 - skipEnd
  47. let end = max(0, start - len)
  48. let finalLen = start - end + (len > 0 ? 0 : 1)
  49. var acc: [Int] = [Int](repeating: 0, count: finalLen)
  50. for i in stride(from: start, to: end, by: -1) {
  51. let index = finalLen - (start - i) - 1
  52. acc[index] = Int(dc_array_get_id(inputArray, i))
  53. }
  54. dc_array_unref(inputArray)
  55. logger.info("got: \(from) \(len) \(lenArray) - \(acc)")
  56. return acc
  57. }
  58. static func isValid(_ email: String) -> Bool {
  59. let emailRegEx = "(?:[a-z0-9!#$%\\&'*+/=?\\^_`{|}~-]+(?:\\.[a-z0-9!#$%\\&'*+/=?\\^_`{|}"
  60. + "~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\"
  61. + "x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-"
  62. + "z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5"
  63. + "]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-"
  64. + "9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21"
  65. + "-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"
  66. let emailTest = NSPredicate(format: "SELF MATCHES[c] %@", emailRegEx)
  67. return emailTest.evaluate(with: email)
  68. }
  69. static func formatAddressForQuery(address: [String: String]) -> String {
  70. // Open address in Apple Maps app.
  71. var addressParts = [String]()
  72. let addAddressPart: ((String?) -> Void) = { part in
  73. guard let part = part else {
  74. return
  75. }
  76. guard !part.isEmpty else {
  77. return
  78. }
  79. addressParts.append(part)
  80. }
  81. addAddressPart(address["Street"])
  82. addAddressPart(address["Neighborhood"])
  83. addAddressPart(address["City"])
  84. addAddressPart(address["Region"])
  85. addAddressPart(address["Postcode"])
  86. addAddressPart(address["Country"])
  87. return addressParts.joined(separator: ", ")
  88. }
  89. static func saveImage(image: UIImage) -> String? {
  90. guard let directory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) as NSURL else {
  91. return nil
  92. }
  93. let size = image.size.applying(CGAffineTransform(scaleX: 0.2, y: 0.2))
  94. let hasAlpha = false
  95. let scale: CGFloat = 0.0
  96. UIGraphicsBeginImageContextWithOptions(size, !hasAlpha, scale)
  97. image.draw(in: CGRect(origin: CGPoint.zero, size: size))
  98. let scaledImageI = UIGraphicsGetImageFromCurrentImageContext()
  99. UIGraphicsEndImageContext()
  100. guard let scaledImage = scaledImageI else {
  101. return nil
  102. }
  103. guard let data = scaledImage.jpegData(compressionQuality: 0.9) else {
  104. return nil
  105. }
  106. do {
  107. let timestamp = Int(Date().timeIntervalSince1970)
  108. let path = directory.appendingPathComponent("\(timestamp).jpg")
  109. try data.write(to: path!)
  110. return path?.relativePath
  111. } catch {
  112. logger.info(error.localizedDescription)
  113. return nil
  114. }
  115. }
  116. static func generateThumbnailFromVideo(url: URL) -> UIImage? {
  117. do {
  118. let asset = AVURLAsset(url: url)
  119. let imageGenerator = AVAssetImageGenerator(asset: asset)
  120. imageGenerator.appliesPreferredTrackTransform = true
  121. // Select the right one based on which version you are using
  122. // Swift 4.2
  123. //let cgImage = try imageGenerator.copyCGImage(at: .zero, actualTime: nil)
  124. // Swift 4.0
  125. let cgImage = try imageGenerator.copyCGImage(at: CMTime.zero, actualTime: nil)
  126. return UIImage(cgImage: cgImage)
  127. } catch {
  128. print(error.localizedDescription)
  129. return nil
  130. }
  131. }
  132. }
  133. class DateUtils {
  134. // TODO: refactor that, it's an improper way for localizations, use stringsdict instead
  135. // blocked by: converting androids plurals xml entries to stringsdict
  136. static func getBriefRelativeTimeSpanString(timeStamp: Int) -> String {
  137. let unixTime = Int(Date().timeIntervalSince1970)
  138. let seconds = unixTime - timeStamp
  139. if seconds < 60 {
  140. return String.localized("now") // under one minute
  141. } else if seconds < 3600 {
  142. let mins = seconds / 60
  143. return String.localized(stringID: "n_minutes", count: mins);
  144. } else if seconds < 86400 {
  145. let hours = seconds / 3600
  146. return String.localized(stringID: "n_hours", count: hours);
  147. } else {
  148. let date = Date(timeIntervalSince1970: Double(timeStamp))
  149. let dateFormatter = DateFormatter()
  150. // dateFormatter.timeStyle = DateFormatter.Style.short //Set time style
  151. dateFormatter.dateStyle = DateFormatter.Style.medium //Set date style
  152. dateFormatter.timeZone = .current
  153. let localDate = dateFormatter.string(from: date)
  154. return localDate
  155. }
  156. }
  157. }