Skip to content

Commit

Permalink
Added table cell. Added diffable assets. Clean code.
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanvorobei committed Feb 15, 2022
1 parent 767263e commit a70c627
Show file tree
Hide file tree
Showing 10 changed files with 252 additions and 52 deletions.
25 changes: 5 additions & 20 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,11 @@ let package = Package(
)
],
dependencies: [
.package(
name: "SPAlert",
url: "https://github.com/ivanvorobei/SPAlert", .upToNextMajor(from: "4.2.0")
),
.package(
name: "NativeUIKit",
url: "https://github.com/ivanvorobei/NativeUIKit", .upToNextMajor(from: "1.3.7")
),
.package(
name: "SPFirebase",
url: "https://github.com/ivanvorobei/SPFirebase", .upToNextMajor(from: "1.0.6")
),
.package(
name: "SPSafeSymbols",
url: "https://github.com/sparrowcode/SPSafeSymbols", .upToNextMajor(from: "1.0.5")
),
.package(
name: "Nuke",
url: "https://github.com/kean/Nuke", .upToNextMajor(from: "10.7.1")
)
.package(url: "https://github.com/ivanvorobei/SPAlert", .upToNextMajor(from: "4.2.0")),
.package(url: "https://github.com/ivanvorobei/NativeUIKit", .upToNextMajor(from: "1.3.7")),
.package(url: "https://github.com/ivanvorobei/SPFirebase", .upToNextMajor(from: "1.0.6")),
.package(url: "https://github.com/sparrowcode/SPSafeSymbols", .upToNextMajor(from: "1.0.5")),
.package(url: "https://github.com/kean/Nuke", .upToNextMajor(from: "10.7.1"))
],
targets: [
.target(
Expand Down
43 changes: 24 additions & 19 deletions Sources/SPProfiling/Data/Texts.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ enum Texts {
public static var save: String { NSLocalizedString("save", bundle: .module, comment: "") }
public static var cancel: String { NSLocalizedString("cancel", bundle: .module, comment: "") }

// MARK: - Error

enum Error {

static var not_found: String { NSLocalizedString("error not found", bundle: .module, comment: "") }
Expand All @@ -39,29 +41,32 @@ enum Texts {
static var cant_present: String { NSLocalizedString("error auth cant present", bundle: .module, comment: "") }
static var cant_prepare_requerid_data: String { NSLocalizedString("error auth cant prepare requerid data", bundle: .module, comment: "") }
}
}

enum Profile {

static var name_didnt_set: String { NSLocalizedString("profile name didint set", bundle: .module, comment: "") }

enum Error {
enum Profile {

static var name_short: String { NSLocalizedString("profile error name short", bundle: .module, comment: "") }
static var name_long: String { NSLocalizedString("profile error name long", bundle: .module, comment: "") }
static var empty_name: String { NSLocalizedString("profile error empty name", bundle: .module, comment: "") }
static var big_avatar_width: String { NSLocalizedString("profile error big avatar width", bundle: .module, comment: "") }
static var big_avatar_size: String { NSLocalizedString("profile error big avatar size", bundle: .module, comment: "") }
static var name_short: String { NSLocalizedString("error profile name short", bundle: .module, comment: "") }
static var name_long: String { NSLocalizedString("error profile name long", bundle: .module, comment: "") }
static var empty_name: String { NSLocalizedString("error profile empty name", bundle: .module, comment: "") }
static var big_avatar_width: String { NSLocalizedString("error profile big avatar width", bundle: .module, comment: "") }
static var big_avatar_size: String { NSLocalizedString("error profile big avatar size", bundle: .module, comment: "") }
}
}

// MARK: - Auth

enum Auth {

enum Auth {

static var continue_anonymously: String { NSLocalizedString("profile auth continue anonymously", bundle: .module, comment: "") }

static var title: String { NSLocalizedString("profile auth title", bundle: .module, comment: "") }
static var description: String { NSLocalizedString("profile auth description", bundle: .module, comment: "") }
static var footer_description: String { NSLocalizedString("profile auth footer description", bundle: .module, comment: "") }
}
static var sign_in: String { NSLocalizedString("auth sign in", bundle: .module, comment: "") }
static var continue_anonymously: String { NSLocalizedString("auth continue anonymously", bundle: .module, comment: "") }
static var description: String { NSLocalizedString("auth description", bundle: .module, comment: "") }
static var footer_description: String { NSLocalizedString("auth footer description", bundle: .module, comment: "") }
}

// MARK: - Profile

enum Profile {

static var placeholder_name: String { NSLocalizedString("profile placeholder name", bundle: .module, comment: "") }

enum Devices {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,13 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.


import UIKit
import SparrowKit
import NativeUIKit
import SPDiffable
import SPAlert

extension CurrentProfileController {
extension ProfileController {

internal func showTextFieldToChangeName() {
let alertController = UIAlertController(title: Texts.Profile.Actions.Rename.alert_title, message: Texts.Profile.Actions.Rename.alert_description, preferredStyle: .alert)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import SPDiffable
import SPSafeSymbols
import SPAlert

extension CurrentProfileController {
extension ProfileController {

internal func configureHeader() {
setProfile(profileModel, completion: { [weak self] in
Expand Down Expand Up @@ -99,7 +99,7 @@ extension CurrentProfileController {

internal func setProfile(_ profileModel: ProfileModel, completion: (()->())? = nil) {
headerView.nameLabel.text = profileModel.name
headerView.namePlaceholderLabel.text = Texts.Profile.name_didnt_set
headerView.namePlaceholderLabel.text = Texts.Profile.placeholder_name
if let email = profileModel.email { headerView.emailButton.setTitle(email) }
headerView.layoutSubviews()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,14 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.


import UIKit
import SparrowKit
import NativeUIKit
import SPDiffable
import SPSafeSymbols
import SPAlert

class CurrentProfileController: NativeProfileController {
class ProfileController: NativeProfileController {

internal var profileModel: ProfileModel

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

import UIKit
import SPDiffable

extension SPDiffableTableDataSource.CellProvider {

public static var profile: SPDiffableTableDataSource.CellProvider {
return SPDiffableTableDataSource.CellProvider() { (tableView, indexPath, item) -> UITableViewCell? in
guard let _ = item as? DiffableProfileItem else { return nil }
let cell = tableView.dequeueReusableCell(withClass: ProfileTableViewCell.self, for: indexPath)
return cell
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// The MIT License (MIT)
// Copyright © 2022 Ivan Vorobei ([email protected])
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import UIKit
import SPDiffable

open class DiffableProfileItem: SPDiffableActionableItem {

public static let id: String = "spprofiling-profile-item"

public init(action: SPDiffableActionableItem.Action? = nil) {
super.init(id: Self.id, action: action)
}
}
146 changes: 146 additions & 0 deletions Sources/SPProfiling/Interface/Profile/Table/ProfileTableViewCell.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
// The MIT License (MIT)
// Copyright © 2022 Ivan Vorobei ([email protected])
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import UIKit
import NativeUIKit
import SparrowKit

open class ProfileTableViewCell: SPTableViewCell {

public let titleLabel = SPLabel().do {
$0.numberOfLines = 1
$0.font = UIFont.preferredFont(forTextStyle: .title2, weight: .semibold)
$0.textColor = .label
}

public let descriptionLabel = SPLabel().do {
$0.numberOfLines = 1
$0.font = UIFont.preferredFont(forTextStyle: .footnote, weight: .regular)
$0.textColor = .secondaryLabel
}

public let avatarView = NativeAvatarView().do {
$0.isEditable = false
$0.placeholderImage = UIImage.system("person.crop.circle.fill", font: .systemFont(ofSize: 52, weight: .medium))
$0.avatarAppearance = .placeholder
}

// MARK: - Init

open override func commonInit() {
super.commonInit()
higlightStyle = .content
contentView.addSubviews(avatarView, titleLabel, descriptionLabel)
accessoryType = .disclosureIndicator
updateAppearance()
}

open override func prepareForReuse() {
super.prepareForReuse()
configureObservers()
updateAppearance()
}

deinit {
NotificationCenter.default.removeObserver(self)
}

// MARK: - Ovveride

open override func setHighlighted(_ highlighted: Bool, animated: Bool) {
super.setHighlighted(highlighted, animated: animated)
let higlightContent = (higlightStyle == .content)
if higlightContent {
[avatarView, titleLabel, descriptionLabel].forEach({ $0?.alpha = highlighted ? 0.6 : 1 })
}
}

// MARK: - Layout

open override func layoutSubviews() {
super.layoutSubviews()
avatarView.sizeToFit()
avatarView.setXToSuperviewLeftMargin()
avatarView.frame.origin.y = contentView.layoutMargins.top

let avatarRightSpace: CGFloat = NativeLayout.Spaces.default
let labelVerticalSpace: CGFloat = NativeLayout.Spaces.step / 2
let labelWidth = contentView.layoutWidth - avatarView.frame.width - avatarRightSpace
titleLabel.layoutDynamicHeight(width: labelWidth)
descriptionLabel.layoutDynamicHeight(width: labelWidth)

titleLabel.frame.origin.x = avatarView.frame.maxX + avatarRightSpace
descriptionLabel.frame.origin.x = titleLabel.frame.origin.x

let labelHeight = titleLabel.frame.height + labelVerticalSpace + descriptionLabel.frame.height
if (avatarView.frame.origin.y + labelHeight) > avatarView.frame.maxY {
titleLabel.frame.origin.y = contentView.layoutMargins.top
} else {
titleLabel.frame.origin.y = contentView.layoutMargins.top + (contentView.layoutHeight - labelHeight) / 2
}

descriptionLabel.frame.origin.y = titleLabel.frame.maxY + labelVerticalSpace
}

open override func sizeThatFits(_ size: CGSize) -> CGSize {
layoutSubviews()
return .init(width: size.width, height: max(avatarView.frame.maxY, descriptionLabel.frame.maxY) + contentView.layoutMargins.bottom)
}

// MARK: - Internal

internal func configureObservers() {
// Clean
NotificationCenter.default.removeObserver(self)

// Configure New
NotificationCenter.default.addObserver(forName: SPProfiling.didChangedAuthState, object: nil, queue: nil) { [weak self] _ in
guard let self = self else { return }
self.updateAppearance()
}

NotificationCenter.default.addObserver(forName: SPProfiling.didReloadedProfile, object: nil, queue: nil) { [weak self] _ in
guard let self = self else { return }
self.updateAppearance()
}
}

internal func updateAppearance() {
if ProfileModel.isAuthed, let profileModel = ProfileModel.currentProfile {
setProfile(profileModel, completion: nil)
} else {
setAuthAppearance()
}
}

internal func setAuthAppearance() {
avatarView.avatarAppearance = .placeholder
titleLabel.text = Texts.Auth.sign_in
titleLabel.textColor = .tint
}

internal func setProfile(_ profileModel: ProfileModel, completion: (()->())? = nil) {
titleLabel.text = profileModel.name ?? profileModel.email ?? Texts.Profile.placeholder_name
avatarView.setAvatar(of: profileModel) {
completion?()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ public enum ProfileMiddlewareError: LocalizedError {

public var errorDescription: String? {
switch self {
case .nameShort: return Texts.Profile.Error.name_short
case .nameLong: return Texts.Profile.Error.name_long
case .emptyName: return Texts.Profile.Error.empty_name
case .invalidEmail: return Texts.Profile.Error.empty_name
case .avatarBigWidth: return Texts.Profile.Error.big_avatar_width
case .avatarBigSize: return Texts.Profile.Error.big_avatar_size
case .nameShort: return Texts.Error.Profile.name_short
case .nameLong: return Texts.Error.Profile.name_long
case .emptyName: return Texts.Error.Profile.empty_name
case .invalidEmail: return Texts.Error.Profile.empty_name
case .avatarBigWidth: return Texts.Error.Profile.big_avatar_width
case .avatarBigSize: return Texts.Error.Profile.big_avatar_size
}
}
}
2 changes: 1 addition & 1 deletion Sources/SPProfiling/ProfileModelExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ extension ProfileModel {
public static func showCurrentProfile(on viewController: UIViewController) {
guard currentProfile != nil else { return }

let controller = CurrentProfileController()
let controller = ProfileController()
let navigationController = controller.wrapToNavigationController(prefersLargeTitles: false)
controller.navigationItem.rightBarButtonItem = controller.closeBarButtonItem

Expand Down

0 comments on commit a70c627

Please sign in to comment.