Skip to content

Commit

Permalink
feat(global): init local CRUD
Browse files Browse the repository at this point in the history
  • Loading branch information
PierreBrisorgueil committed May 7, 2019
1 parent 65ee73b commit f960634
Show file tree
Hide file tree
Showing 49 changed files with 1,517 additions and 635 deletions.
4 changes: 3 additions & 1 deletion Cartfile
@@ -1,7 +1,9 @@
github "ReactiveX/RxSwift"
github "RxSwiftCommunity/RxOptional"
github "RxSwiftCommunity/RxFlow"
github "ReactorKit/ReactorKit"
github "CocoaLumberjack/CocoaLumberjack"
github "AliSoftware/Reusable"
github "SwiftyJSON/SwiftyJSON"
github "RxSwiftCommunity/RxDataSources"
github "RxSwiftCommunity/RxDataSources"
github "SnapKit/SnapKit"
6 changes: 4 additions & 2 deletions Cartfile.resolved
@@ -1,7 +1,9 @@
github "AliSoftware/Reusable" "4.0.5"
github "CocoaLumberjack/CocoaLumberjack" "3.5.2"
github "CocoaLumberjack/CocoaLumberjack" "3.5.3"
github "ReactiveX/RxSwift" "4.5.0"
github "ReactorKit/ReactorKit" "1.2.1"
github "RxSwiftCommunity/RxDataSources" "3.1.0"
github "RxSwiftCommunity/RxFlow" "2.1.0"
github "RxSwiftCommunity/RxFlow" "2.2.0"
github "RxSwiftCommunity/RxOptional" "3.6.2"
github "SnapKit/SnapKit" "5.0.0"
github "SwiftyJSON/SwiftyJSON" "5.0.0"
202 changes: 124 additions & 78 deletions waosSwift.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions waosSwift/config/headers/BridgingHeader.h
@@ -1,4 +1,6 @@
@import RxSwift;
@import RxOptional;
@import RxCocoa;
@import RxFlow;
@import SwiftyJSON;
@import SnapKit;
6 changes: 3 additions & 3 deletions waosSwift/config/localizations/Strings.swift
Expand Up @@ -11,16 +11,16 @@ import Foundation
// swiftlint:disable explicit_type_interface function_parameter_count identifier_name line_length
// swiftlint:disable nesting type_body_length type_name
internal enum L10n {
/// title 1
internal static let firstTitle = L10n.tr("Localizable", "first_title")
/// this is the first page of the application, it will only be affixed once after installation. We call it onBoarding.
internal static let onBoardingIntroduction = L10n.tr("Localizable", "onBoarding_introduction")
/// onBoarding
internal static let onBoardingTitle = L10n.tr("Localizable", "onBoarding_title")
/// I'm in !
internal static let onBoardingValidation = L10n.tr("Localizable", "onBoarding_validation")
/// title 2
/// Example
internal static let secondTitle = L10n.tr("Localizable", "second_title")
/// Tasks
internal static let taskTitle = L10n.tr("Localizable", "task_title")
}
// swiftlint:enable explicit_type_interface function_parameter_count identifier_name line_length
// swiftlint:enable nesting type_body_length type_name
Expand Down
4 changes: 2 additions & 2 deletions waosSwift/config/localizations/en.lproj/Localizable.strings
Expand Up @@ -8,7 +8,7 @@
"onBoarding_validation"= "I'm in !";

// first
"first_title"= "title 1";
"task_title"= "Tasks";

// second
"second_title"= "title 2";
"second_title"= "Example";
Expand Up @@ -8,7 +8,7 @@
"onBoarding_validation"= "J'en suis !";

// first
"first_title"= "titre 1";
"task_title"= "Tasks";

// second
"second_title"= "titre 2";
Expand Down
21 changes: 21 additions & 0 deletions waosSwift/lib/helpers/Array.swift
@@ -0,0 +1,21 @@
extension Array where Element: Equatable {

@discardableResult mutating func remove(object: Element) -> Bool {
if let index = index(of: object) {
self.remove(at: index)
return true
}
return false
}

@discardableResult mutating func remove(where predicate: (Array.Iterator.Element) -> Bool) -> Bool {
if let index = self.index(where: { (element) -> Bool in
return predicate(element)
}) {
self.remove(at: index)
return true
}
return false
}

}
66 changes: 66 additions & 0 deletions waosSwift/lib/helpers/ReusableKit/ReusableKit.swift
@@ -0,0 +1,66 @@
#if os(iOS)
import UIKit

public protocol CellType: class {
var reuseIdentifier: String? { get }
}

