mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-05 11:58:32 +00:00
Add SwiftFormat to the project. (#129)
* Run swiftformat for whitespace. * Run swiftformat with some rules.
This commit is contained in:
@@ -9,9 +9,9 @@
|
||||
import Foundation
|
||||
|
||||
struct Benchmark {
|
||||
static private var trackingIdentifiers = [String: CFAbsoluteTime]()
|
||||
private static var trackingIdentifiers = [String: CFAbsoluteTime]()
|
||||
|
||||
static public var trackingEnabled = false
|
||||
public static var trackingEnabled = false
|
||||
|
||||
static func startTrackingForIdentifier(_ identifier: String, message: String? = nil) {
|
||||
guard trackingEnabled else {
|
||||
|
||||
@@ -2,25 +2,25 @@ import UIKit
|
||||
|
||||
// swiftlint:disable all
|
||||
|
||||
extension UIImage {
|
||||
public convenience init?(blurHash: String, size: CGSize, punch: Float = 1) {
|
||||
public extension UIImage {
|
||||
convenience init?(blurHash: String, size: CGSize, punch: Float = 1) {
|
||||
guard blurHash.count >= 6 else { return nil }
|
||||
|
||||
let sizeFlag = String(blurHash[0]).decode83()
|
||||
let numY = (sizeFlag / 9) + 1
|
||||
let numX = (sizeFlag % 9) + 1
|
||||
let sizeFlag = String(blurHash[0]).decode83()
|
||||
let numY = (sizeFlag / 9) + 1
|
||||
let numX = (sizeFlag % 9) + 1
|
||||
|
||||
let quantisedMaximumValue = String(blurHash[1]).decode83()
|
||||
let quantisedMaximumValue = String(blurHash[1]).decode83()
|
||||
let maximumValue = Float(quantisedMaximumValue + 1) / 166
|
||||
|
||||
guard blurHash.count == 4 + 2 * numX * numY else { return nil }
|
||||
|
||||
let colours: [(Float, Float, Float)] = (0 ..< numX * numY).map { i in
|
||||
let colours: [(Float, Float, Float)] = (0..<numX * numY).map { i in
|
||||
if i == 0 {
|
||||
let value = String(blurHash[2 ..< 6]).decode83()
|
||||
let value = String(blurHash[2..<6]).decode83()
|
||||
return decodeDC(value)
|
||||
} else {
|
||||
let value = String(blurHash[4 + i * 2 ..< 4 + i * 2 + 2]).decode83()
|
||||
let value = String(blurHash[4 + i * 2..<4 + i * 2 + 2]).decode83()
|
||||
return decodeAC(value, maximumValue: maximumValue * punch)
|
||||
}
|
||||
}
|
||||
@@ -32,14 +32,14 @@ extension UIImage {
|
||||
CFDataSetLength(data, bytesPerRow * height)
|
||||
guard let pixels = CFDataGetMutableBytePtr(data) else { return nil }
|
||||
|
||||
for y in 0 ..< height {
|
||||
for x in 0 ..< width {
|
||||
for y in 0..<height {
|
||||
for x in 0..<width {
|
||||
var r: Float = 0
|
||||
var g: Float = 0
|
||||
var b: Float = 0
|
||||
|
||||
for j in 0 ..< numY {
|
||||
for i in 0 ..< numX {
|
||||
for j in 0..<numY {
|
||||
for i in 0..<numX {
|
||||
let basis = cos(Float.pi * Float(x) * Float(i) / Float(width)) * cos(Float.pi * Float(y) * Float(j) / Float(height))
|
||||
let colour = colours[i + j * numX]
|
||||
r += colour.0 * basis
|
||||
@@ -62,7 +62,7 @@ extension UIImage {
|
||||
|
||||
guard let provider = CGDataProvider(data: data) else { return nil }
|
||||
guard let cgImage = CGImage(width: width, height: height, bitsPerComponent: 8, bitsPerPixel: 24, bytesPerRow: bytesPerRow,
|
||||
space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: bitmapInfo, provider: provider, decode: nil, shouldInterpolate: true, intent: .defaultIntent) else { return nil }
|
||||
space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: bitmapInfo, provider: provider, decode: nil, shouldInterpolate: true, intent: .defaultIntent) else { return nil }
|
||||
|
||||
self.init(cgImage: cgImage)
|
||||
}
|
||||
@@ -76,21 +76,21 @@ private func decodeDC(_ value: Int) -> (Float, Float, Float) {
|
||||
}
|
||||
|
||||
private func decodeAC(_ value: Int, maximumValue: Float) -> (Float, Float, Float) {
|
||||
let quantR = value / (19 * 19)
|
||||
let quantG = (value / 19) % 19
|
||||
let quantB = value % 19
|
||||
let quantR = value / (19 * 19)
|
||||
let quantG = (value / 19) % 19
|
||||
let quantB = value % 19
|
||||
|
||||
let rgb = (
|
||||
signPow((Float(quantR) - 9) / 9, 2) * maximumValue,
|
||||
signPow((Float(quantG) - 9) / 9, 2) * maximumValue,
|
||||
signPow((Float(quantB) - 9) / 9, 2) * maximumValue
|
||||
)
|
||||
let rgb = (
|
||||
signPow((Float(quantR) - 9) / 9, 2) * maximumValue,
|
||||
signPow((Float(quantG) - 9) / 9, 2) * maximumValue,
|
||||
signPow((Float(quantB) - 9) / 9, 2) * maximumValue
|
||||
)
|
||||
|
||||
return rgb
|
||||
return rgb
|
||||
}
|
||||
|
||||
private func signPow(_ value: Float, _ exp: Float) -> Float {
|
||||
return copysign(pow(abs(value), exp), value)
|
||||
copysign(pow(abs(value), exp), value)
|
||||
}
|
||||
|
||||
private func linearTosRGB(_ value: Float) -> Int {
|
||||
@@ -105,46 +105,44 @@ private func sRGBToLinear<Type: BinaryInteger>(_ value: Type) -> Float {
|
||||
else { return pow((v + 0.055) / 1.055, 2.4) }
|
||||
}
|
||||
|
||||
private let encodeCharacters: [String] = {
|
||||
return "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~".map { String($0) }
|
||||
}()
|
||||
private let encodeCharacters: [String] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~".map { String($0) }
|
||||
|
||||
private let decodeCharacters: [String: Int] = {
|
||||
var dict: [String: Int] = [:]
|
||||
for (index, character) in encodeCharacters.enumerated() {
|
||||
dict[character] = index
|
||||
}
|
||||
return dict
|
||||
var dict: [String: Int] = [:]
|
||||
for (index, character) in encodeCharacters.enumerated() {
|
||||
dict[character] = index
|
||||
}
|
||||
return dict
|
||||
}()
|
||||
|
||||
extension String {
|
||||
func decode83() -> Int {
|
||||
var value: Int = 0
|
||||
for character in self {
|
||||
if let digit = decodeCharacters[String(character)] {
|
||||
value = value * 83 + digit
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
func decode83() -> Int {
|
||||
var value = 0
|
||||
for character in self {
|
||||
if let digit = decodeCharacters[String(character)] {
|
||||
value = value * 83 + digit
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
private extension String {
|
||||
subscript (offset: Int) -> Character {
|
||||
return self[index(startIndex, offsetBy: offset)]
|
||||
}
|
||||
subscript(offset: Int) -> Character {
|
||||
self[index(startIndex, offsetBy: offset)]
|
||||
}
|
||||
|
||||
subscript (bounds: CountableClosedRange<Int>) -> Substring {
|
||||
let start = index(startIndex, offsetBy: bounds.lowerBound)
|
||||
let end = index(startIndex, offsetBy: bounds.upperBound)
|
||||
return self[start...end]
|
||||
}
|
||||
subscript(bounds: CountableClosedRange<Int>) -> Substring {
|
||||
let start = index(startIndex, offsetBy: bounds.lowerBound)
|
||||
let end = index(startIndex, offsetBy: bounds.upperBound)
|
||||
return self[start...end]
|
||||
}
|
||||
|
||||
subscript (bounds: CountableRange<Int>) -> Substring {
|
||||
let start = index(startIndex, offsetBy: bounds.lowerBound)
|
||||
let end = index(startIndex, offsetBy: bounds.upperBound)
|
||||
return self[start..<end]
|
||||
}
|
||||
subscript(bounds: CountableRange<Int>) -> Substring {
|
||||
let start = index(startIndex, offsetBy: bounds.lowerBound)
|
||||
let end = index(startIndex, offsetBy: bounds.upperBound)
|
||||
return self[start..<end]
|
||||
}
|
||||
}
|
||||
|
||||
// swiftlint:enable all
|
||||
|
||||
@@ -47,6 +47,6 @@ extension Coordinator {
|
||||
}
|
||||
|
||||
func remove(childCoordinator: Coordinator) {
|
||||
self.childCoordinators = self.childCoordinators.filter { $0 !== childCoordinator }
|
||||
childCoordinators = childCoordinators.filter { $0 !== childCoordinator }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,15 +36,15 @@ public extension Bundle {
|
||||
}
|
||||
|
||||
/// Preferred languages in the priority order.
|
||||
static private(set) var preferredLanguages: [String] = calculatePreferredLanguages()
|
||||
private(set) static var preferredLanguages: [String] = calculatePreferredLanguages()
|
||||
|
||||
private static func calculatePreferredLanguages() -> [String] {
|
||||
var set = Set<String>()
|
||||
return ([Bundle.elementLanguage] +
|
||||
Locale.preferredLanguages +
|
||||
[Bundle.elementFallbackLanguage])
|
||||
.compactMap { $0 }
|
||||
.filter { set.insert($0).inserted }
|
||||
Locale.preferredLanguages +
|
||||
[Bundle.elementFallbackLanguage])
|
||||
.compactMap { $0 }
|
||||
.filter { set.insert($0).inserted }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
// Copyright © 2022 Element. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import DTCoreText
|
||||
import Foundation
|
||||
|
||||
struct AttributedStringBuilder: AttributedStringBuilderProtocol {
|
||||
|
||||
@@ -55,8 +55,8 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
|
||||
func fromHTML(_ htmlString: String?) -> AttributedString? {
|
||||
guard let htmlString = htmlString,
|
||||
let data = htmlString.data(using: .utf8) else {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
let defaultFont = UIFont.preferredFont(forTextStyle: .body)
|
||||
|
||||
@@ -65,7 +65,7 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
|
||||
DTDefaultFontFamily: defaultFont.familyName,
|
||||
DTDefaultFontName: defaultFont.fontName,
|
||||
DTDefaultFontSize: defaultFont.pointSize,
|
||||
DTDefaultStyleSheet: DTCSSStylesheet(styleBlock: self.defaultCSS) as Any
|
||||
DTDefaultStyleSheet: DTCSSStylesheet(styleBlock: defaultCSS) as Any
|
||||
]
|
||||
|
||||
guard let builder = DTHTMLAttributedStringBuilder(html: data, options: parsingOptions, documentAttributes: nil) else {
|
||||
@@ -96,7 +96,7 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
|
||||
return nil
|
||||
}
|
||||
|
||||
return attributedString.runs[\.blockquote].map { (value, range) in
|
||||
return attributedString.runs[\.blockquote].map { value, range in
|
||||
var attributedString = AttributedString(attributedString[range])
|
||||
|
||||
// Remove trailing new lines if any
|
||||
@@ -119,8 +119,8 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
|
||||
guard let value = value as? NSArray,
|
||||
let dtTextBlock = value.firstObject as? DTTextBlock,
|
||||
dtTextBlock.backgroundColor == temporaryBlockquoteMarkingColor else {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
attributedString.addAttribute(.MXBlockquote, value: true, range: range)
|
||||
}
|
||||
@@ -128,8 +128,8 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
|
||||
attributedString.enumerateAttribute(.backgroundColor, in: .init(location: 0, length: attributedString.length), options: []) { value, range, _ in
|
||||
guard let value = value as? UIColor,
|
||||
value == temporaryBlockquoteMarkingColor else {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
attributedString.removeAttribute(.backgroundColor, range: range)
|
||||
attributedString.addAttribute(.MXBlockquote, value: true, range: range)
|
||||
@@ -212,22 +212,22 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol {
|
||||
}
|
||||
|
||||
private var defaultCSS: String {
|
||||
"""
|
||||
blockquote {
|
||||
background: \(temporaryBlockquoteMarkingColor.toHexString());
|
||||
display: block;
|
||||
}
|
||||
pre,code {
|
||||
background-color: \(temporaryCodeBlockMarkingColor.toHexString());
|
||||
display: inline;
|
||||
font-family: monospace;
|
||||
white-space: pre;
|
||||
-coretext-fontname: Menlo-Regular;
|
||||
}
|
||||
h1,h2,h3 {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
"""
|
||||
"""
|
||||
blockquote {
|
||||
background: \(temporaryBlockquoteMarkingColor.toHexString());
|
||||
display: block;
|
||||
}
|
||||
pre,code {
|
||||
background-color: \(temporaryCodeBlockMarkingColor.toHexString());
|
||||
display: inline;
|
||||
font-family: monospace;
|
||||
white-space: pre;
|
||||
-coretext-fontname: Menlo-Regular;
|
||||
}
|
||||
h1,h2,h3 {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ extension UIColor {
|
||||
|
||||
getRed(&red, green: &green, blue: &blue, alpha: &alpha)
|
||||
|
||||
let rgb: Int = (Int)(red*255)<<16 | (Int)(green*255)<<8 | (Int)(blue*255)<<0
|
||||
let rgb = Int(red * 255) << 16 | Int(green * 255) << 8 | Int(blue * 255) << 0
|
||||
|
||||
return NSString(format: "#%06x", rgb) as String
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
// Copyright © 2022 Element. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import DTCoreText
|
||||
import Foundation
|
||||
|
||||
public extension DTHTMLElement {
|
||||
/// Sanitize the element using the given parameters.
|
||||
|
||||
@@ -26,6 +26,6 @@ extension AttributeScopes {
|
||||
|
||||
extension AttributeDynamicLookup {
|
||||
subscript<T: AttributedStringKey>(dynamicMember keyPath: KeyPath<AttributeScopes.ElementXAttributes, T>) -> T {
|
||||
return self[T.self]
|
||||
self[T.self]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Vision
|
||||
import UIKit
|
||||
import Vision
|
||||
|
||||
enum ImageAnonymizerError: Error {
|
||||
case noCgImageBased
|
||||
}
|
||||
|
||||
struct ImageAnonymizer {
|
||||
enum ImageAnonymizer {
|
||||
|
||||
private static var allowedTextItems: [String] = [
|
||||
"#",
|
||||
@@ -96,7 +96,7 @@ struct ImageAnonymizer {
|
||||
continue
|
||||
}
|
||||
if let textObservation = observation as? VNRecognizedTextObservation,
|
||||
let text = textObservation.topCandidates(1).first?.string {
|
||||
let text = textObservation.topCandidates(1).first?.string {
|
||||
if Double(text) != nil || Self.allowedTextItems.contains(text) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -21,10 +21,10 @@ import SwiftyBeaver
|
||||
@objc public class MXLogConfiguration: NSObject {
|
||||
|
||||
/// the desired log level. `.verbose` by default.
|
||||
@objc public var logLevel: MXLogLevel = MXLogLevel.verbose
|
||||
@objc public var logLevel = MXLogLevel.verbose
|
||||
|
||||
/// whether logs should be written directly to files. `false` by default.
|
||||
@objc public var redirectLogsToFiles: Bool = false
|
||||
@objc public var redirectLogsToFiles = false
|
||||
|
||||
/// the maximum total space to use for log files in bytes. `100MB` by default.
|
||||
@objc public var logFilesSizeLimit: UInt = 100 * 1024 * 1024 // 100MB
|
||||
@@ -64,7 +64,7 @@ private var logger: SwiftyBeaver.Type = {
|
||||
/// Please see `MXLogConfiguration` for all available options.
|
||||
/// - Parameters:
|
||||
/// - configuration: the `MXLogConfiguration` instance to use
|
||||
@objc static public func configure(_ configuration: MXLogConfiguration) {
|
||||
@objc public static func configure(_ configuration: MXLogConfiguration) {
|
||||
configureLogger(logger, withConfiguration: configuration)
|
||||
}
|
||||
|
||||
@@ -107,8 +107,8 @@ private var logger: SwiftyBeaver.Type = {
|
||||
logger.info(message, file, function, line: line)
|
||||
}
|
||||
|
||||
public static func warning(_ message: @autoclosure () -> Any, _
|
||||
file: String = #file,
|
||||
public static func warning(_ message: @autoclosure () -> Any,
|
||||
_ file: String = #file,
|
||||
_ function: String = #function,
|
||||
line: Int = #line,
|
||||
context: Any? = nil) {
|
||||
@@ -133,8 +133,8 @@ private var logger: SwiftyBeaver.Type = {
|
||||
logger.error(message, file, function, line: line)
|
||||
}
|
||||
|
||||
public static func failure(_ message: @autoclosure () -> Any, _
|
||||
file: String = #file,
|
||||
public static func failure(_ message: @autoclosure () -> Any,
|
||||
_ file: String = #file,
|
||||
_ function: String = #function,
|
||||
line: Int = #line,
|
||||
context: Any? = nil) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -30,7 +30,7 @@ struct NavigationModule {
|
||||
extension NavigationModule: CustomStringConvertible {
|
||||
|
||||
var description: String {
|
||||
return "NavigationModule: \(presentable), pop completion: \(String(describing: popCompletion))"
|
||||
"NavigationModule: \(presentable), pop completion: \(String(describing: popCompletion))"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ final class NavigationRouter: NSObject, NavigationRouterType {
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private var completions: [UIViewController : () -> Void]
|
||||
private var completions: [UIViewController: () -> Void]
|
||||
private let navigationController: UINavigationController
|
||||
|
||||
/// Stores the association between the added Presentable and his view controller.
|
||||
@@ -34,34 +34,34 @@ final class NavigationRouter: NSObject, NavigationRouterType {
|
||||
|
||||
/// Returns the presentables associated to each view controller
|
||||
var modules: [Presentable] {
|
||||
return self.viewControllers.map { (viewController) -> Presentable in
|
||||
return self.module(for: viewController)
|
||||
viewControllers.map { viewController -> Presentable in
|
||||
self.module(for: viewController)
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the view controllers stack
|
||||
var viewControllers: [UIViewController] {
|
||||
return navigationController.viewControllers
|
||||
navigationController.viewControllers
|
||||
}
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(navigationController: UINavigationController) {
|
||||
self.navigationController = navigationController
|
||||
self.completions = [:]
|
||||
completions = [:]
|
||||
super.init()
|
||||
self.navigationController.delegate = self
|
||||
|
||||
// Post local notification on NavigationRouter creation
|
||||
let userInfo: [String: Any] = [NavigationRouter.NotificationUserInfoKey.navigationRouter: self,
|
||||
NavigationRouter.NotificationUserInfoKey.navigationController: navigationController]
|
||||
NavigationRouter.NotificationUserInfoKey.navigationController: navigationController]
|
||||
NotificationCenter.default.post(name: NavigationRouter.didCreate, object: self, userInfo: userInfo)
|
||||
}
|
||||
|
||||
deinit {
|
||||
// Post local notification on NavigationRouter deinit
|
||||
let userInfo: [String: Any] = [NavigationRouter.NotificationUserInfoKey.navigationRouter: self,
|
||||
NavigationRouter.NotificationUserInfoKey.navigationController: navigationController]
|
||||
NavigationRouter.NotificationUserInfoKey.navigationController: navigationController]
|
||||
NotificationCenter.default.post(name: NavigationRouter.willDestroy, object: self, userInfo: userInfo)
|
||||
}
|
||||
|
||||
@@ -88,9 +88,9 @@ final class NavigationRouter: NSObject, NavigationRouterType {
|
||||
return
|
||||
}
|
||||
|
||||
self.addModule(module, for: controller)
|
||||
addModule(module, for: controller)
|
||||
|
||||
let controllersToPop = self.navigationController.viewControllers.reversed()
|
||||
let controllersToPop = navigationController.viewControllers.reversed()
|
||||
|
||||
controllersToPop.forEach {
|
||||
self.willPopViewController($0)
|
||||
@@ -100,7 +100,7 @@ final class NavigationRouter: NSObject, NavigationRouterType {
|
||||
completions[controller] = popCompletion
|
||||
}
|
||||
|
||||
self.willPushViewController(controller)
|
||||
willPushViewController(controller)
|
||||
|
||||
navigationController.setViewControllers([controller], animated: animated)
|
||||
navigationController.isNavigationBarHidden = hideNavigationBar
|
||||
@@ -111,22 +111,22 @@ final class NavigationRouter: NSObject, NavigationRouterType {
|
||||
}
|
||||
|
||||
// Add again controller to module association, in case same module instance is added back
|
||||
self.addModule(module, for: controller)
|
||||
addModule(module, for: controller)
|
||||
|
||||
self.didPushViewController(controller)
|
||||
didPushViewController(controller)
|
||||
}
|
||||
|
||||
func setModules(_ modules: [NavigationModule], hideNavigationBar: Bool, animated: Bool) {
|
||||
|
||||
MXLog.debug("[NavigationRouter] Set modules \(modules)")
|
||||
|
||||
let controllers = modules.map { (module) -> UIViewController in
|
||||
let controllers = modules.map { module -> UIViewController in
|
||||
let controller = module.presentable.toPresentable()
|
||||
self.addModule(module.presentable, for: controller)
|
||||
return controller
|
||||
}
|
||||
|
||||
let controllersToPop = self.navigationController.viewControllers.reversed()
|
||||
let controllersToPop = navigationController.viewControllers.reversed()
|
||||
|
||||
controllersToPop.forEach {
|
||||
self.willPopViewController($0)
|
||||
@@ -146,7 +146,7 @@ final class NavigationRouter: NSObject, NavigationRouterType {
|
||||
}
|
||||
|
||||
// Add again controller to module association, in case same modules instance are added back
|
||||
modules.forEach { (module) in
|
||||
modules.forEach { module in
|
||||
self.addModule(module.presentable, for: module.presentable.toPresentable())
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ final class NavigationRouter: NSObject, NavigationRouterType {
|
||||
func popToRootModule(animated: Bool) {
|
||||
MXLog.debug("[NavigationRouter] Pop to root module")
|
||||
|
||||
let controllers = self.navigationController.viewControllers
|
||||
let controllers = navigationController.viewControllers
|
||||
|
||||
if controllers.count > 1 {
|
||||
let controllersToPop = controllers[1..<controllers.count]
|
||||
@@ -179,7 +179,7 @@ final class NavigationRouter: NSObject, NavigationRouterType {
|
||||
MXLog.debug("[NavigationRouter] Pop to module \(module)")
|
||||
|
||||
let controller = module.toPresentable()
|
||||
let controllersBeforePop = self.navigationController.viewControllers
|
||||
let controllersBeforePop = navigationController.viewControllers
|
||||
|
||||
if let controllerIndex = controllersBeforePop.firstIndex(of: controller) {
|
||||
let controllersToPop = controllersBeforePop[controllerIndex..<controllersBeforePop.count]
|
||||
@@ -207,17 +207,17 @@ final class NavigationRouter: NSObject, NavigationRouterType {
|
||||
return
|
||||
}
|
||||
|
||||
self.addModule(module, for: controller)
|
||||
addModule(module, for: controller)
|
||||
|
||||
if let completion = popCompletion {
|
||||
completions[controller] = completion
|
||||
}
|
||||
|
||||
self.willPushViewController(controller)
|
||||
willPushViewController(controller)
|
||||
|
||||
navigationController.pushViewController(controller, animated: animated)
|
||||
|
||||
self.didPushViewController(controller)
|
||||
didPushViewController(controller)
|
||||
}
|
||||
|
||||
func push(_ modules: [NavigationModule], animated: Bool) {
|
||||
@@ -231,22 +231,22 @@ final class NavigationRouter: NSObject, NavigationRouterType {
|
||||
|
||||
for module in modules {
|
||||
let controller = module.presentable.toPresentable()
|
||||
self.addModule(module.presentable, for: controller)
|
||||
addModule(module.presentable, for: controller)
|
||||
|
||||
if let completion = module.popCompletion {
|
||||
completions[controller] = completion
|
||||
}
|
||||
|
||||
self.willPushViewController(controller)
|
||||
willPushViewController(controller)
|
||||
}
|
||||
|
||||
var viewControllers = navigationController.viewControllers
|
||||
viewControllers.append(contentsOf: modules.map({ $0.presentable.toPresentable() }))
|
||||
viewControllers.append(contentsOf: modules.map { $0.presentable.toPresentable() })
|
||||
navigationController.setViewControllers(viewControllers, animated: animated)
|
||||
|
||||
for module in modules {
|
||||
let controller = module.presentable.toPresentable()
|
||||
self.didPushViewController(controller)
|
||||
didPushViewController(controller)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,22 +254,22 @@ final class NavigationRouter: NSObject, NavigationRouterType {
|
||||
MXLog.debug("[NavigationRouter] Pop module")
|
||||
|
||||
if let lastController = navigationController.viewControllers.last {
|
||||
self.willPopViewController(lastController)
|
||||
willPopViewController(lastController)
|
||||
}
|
||||
|
||||
if let controller = navigationController.popViewController(animated: animated) {
|
||||
self.didPopViewController(controller)
|
||||
didPopViewController(controller)
|
||||
}
|
||||
}
|
||||
|
||||
func popAllModules(animated: Bool) {
|
||||
MXLog.debug("[NavigationRouter] Pop all modules")
|
||||
|
||||
let controllersToPop = self.navigationController.viewControllers.reversed()
|
||||
let controllersToPop = navigationController.viewControllers.reversed()
|
||||
|
||||
controllersToPop.forEach {
|
||||
self.willPopViewController($0)
|
||||
}
|
||||
}
|
||||
|
||||
navigationController.setViewControllers([], animated: animated)
|
||||
|
||||
@@ -281,31 +281,31 @@ final class NavigationRouter: NSObject, NavigationRouterType {
|
||||
func contains(_ module: Presentable) -> Bool {
|
||||
|
||||
let controller = module.toPresentable()
|
||||
return self.navigationController.viewControllers.contains(controller)
|
||||
return navigationController.viewControllers.contains(controller)
|
||||
}
|
||||
|
||||
// MARK: Presentable
|
||||
|
||||
func toPresentable() -> UIViewController {
|
||||
return navigationController
|
||||
navigationController
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func module(for viewController: UIViewController) -> Presentable {
|
||||
|
||||
guard let module = self.storedModules[viewController] as? Presentable else {
|
||||
guard let module = storedModules[viewController] as? Presentable else {
|
||||
return viewController
|
||||
}
|
||||
return module
|
||||
}
|
||||
|
||||
private func addModule(_ module: Presentable, for viewController: UIViewController) {
|
||||
self.storedModules[viewController] = module as AnyObject
|
||||
storedModules[viewController] = module as AnyObject
|
||||
}
|
||||
|
||||
private func removeModule(for viewController: UIViewController) {
|
||||
self.storedModules[viewController] = nil
|
||||
storedModules[viewController] = nil
|
||||
}
|
||||
|
||||
private func runCompletion(for controller: UIViewController) {
|
||||
@@ -317,30 +317,30 @@ final class NavigationRouter: NSObject, NavigationRouterType {
|
||||
}
|
||||
|
||||
private func willPushViewController(_ viewController: UIViewController) {
|
||||
self.postNotification(withName: NavigationRouter.willPushModule, for: viewController)
|
||||
postNotification(withName: NavigationRouter.willPushModule, for: viewController)
|
||||
}
|
||||
|
||||
private func didPushViewController(_ viewController: UIViewController) {
|
||||
self.postNotification(withName: NavigationRouter.didPushModule, for: viewController)
|
||||
postNotification(withName: NavigationRouter.didPushModule, for: viewController)
|
||||
}
|
||||
|
||||
private func willPopViewController(_ viewController: UIViewController) {
|
||||
self.postNotification(withName: NavigationRouter.willPopModule, for: viewController)
|
||||
postNotification(withName: NavigationRouter.willPopModule, for: viewController)
|
||||
}
|
||||
|
||||
private func didPopViewController(_ viewController: UIViewController) {
|
||||
self.postNotification(withName: NavigationRouter.didPopModule, for: viewController)
|
||||
private func didPopViewController(_ viewController: UIViewController) {
|
||||
postNotification(withName: NavigationRouter.didPopModule, for: viewController)
|
||||
|
||||
// Call completion closure associated to the view controller
|
||||
// So associated coordinator can be deallocated
|
||||
runCompletion(for: viewController)
|
||||
|
||||
self.removeModule(for: viewController)
|
||||
removeModule(for: viewController)
|
||||
}
|
||||
|
||||
private func postNotification(withName name: Notification.Name, for viewController: UIViewController) {
|
||||
|
||||
let module = self.module(for: viewController)
|
||||
let module = module(for: viewController)
|
||||
|
||||
let userInfo: [String: Any] = [
|
||||
NotificationUserInfoKey.navigationRouter: self,
|
||||
@@ -352,6 +352,7 @@ final class NavigationRouter: NSObject, NavigationRouterType {
|
||||
}
|
||||
|
||||
// MARK: - UINavigationControllerDelegate
|
||||
|
||||
extension NavigationRouter: UINavigationControllerDelegate {
|
||||
|
||||
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
|
||||
@@ -363,17 +364,18 @@ extension NavigationRouter: UINavigationControllerDelegate {
|
||||
|
||||
// Ensure the view controller is popping
|
||||
guard let poppedViewController = navigationController.transitionCoordinator?.viewController(forKey: .from),
|
||||
!navigationController.viewControllers.contains(poppedViewController) else {
|
||||
return
|
||||
!navigationController.viewControllers.contains(poppedViewController) else {
|
||||
return
|
||||
}
|
||||
|
||||
MXLog.debug("[NavigationRouter] Popped module: \(poppedViewController)")
|
||||
|
||||
self.didPopViewController(poppedViewController)
|
||||
didPopViewController(poppedViewController)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - NavigationRouter notification constants
|
||||
|
||||
extension NavigationRouter {
|
||||
|
||||
// MARK: Notification names
|
||||
@@ -388,7 +390,7 @@ extension NavigationRouter {
|
||||
|
||||
// MARK: Notification keys
|
||||
|
||||
public struct NotificationUserInfoKey {
|
||||
public enum NotificationUserInfoKey {
|
||||
|
||||
/// The associated view controller (UIViewController).
|
||||
static let viewController = "viewController"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -25,7 +25,7 @@ class NavigationRouterStore: NavigationRouterStoreProtocol {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// WeakDictionary does not work with protocol
|
||||
// WeakDictionary does not work with protocol
|
||||
// Find a way to use NavigationRouterType as value
|
||||
private var navigationRouters = WeakDictionary<UINavigationController, NavigationRouter>()
|
||||
|
||||
@@ -33,14 +33,14 @@ class NavigationRouterStore: NavigationRouterStoreProtocol {
|
||||
|
||||
/// As we are ensuring that there is only one navigation controller per NavigationRouter, the class here should be used as a singleton.
|
||||
private init() {
|
||||
self.registerNavigationRouterNotifications()
|
||||
registerNavigationRouterNotifications()
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func navigationRouter(for navigationController: UINavigationController) -> NavigationRouterType {
|
||||
|
||||
if let existingNavigationRouter = self.findNavigationRouter(for: navigationController) {
|
||||
if let existingNavigationRouter = findNavigationRouter(for: navigationController) {
|
||||
return existingNavigationRouter
|
||||
}
|
||||
|
||||
@@ -51,11 +51,11 @@ class NavigationRouterStore: NavigationRouterStoreProtocol {
|
||||
// MARK: - Private
|
||||
|
||||
private func findNavigationRouter(for navigationController: UINavigationController) -> NavigationRouterType? {
|
||||
return self.navigationRouters[navigationController]
|
||||
navigationRouters[navigationController]
|
||||
}
|
||||
|
||||
private func removeNavigationRouter(for navigationController: UINavigationController) {
|
||||
self.navigationRouters[navigationController] = nil
|
||||
navigationRouters[navigationController] = nil
|
||||
}
|
||||
|
||||
private func registerNavigationRouterNotifications() {
|
||||
@@ -71,12 +71,12 @@ class NavigationRouterStore: NavigationRouterStoreProtocol {
|
||||
return
|
||||
}
|
||||
|
||||
if let existingNavigationRouter = self.findNavigationRouter(for: navigationController) {
|
||||
if let existingNavigationRouter = findNavigationRouter(for: navigationController) {
|
||||
fatalError("\(existingNavigationRouter) is already tied to the same navigation controller as \(navigationRouter). We should have only one NavigationRouter per navigation controller")
|
||||
} else {
|
||||
// WeakDictionary does not work with protocol
|
||||
// Find a way to avoid this cast
|
||||
self.navigationRouters[navigationController] = navigationRouter as? NavigationRouter
|
||||
navigationRouters[navigationController] = navigationRouter as? NavigationRouter
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,10 +87,10 @@ class NavigationRouterStore: NavigationRouterStoreProtocol {
|
||||
return
|
||||
}
|
||||
|
||||
if let existingNavigationRouter = self.findNavigationRouter(for: navigationController), existingNavigationRouter !== navigationRouter {
|
||||
if let existingNavigationRouter = findNavigationRouter(for: navigationController), existingNavigationRouter !== navigationRouter {
|
||||
fatalError("\(existingNavigationRouter) is already tied to the same navigation controller as \(navigationRouter). We should have only one NavigationRouter per navigation controller")
|
||||
}
|
||||
|
||||
self.removeNavigationRouter(for: navigationController)
|
||||
removeNavigationRouter(for: navigationController)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
@@ -24,7 +24,7 @@ protocol Presentable {
|
||||
|
||||
extension UIViewController: Presentable {
|
||||
public func toPresentable() -> UIViewController {
|
||||
return self
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ extension Presentable {
|
||||
/// Returns a new module from the presentable without a pop completion block
|
||||
/// - Returns: Module
|
||||
func toModule() -> NavigationModule {
|
||||
return NavigationModule(presentable: self, popCompletion: nil)
|
||||
NavigationModule(presentable: self, popCompletion: nil)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,9 +33,9 @@ final class RootRouter: RootRouterType {
|
||||
|
||||
let window: UIWindow
|
||||
|
||||
/// The root view controller currently presented
|
||||
/// The root view controller currently presented
|
||||
var rootViewController: UIViewController? {
|
||||
return self.window.rootViewController
|
||||
window.rootViewController
|
||||
}
|
||||
|
||||
// MARK: - Setup
|
||||
@@ -47,23 +47,23 @@ final class RootRouter: RootRouterType {
|
||||
// MARK: - Public methods
|
||||
|
||||
func setRootModule(_ module: Presentable) {
|
||||
self.updateRootViewController(rootViewController: module.toPresentable(), animated: false, completion: nil)
|
||||
self.window.makeKeyAndVisible()
|
||||
updateRootViewController(rootViewController: module.toPresentable(), animated: false, completion: nil)
|
||||
window.makeKeyAndVisible()
|
||||
}
|
||||
|
||||
func dismissRootModule(animated: Bool, completion: (() -> Void)?) {
|
||||
self.updateRootViewController(rootViewController: nil, animated: animated, completion: completion)
|
||||
updateRootViewController(rootViewController: nil, animated: animated, completion: completion)
|
||||
}
|
||||
|
||||
func presentModule(_ module: Presentable, animated: Bool, completion: (() -> Void)?) {
|
||||
let viewControllerPresenter = self.rootViewController?.presentedViewController ?? self.rootViewController
|
||||
let viewControllerPresenter = rootViewController?.presentedViewController ?? rootViewController
|
||||
|
||||
viewControllerPresenter?.present(module.toPresentable(), animated: animated, completion: completion)
|
||||
self.presentedModule = module
|
||||
presentedModule = module
|
||||
}
|
||||
|
||||
func dismissModule(animated: Bool, completion: (() -> Void)?) {
|
||||
self.presentedModule?.toPresentable().dismiss(animated: animated, completion: completion)
|
||||
presentedModule?.toPresentable().dismiss(animated: animated, completion: completion)
|
||||
}
|
||||
|
||||
// MARK: - Private methods
|
||||
@@ -76,11 +76,11 @@ final class RootRouter: RootRouterType {
|
||||
UIView.setAnimationsEnabled(false)
|
||||
self.window.rootViewController = rootViewController
|
||||
UIView.setAnimationsEnabled(oldState)
|
||||
}, completion: { (_: Bool) -> Void in
|
||||
}, completion: { _ in
|
||||
completion?()
|
||||
})
|
||||
} else {
|
||||
self.window.rootViewController = rootViewController
|
||||
window.rootViewController = rootViewController
|
||||
completion?()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,12 +19,12 @@ import UIKit
|
||||
/// Protocol describing a router that wraps the root navigation of the application.
|
||||
/// Routers are used to be passed between coordinators. They handles only `physical` navigation.
|
||||
@MainActor
|
||||
protocol RootRouterType: AnyObject {
|
||||
protocol RootRouterType: AnyObject {
|
||||
|
||||
/// Update the root view controller
|
||||
///
|
||||
/// - Parameter module: The new root view controller to set
|
||||
func setRootModule(_ module: Presentable)
|
||||
func setRootModule(_ module: Presentable)
|
||||
|
||||
/// Dismiss the root view controller
|
||||
///
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2022 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -16,11 +16,9 @@
|
||||
|
||||
import SwiftUI
|
||||
|
||||
// swiftlint:disable private_over_fileprivate
|
||||
|
||||
/// Positions this view within an invisible frame that fills the width of its parent view,
|
||||
/// whilst limiting the width of the content to a readable size (which is customizable).
|
||||
fileprivate struct ReadableFrameModifier: ViewModifier {
|
||||
private struct ReadableFrameModifier: ViewModifier {
|
||||
var maxWidth: CGFloat
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -27,9 +27,7 @@ extension BindableState where BindStateType == Void {
|
||||
/// We provide a default implementation for the Void type so that we can have `ViewState` that
|
||||
/// just doesn't include/take advantage of the bindings.
|
||||
var bindings: Void {
|
||||
get {
|
||||
|
||||
}
|
||||
get { }
|
||||
set {
|
||||
fatalError("Can't bind to the default Void binding.")
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
import Foundation
|
||||
|
||||
/// A constrained and concise interface for interacting with the ViewModel.
|
||||
///
|
||||
@@ -96,8 +96,8 @@ class StateStoreViewModel<State: BindableState, ViewAction> {
|
||||
// MARK: Setup
|
||||
|
||||
init(initialViewState: State) {
|
||||
self.context = Context(initialViewState: initialViewState)
|
||||
self.context.viewActions.sink { [weak self] action in
|
||||
context = Context(initialViewState: initialViewState)
|
||||
context.viewActions.sink { [weak self] action in
|
||||
guard let self = self else { return }
|
||||
|
||||
Task { await self.process(viewAction: action) }
|
||||
|
||||
@@ -52,7 +52,7 @@ final class ActivityIndicatorPresenter: ActivityIndicatorPresenterType {
|
||||
|
||||
view.isUserInteractionEnabled = false
|
||||
|
||||
let backgroundOverlayView = self.createBackgroundOverlayView(with: view.frame)
|
||||
let backgroundOverlayView = createBackgroundOverlayView(with: view.frame)
|
||||
|
||||
let activityIndicatorView = ActivityIndicatorView()
|
||||
|
||||
@@ -89,9 +89,9 @@ final class ActivityIndicatorPresenter: ActivityIndicatorPresenterType {
|
||||
}
|
||||
|
||||
func removeCurrentActivityIndicator(animated: Bool, completion: (() -> Void)? = nil) {
|
||||
guard let presentingView = self.presentingView,
|
||||
let backgroundOverlayView = self.backgroundOverlayView,
|
||||
let activityIndicatorView = self.activityIndicatorView else {
|
||||
guard let presentingView = presentingView,
|
||||
let backgroundOverlayView = backgroundOverlayView,
|
||||
let activityIndicatorView = activityIndicatorView else {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -29,23 +29,23 @@ final class ActivityIndicatorView: UIView {
|
||||
|
||||
// MARK: Outlets
|
||||
|
||||
@IBOutlet private weak var activityIndicatorView: UIActivityIndicatorView!
|
||||
@IBOutlet private weak var activityIndicatorBackgroundView: UIView!
|
||||
@IBOutlet private var activityIndicatorView: UIActivityIndicatorView!
|
||||
@IBOutlet private var activityIndicatorBackgroundView: UIView!
|
||||
|
||||
// MARK: Public
|
||||
|
||||
var color: UIColor? {
|
||||
get {
|
||||
return activityIndicatorView.color
|
||||
activityIndicatorView.color
|
||||
}
|
||||
set {
|
||||
set {
|
||||
activityIndicatorView.color = newValue
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
private func commonInit() {
|
||||
private func commonInit() {
|
||||
activityIndicatorBackgroundView.layer.masksToBounds = true
|
||||
}
|
||||
|
||||
@@ -68,8 +68,8 @@ final class ActivityIndicatorView: UIView {
|
||||
// MARK: - Overrides
|
||||
|
||||
override var intrinsicContentSize: CGSize {
|
||||
return CGSize(width: activityIndicatorView.intrinsicContentSize.width + Constants.activityIndicatorMargin.width,
|
||||
height: activityIndicatorView.intrinsicContentSize.height + Constants.activityIndicatorMargin.height)
|
||||
CGSize(width: activityIndicatorView.intrinsicContentSize.width + Constants.activityIndicatorMargin.width,
|
||||
height: activityIndicatorView.intrinsicContentSize.height + Constants.activityIndicatorMargin.height)
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
@@ -91,22 +91,22 @@ final class ActivityIndicatorView: UIView {
|
||||
|
||||
private extension UIView {
|
||||
static var nib: UINib {
|
||||
return UINib(nibName: String(describing: self), bundle: Bundle(for: self))
|
||||
UINib(nibName: String(describing: self), bundle: Bundle(for: self))
|
||||
}
|
||||
|
||||
func loadNibContent() {
|
||||
let layoutAttributes: [NSLayoutConstraint.Attribute] = [.top, .leading, .bottom, .trailing]
|
||||
for case let view as UIView in type(of: self).nib.instantiate(withOwner: self, options: nil) {
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
addSubview(view)
|
||||
NSLayoutConstraint.activate(layoutAttributes.map { attribute in
|
||||
NSLayoutConstraint(
|
||||
item: view, attribute: attribute,
|
||||
relatedBy: .equal,
|
||||
toItem: self, attribute: attribute,
|
||||
multiplier: 1, constant: 0.0
|
||||
)
|
||||
})
|
||||
}
|
||||
let layoutAttributes: [NSLayoutConstraint.Attribute] = [.top, .leading, .bottom, .trailing]
|
||||
for case let view as UIView in type(of: self).nib.instantiate(withOwner: self, options: nil) {
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
addSubview(view)
|
||||
NSLayoutConstraint.activate(layoutAttributes.map { attribute in
|
||||
NSLayoutConstraint(
|
||||
item: view, attribute: attribute,
|
||||
relatedBy: .equal,
|
||||
toItem: self, attribute: attribute,
|
||||
multiplier: 1, constant: 0.0
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -49,15 +49,14 @@ final class LabelledActivityIndicatorView: UIView {
|
||||
return view
|
||||
}()
|
||||
|
||||
private let label: UILabel = {
|
||||
UILabel()
|
||||
}()
|
||||
private let label = UILabel()
|
||||
|
||||
init(text: String) {
|
||||
super.init(frame: .zero)
|
||||
setup(text: text)
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -20,7 +20,7 @@ import UIKit
|
||||
class RectangleToastView: UIView {
|
||||
|
||||
private enum Constants {
|
||||
static let padding: UIEdgeInsets = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
|
||||
static let padding = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
|
||||
static let cornerRadius: CGFloat = 8.0
|
||||
}
|
||||
|
||||
@@ -81,6 +81,7 @@ class RectangleToastView: UIView {
|
||||
layer.masksToBounds = true
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -23,7 +23,7 @@ class RoundedToastView: UIView {
|
||||
let opacity: Float
|
||||
}
|
||||
|
||||
private struct Constants {
|
||||
private enum Constants {
|
||||
static let padding = UIEdgeInsets(top: 10, left: 12, bottom: 10, right: 12)
|
||||
static let activityIndicatorScale = CGFloat(0.75)
|
||||
static let imageViewSize = CGFloat(15)
|
||||
@@ -57,15 +57,14 @@ class RoundedToastView: UIView {
|
||||
return stack
|
||||
}()
|
||||
|
||||
private let label: UILabel = {
|
||||
UILabel()
|
||||
}()
|
||||
private let label = UILabel()
|
||||
|
||||
init(viewState: ToastViewState) {
|
||||
super.init(frame: .zero)
|
||||
setup(viewState: viewState)
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -19,7 +19,7 @@ import UIKit
|
||||
/// A presenter responsible for showing / hiding a toast view for loading spinners or success messages.
|
||||
/// It is managed by an `UserIndicator`, meaning the `present` and `dismiss` methods will be called when the parent `UserIndicator` starts or completes.
|
||||
class ToastViewPresenter: UserIndicatorViewPresentable {
|
||||
struct Constants {
|
||||
enum Constants {
|
||||
static let navigationBarPatting = CGFloat(10)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2022 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2022 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
@@ -18,7 +18,7 @@ public struct WeakDictionary<Key: Hashable, Value: AnyObject> {
|
||||
|
||||
public init(dictionary: [Key: Value]) {
|
||||
var newStorage = [Key: WeakDictionaryReference<Value>]()
|
||||
dictionary.forEach({ key, value in newStorage[key] = WeakDictionaryReference<Value>(value: value) })
|
||||
dictionary.forEach { key, value in newStorage[key] = WeakDictionaryReference<Value>(value: value) }
|
||||
self.init(storage: newStorage)
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ public struct WeakDictionary<Key: Hashable, Value: AnyObject> {
|
||||
}
|
||||
|
||||
public func weakDictionary() -> WeakDictionary<Key, Value> {
|
||||
return self[startIndex ..< endIndex]
|
||||
self[startIndex..<endIndex]
|
||||
}
|
||||
|
||||
public func dictionary() -> [Key: Value] {
|
||||
@@ -52,15 +52,15 @@ extension WeakDictionary: Collection {
|
||||
public typealias Index = DictionaryIndex<Key, WeakDictionaryReference<Value>>
|
||||
|
||||
public var startIndex: Index {
|
||||
return storage.startIndex
|
||||
storage.startIndex
|
||||
}
|
||||
|
||||
public var endIndex: Index {
|
||||
return storage.endIndex
|
||||
storage.endIndex
|
||||
}
|
||||
|
||||
public func index(after index: Index) -> Index {
|
||||
return storage.index(after: index)
|
||||
storage.index(after: index)
|
||||
}
|
||||
|
||||
public subscript(position: Index) -> (Key, WeakDictionaryReference<Value>) {
|
||||
@@ -87,18 +87,18 @@ extension WeakDictionary: Collection {
|
||||
}
|
||||
|
||||
public subscript(bounds: Range<Index>) -> WeakDictionary<Key, Value> {
|
||||
let subStorage = storage[bounds.lowerBound ..< bounds.upperBound]
|
||||
let subStorage = storage[bounds.lowerBound..<bounds.upperBound]
|
||||
var newStorage = [Key: WeakDictionaryReference<Value>]()
|
||||
|
||||
subStorage.filter { _, value in return value.value != nil }
|
||||
subStorage.filter { _, value in value.value != nil }
|
||||
.forEach { key, value in newStorage[key] = value }
|
||||
|
||||
return WeakDictionary<Key, Value>(storage: newStorage)
|
||||
}
|
||||
}
|
||||
|
||||
extension Dictionary where Value: AnyObject {
|
||||
public func weakDictionary() -> WeakDictionary<Key, Value> {
|
||||
return WeakDictionary<Key, Value>(dictionary: self)
|
||||
public extension Dictionary where Value: AnyObject {
|
||||
func weakDictionary() -> WeakDictionary<Key, Value> {
|
||||
WeakDictionary<Key, Value>(dictionary: self)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct WeakDictionaryKey<Key: AnyObject & Hashable, Value: AnyObject> : Hashable {
|
||||
public struct WeakDictionaryKey<Key: AnyObject & Hashable, Value: AnyObject>: Hashable {
|
||||
|
||||
private weak var baseKey: Key?
|
||||
private let hash: Int
|
||||
@@ -22,7 +22,7 @@ public struct WeakDictionaryKey<Key: AnyObject & Hashable, Value: AnyObject> : H
|
||||
}
|
||||
|
||||
public static func == (lhs: WeakDictionaryKey, rhs: WeakDictionaryKey) -> Bool {
|
||||
return (lhs.baseKey != nil && rhs.baseKey != nil && lhs.baseKey == rhs.baseKey)
|
||||
(lhs.baseKey != nil && rhs.baseKey != nil && lhs.baseKey == rhs.baseKey)
|
||||
|| lhs.hashValue == rhs.hashValue
|
||||
}
|
||||
|
||||
@@ -35,6 +35,6 @@ public struct WeakDictionaryKey<Key: AnyObject & Hashable, Value: AnyObject> : H
|
||||
}
|
||||
|
||||
public var key: Key? {
|
||||
return baseKey
|
||||
baseKey
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,6 @@ public struct WeakDictionaryReference<Value: AnyObject> {
|
||||
}
|
||||
|
||||
public var value: Value? {
|
||||
return referencedValue
|
||||
referencedValue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,11 +48,11 @@ public struct WeakKeyDictionary<Key: AnyObject & Hashable, Value: AnyObject> {
|
||||
}
|
||||
|
||||
public func weakDictionary() -> WeakDictionary<Key, Value> {
|
||||
return dictionary().weakDictionary()
|
||||
dictionary().weakDictionary()
|
||||
}
|
||||
|
||||
public func weakKeyDictionary() -> WeakKeyDictionary<Key, Value> {
|
||||
return self[startIndex ..< endIndex]
|
||||
self[startIndex..<endIndex]
|
||||
}
|
||||
|
||||
public func dictionary() -> [Key: Value] {
|
||||
@@ -73,15 +73,15 @@ extension WeakKeyDictionary: Collection {
|
||||
public typealias Index = DictionaryIndex<WeakDictionaryKey<Key, Value>, WeakDictionaryReference<Value>>
|
||||
|
||||
public var startIndex: Index {
|
||||
return storage.startIndex
|
||||
storage.startIndex
|
||||
}
|
||||
|
||||
public var endIndex: Index {
|
||||
return storage.endIndex
|
||||
storage.endIndex
|
||||
}
|
||||
|
||||
public func index(after index: Index) -> Index {
|
||||
return storage.index(after: index)
|
||||
storage.index(after: index)
|
||||
}
|
||||
|
||||
public subscript(position: Index) -> (WeakDictionaryKey<Key, Value>, WeakDictionaryReference<Value>) {
|
||||
@@ -90,7 +90,7 @@ extension WeakKeyDictionary: Collection {
|
||||
|
||||
public subscript(key: Key) -> Value? {
|
||||
get {
|
||||
return storage[WeakDictionaryKey<Key, Value>(key: key)]
|
||||
storage[WeakDictionaryKey<Key, Value>(key: key)]
|
||||
}
|
||||
|
||||
set {
|
||||
@@ -101,24 +101,24 @@ extension WeakKeyDictionary: Collection {
|
||||
}
|
||||
|
||||
public subscript(bounds: Range<Index>) -> WeakKeyDictionary<Key, Value> {
|
||||
let subStorage = storage[bounds.lowerBound ..< bounds.upperBound]
|
||||
let subStorage = storage[bounds.lowerBound..<bounds.upperBound]
|
||||
var newStorage = WeakDictionary<WeakDictionaryKey<Key, Value>, Value>()
|
||||
|
||||
subStorage.filter { key, value in return key.key != nil && value.value != nil }
|
||||
subStorage.filter { key, value in key.key != nil && value.value != nil }
|
||||
.forEach { key, value in newStorage[key] = value.value }
|
||||
|
||||
return WeakKeyDictionary<Key, Value>(storage: newStorage)
|
||||
}
|
||||
}
|
||||
|
||||
extension WeakDictionary where Key: AnyObject {
|
||||
public func weakKeyDictionary(valuesRetainedByKey: Bool = false) -> WeakKeyDictionary<Key, Value> {
|
||||
return WeakKeyDictionary<Key, Value>(dictionary: dictionary(), valuesRetainedByKey: valuesRetainedByKey)
|
||||
public extension WeakDictionary where Key: AnyObject {
|
||||
func weakKeyDictionary(valuesRetainedByKey: Bool = false) -> WeakKeyDictionary<Key, Value> {
|
||||
WeakKeyDictionary<Key, Value>(dictionary: dictionary(), valuesRetainedByKey: valuesRetainedByKey)
|
||||
}
|
||||
}
|
||||
|
||||
extension Dictionary where Key: AnyObject, Value: AnyObject {
|
||||
public func weakKeyDictionary(valuesRetainedByKey: Bool = false) -> WeakKeyDictionary<Key, Value> {
|
||||
return WeakKeyDictionary<Key, Value>(dictionary: self, valuesRetainedByKey: valuesRetainedByKey)
|
||||
public extension Dictionary where Key: AnyObject, Value: AnyObject {
|
||||
func weakKeyDictionary(valuesRetainedByKey: Bool = false) -> WeakKeyDictionary<Key, Value> {
|
||||
WeakKeyDictionary<Key, Value>(dictionary: self, valuesRetainedByKey: valuesRetainedByKey)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user