/// A generic class that represents reusable cells.
public struct ReusableCell<Cell: CellType> {
public typealias Class = Cell

public let `class`: Class.Type = Class.self
public let identifier: String
public let nib: UINib?

/// Create and returns a new `ReusableCell` instance.
///
/// - parameter identifier: A reuse identifier. Use random UUID string if identifier is not provided.
/// - parameter nib: A `UINib` instance. Use this when registering from xib.
public init(identifier: String? = nil, nib: UINib? = nil) {
self.identifier = nib?.instantiate(withOwner: nil, options: nil).lazy
.compactMap { ($0 as? CellType)?.reuseIdentifier }
.first ?? identifier ?? UUID().uuidString
self.nib = nib
}

/// A convenience initializer.
///
/// - parameter identifier: A reuse identifier. Use random UUID string if identifier is not provided.
/// - parameter nibName: A name of nib.
public init(identifier: String? = nil, nibName: String) {
let nib = UINib(nibName: nibName, bundle: nil)
self.init(identifier: identifier, nib: nib)
}
}

public protocol ViewType: class {
}

/// A generic class that represents reusable views.
public struct ReusableView<View: ViewType> {
public typealias Class = View

public let `class`: Class.Type = Class.self
public let identifier: String
public let nib: UINib?

/// Create and returns a new `ReusableView` instance.
///
/// - parameter identifier: A reuse identifier. Use random UUID string if identifier is not provided.
/// - parameter nib: A `UINib` instance. Use this when registering from xib.
public init(identifier: String? = nil, nib: UINib? = nil) {
self.identifier = identifier ?? UUID().uuidString
self.nib = nib
}

/// A convenience initializer.
///
/// - parameter identifier: A reuse identifier. Use random UUID string if identifier is not provided.
/// - parameter nibName: A name of nib.
public init(identifier: String? = nil, nibName: String) {
let nib = UINib(nibName: nibName, bundle: nil)
self.init(identifier: identifier, nib: nib)
}
}
#endif
@@ -0,0 +1,72 @@
#if os(iOS)
import UIKit

/// An enumeration that represents UICollectionView supplementary view kind.
public enum SupplementaryViewKind: String {
case header, footer

public init?(rawValue: String) {
switch rawValue {
case UICollectionView.elementKindSectionHeader: self = .header
case UICollectionView.elementKindSectionFooter: self = .footer
default: return nil
}
}

public var rawValue: String {
switch self {
case .header: return UICollectionView.elementKindSectionHeader
case .footer: return UICollectionView.elementKindSectionFooter
}
}
}

extension UICollectionViewCell: CellType {
}

extension UIView: ViewType {
}

extension UICollectionView {

// MARK: Cell
/// Registers a generic cell for use in creating new collection view cells.
public func register<Cell>(_ cell: ReusableCell<Cell>) {
if let nib = cell.nib {
self.register(nib, forCellWithReuseIdentifier: cell.identifier)
} else {
self.register(Cell.self, forCellWithReuseIdentifier: cell.identifier)
}
}

/// Returns a generic reusable cell located by its identifier.
public func dequeue<Cell>(_ cell: ReusableCell<Cell>, for indexPath: IndexPath) -> Cell {
return self.dequeueReusableCell(withReuseIdentifier: cell.identifier, for: indexPath) as! Cell
}

// MARK: Supplementary View
/// Registers a generic view for use in creating new supplementary views for the collection view.
public func register<View>(_ view: ReusableView<View>, kind: SupplementaryViewKind) {
self.register(view, kind: kind.rawValue)
}

/// Registers a generic view for use in creating new supplementary views for the collection view.
public func register<View>(_ view: ReusableView<View>, kind: String) {
if let nib = view.nib {
self.register(nib, forSupplementaryViewOfKind: kind, withReuseIdentifier: view.identifier)
} else {
self.register(View.self, forSupplementaryViewOfKind: kind, withReuseIdentifier: view.identifier)
}
}

/// Returns a generic reusable supplementary view located by its identifier and kind.
public func dequeue<View>(_ view: ReusableView<View>, kind: String, for indexPath: IndexPath) -> View {
return self.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: view.identifier, for: indexPath) as! View
}

/// Returns a generic reusable supplementary view located by its identifier and kind.
public func dequeue<View>(_ view: ReusableView<View>, kind: SupplementaryViewKind, for indexPath: IndexPath) -> View {
return self.dequeue(view, kind: kind.rawValue, for: indexPath)
}
}
#endif
44 changes: 44 additions & 0 deletions waosSwift/lib/helpers/ReusableKit/UITableView+ReusableKit.swift
@@ -0,0 +1,44 @@
#if os(iOS)
import UIKit

extension UITableViewCell: CellType {
}

extension UITableView {

// MARK: Cell
/// Registers a generic cell for use in creating new table cells.
public func register<Cell>(_ cell: ReusableCell<Cell>) {
if let nib = cell.nib {
self.register(nib, forCellReuseIdentifier: cell.identifier)
} else {
self.register(Cell.self, forCellReuseIdentifier: cell.identifier)
}
}

/// Returns a generic reusable cell located by its identifier.
public func dequeue<Cell>(_ cell: ReusableCell<Cell>) -> Cell? {
return self.dequeueReusableCell(withIdentifier: cell.identifier) as? Cell
}

/// Returns a generic reusable cell located by its identifier.
public func dequeue<Cell>(_ cell: ReusableCell<Cell>, for indexPath: IndexPath) -> Cell {
return self.dequeueReusableCell(withIdentifier: cell.identifier, for: indexPath) as! Cell
}

// MARK: View
/// Registers a generic view for use in creating new table header or footer views.
public func register<View>(_ cell: ReusableView<View>) {
if let nib = cell.nib {
self.register(nib, forHeaderFooterViewReuseIdentifier: cell.identifier)
} else {
self.register(View.self, forHeaderFooterViewReuseIdentifier: cell.identifier)
}
}

/// Returns a generic reusable header of footer view located by its identifier.
public func dequeue<View>(_ view: ReusableView<View>) -> View? {
return self.dequeueReusableHeaderFooterView(withIdentifier: view.identifier) as? View
}
}
#endif
40 changes: 40 additions & 0 deletions waosSwift/lib/helpers/Rx/Array+SectionModel.swift
@@ -0,0 +1,40 @@
import RxDataSources

extension Array where Element: SectionModelType {

public subscript(indexPath: IndexPath) -> Element.Item {
get {
return self[indexPath.section].items[indexPath.item]
}
mutating set {
self.update(section: indexPath.section) { items in
items[indexPath.item] = newValue
}
}
}

public mutating func insert(_ newElement: Element.Item, at indexPath: IndexPath) {
self.update(section: indexPath.section) { items in
items.insert(newElement, at: indexPath.item)
}
}

@discardableResult
public mutating func remove(at indexPath: IndexPath) -> Element.Item {
return self.update(section: indexPath.section) { items in
return items.remove(at: indexPath.item)
}
}

private mutating func replace(section: Int, items: [Element.Item]) {
self[section] = Element.init(original: self[section], items: items)
}

private mutating func update<T>(section: Int, mutate: (inout [Element.Item]) -> T) -> T {
var items = self[section].items
let value = mutate(&items)
self[section] = Element.init(original: self[section], items: items)
return value
}

}
40 changes: 40 additions & 0 deletions waosSwift/lib/helpers/Rx/NSViewController+Rx.swift
@@ -0,0 +1,40 @@
#if os(macOS)
import AppKit

import RxCocoa
import RxSwift

public extension Reactive where Base: NSViewController {
var viewDidLoad: ControlEvent<Void> {
let source = self.methodInvoked(#selector(Base.viewDidLoad)).map { _ in }
return ControlEvent(events: source)
}

var viewWillAppear: ControlEvent<Void> {
let source = self.methodInvoked(#selector(Base.viewWillAppear)).map { _ in }
return ControlEvent(events: source)
}
var viewDidAppear: ControlEvent<Void> {
let source = self.methodInvoked(#selector(Base.viewDidAppear)).map { _ in }
return ControlEvent(events: source)
}

var viewWillDisappear: ControlEvent<Void> {
let source = self.methodInvoked(#selector(Base.viewWillDisappear)).map { _ in }
return ControlEvent(events: source)
}
var viewDidDisappear: ControlEvent<Void> {
let source = self.methodInvoked(#selector(Base.viewDidDisappear)).map { _ in }
return ControlEvent(events: source)
}

var viewWillLayout: ControlEvent<Void> {
let source = self.methodInvoked(#selector(Base.viewWillLayout)).map { _ in }
return ControlEvent(events: source)
}
var viewDidLayout: ControlEvent<Void> {
let source = self.methodInvoked(#selector(Base.viewDidLayout)).map { _ in }
return ControlEvent(events: source)
}
}
#endif
21 changes: 21 additions & 0 deletions waosSwift/lib/helpers/Rx/UICollectionView+RxReusableKit.swift
@@ -0,0 +1,21 @@
import RxCocoa
import RxSwift

#if os(iOS)
import UIKit

extension Reactive where Base: UICollectionView {
public func items<S: Sequence, Cell: UICollectionViewCell, O: ObservableType>(
_ reusableCell: ReusableCell<Cell>
) -> (_ source: O)
-> (_ configureCell: @escaping (Int, S.Iterator.Element, Cell) -> Void)
-> Disposable
where O.E == S {
return { source in
return { configureCell in
return self.items(cellIdentifier: reusableCell.identifier, cellType: Cell.self)(source)(configureCell)
}
}
}
}
#endif

0 comments on commit f960634

Please sign in to comment.