Skip to content

Commit 839ff6e

Browse files
committed
Updated auth cell. Added auth screen.
1 parent 78b8d52 commit 839ff6e

File tree

6 files changed

+199
-42
lines changed

6 files changed

+199
-42
lines changed

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ let package = Package(
1616
],
1717
dependencies: [
1818
.package(url: "https://github.com/ivanvorobei/SPAlert", .upToNextMajor(from: "4.2.0")),
19-
.package(url: "https://github.com/ivanvorobei/NativeUIKit", .upToNextMajor(from: "1.3.8")),
19+
.package(url: "https://github.com/ivanvorobei/NativeUIKit", .upToNextMajor(from: "1.3.9")),
2020
.package(url: "https://github.com/ivanvorobei/SPFirebase", .upToNextMajor(from: "1.0.6")),
2121
.package(url: "https://github.com/sparrowcode/SPSafeSymbols", .upToNextMajor(from: "1.0.5")),
2222
.package(url: "https://github.com/kean/Nuke", .upToNextMajor(from: "10.7.1"))
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// The MIT License (MIT)
2+
// Copyright © 2022 Ivan Vorobei ([email protected])
3+
//
4+
// Permission is hereby granted, free of charge, to any person obtaining a copy
5+
// of this software and associated documentation files (the "Software"), to deal
6+
// in the Software without restriction, including without limitation the rights
7+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
// copies of the Software, and to permit persons to whom the Software is
9+
// furnished to do so, subject to the following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included in all
12+
// copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
// SOFTWARE.
21+
22+
import UIKit
23+
import NativeUIKit
24+
import SparrowKit
25+
import SPAlert
26+
27+
public class AuthController: NativeOnboardingFeaturesController {
28+
29+
private var completion: ()->Void
30+
31+
// MARK: - Views
32+
33+
let actionToolbarView = NativeAppleAuthToolBarView()
34+
35+
// MARK: - Init
36+
37+
init(title: String, description: String, completion: @escaping ()->Void) {
38+
self.completion = completion
39+
super.init(
40+
iconImage: NativeAvatarView.generatePlaceholderImage(fontSize: 80, fontWeight: .medium),
41+
title: title,
42+
subtitle: description
43+
)
44+
}
45+
46+
required init?(coder: NSCoder) {
47+
fatalError("init(coder:) has not been implemented")
48+
}
49+
50+
// MARK: - Lifecycle
51+
52+
public override func viewDidLoad() {
53+
super.viewDidLoad()
54+
55+
if let navigationController = self.navigationController as? NativeNavigationController {
56+
navigationController.mimicrateToolBarView = actionToolbarView
57+
}
58+
59+
actionToolbarView.authButton.addTarget(self, action: #selector(self.tapSignInApple), for: .touchUpInside)
60+
}
61+
62+
@objc func tapSignInApple() {
63+
ProfileModel.signInApple(on: self) { error in
64+
if let error = error {
65+
SPAlert.present(message: error.localizedDescription, haptic: .error)
66+
} else {
67+
self.completion()
68+
}
69+
}
70+
}
71+
}

Sources/SPProfiling/Interface/Profile/Table/CellProvider+Profile.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ extension SPDiffableTableDataSource.CellProvider {
2626

2727
public static var profile: SPDiffableTableDataSource.CellProvider {
2828
return SPDiffableTableDataSource.CellProvider() { (tableView, indexPath, item) -> UITableViewCell? in
29-
guard let _ = item as? DiffableProfileItem else { return nil }
29+
guard let item = item as? DiffableProfileItem else { return nil }
3030
let cell = tableView.dequeueReusableCell(withClass: ProfileTableViewCell.self, for: indexPath)
31+
cell.profileLabelsView.descriptionLabel.text = item.cellProfileSubtitle
32+
cell.authLabelsView.descriptionLabel.text = item.cellAuthSubtitle
3133
return cell
3234
}
3335
}

Sources/SPProfiling/Interface/Profile/Table/DiffableProfileItem.swift

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,38 @@
2121

2222
import UIKit
2323
import SPDiffable
24+
import NativeUIKit
2425

2526
open class DiffableProfileItem: SPDiffableActionableItem {
2627

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

29-
public init(action: SPDiffableActionableItem.Action? = nil) {
30-
super.init(id: Self.id, action: action)
30+
var cellAuthSubtitle: String
31+
var cellProfileSubtitle: String
32+
33+
public init(
34+
authTitle: String,
35+
authDescription: String,
36+
cellAuthSubtitle: String,
37+
cellProfileSubtitle: String,
38+
features: [NativeOnboardingFeatureView.FeatureModel],
39+
completion: @escaping ()->Void,
40+
presentOn controller: UIViewController
41+
) {
42+
self.cellAuthSubtitle = cellAuthSubtitle
43+
self.cellProfileSubtitle = cellProfileSubtitle
44+
super.init(id: Self.id, action: { item, indexPath in
45+
if ProfileModel.isAnonymous ?? true {
46+
ProfileModel.showAuth(
47+
title: authTitle,
48+
description: authDescription,
49+
features: features,
50+
completion: completion,
51+
on: controller
52+
)
53+
} else {
54+
ProfileModel.showCurrentProfile(on: controller)
55+
}
56+
})
3157
}
3258
}

Sources/SPProfiling/Interface/Profile/Table/ProfileTableViewCell.swift

Lines changed: 71 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,15 @@ import SparrowKit
2525

2626
open class ProfileTableViewCell: SPTableViewCell {
2727

28-
public let titleLabel = SPLabel().do {
29-
$0.numberOfLines = 1
30-
$0.font = UIFont.preferredFont(forTextStyle: .title2, weight: .semibold)
31-
$0.textColor = .label
32-
}
28+
// MARK: - Views
3329

34-
public let descriptionLabel = SPLabel().do {
35-
$0.numberOfLines = 1
36-
$0.font = UIFont.preferredFont(forTextStyle: .footnote, weight: .regular)
37-
$0.textColor = .secondaryLabel
38-
}
30+
public let profileLabelsView = ProfileLabelsView()
31+
32+
public let authLabelsView = AuthLabelsView()
3933

4034
public let avatarView = NativeAvatarView().do {
4135
$0.isEditable = false
42-
$0.placeholderImage = UIImage.system("person.crop.circle.fill", font: .systemFont(ofSize: 52, weight: .medium))
36+
$0.placeholderImage = NativeAvatarView.generatePlaceholderImage(fontSize: 46, fontWeight: .medium)
4337
$0.avatarAppearance = .placeholder
4438
}
4539

@@ -48,9 +42,10 @@ open class ProfileTableViewCell: SPTableViewCell {
4842
open override func commonInit() {
4943
super.commonInit()
5044
higlightStyle = .content
51-
contentView.addSubviews(avatarView, titleLabel, descriptionLabel)
45+
contentView.addSubviews(avatarView, profileLabelsView, authLabelsView)
5246
accessoryType = .disclosureIndicator
5347
updateAppearance()
48+
configureObservers()
5449
}
5550

5651
open override func prepareForReuse() {
@@ -65,11 +60,12 @@ open class ProfileTableViewCell: SPTableViewCell {
6560

6661
// MARK: - Ovveride
6762

63+
#warning("change to subbiews")
6864
open override func setHighlighted(_ highlighted: Bool, animated: Bool) {
6965
super.setHighlighted(highlighted, animated: animated)
7066
let higlightContent = (higlightStyle == .content)
7167
if higlightContent {
72-
[avatarView, titleLabel, descriptionLabel].forEach({ $0?.alpha = highlighted ? 0.6 : 1 })
68+
[avatarView, profileLabelsView, authLabelsView].forEach({ $0?.alpha = highlighted ? 0.6 : 1 })
7369
}
7470
}
7571

@@ -81,28 +77,24 @@ open class ProfileTableViewCell: SPTableViewCell {
8177
avatarView.setXToSuperviewLeftMargin()
8278
avatarView.frame.origin.y = contentView.layoutMargins.top
8379

80+
let visibleLabelsView = profileLabelsView.isHidden ? authLabelsView : profileLabelsView
8481
let avatarRightSpace: CGFloat = NativeLayout.Spaces.default
85-
let labelVerticalSpace: CGFloat = NativeLayout.Spaces.step / 2
86-
let labelWidth = contentView.layoutWidth - avatarView.frame.width - avatarRightSpace
87-
titleLabel.layoutDynamicHeight(width: labelWidth)
88-
descriptionLabel.layoutDynamicHeight(width: labelWidth)
89-
90-
titleLabel.frame.origin.x = avatarView.frame.maxX + avatarRightSpace
91-
descriptionLabel.frame.origin.x = titleLabel.frame.origin.x
82+
let labelsWidth = contentView.layoutWidth - avatarView.frame.width - avatarRightSpace
83+
visibleLabelsView.frame.setWidth(labelsWidth)
84+
visibleLabelsView.sizeToFit()
85+
visibleLabelsView.frame.origin.x = avatarView.frame.maxX + avatarRightSpace
9286

93-
let labelHeight = titleLabel.frame.height + labelVerticalSpace + descriptionLabel.frame.height
94-
if (avatarView.frame.origin.y + labelHeight) > avatarView.frame.maxY {
95-
titleLabel.frame.origin.y = contentView.layoutMargins.top
87+
if (avatarView.frame.origin.y + visibleLabelsView.frame.height) > avatarView.frame.maxY {
88+
visibleLabelsView.frame.origin.y = contentView.layoutMargins.top
9689
} else {
97-
titleLabel.frame.origin.y = contentView.layoutMargins.top + (contentView.layoutHeight - labelHeight) / 2
90+
visibleLabelsView.frame.origin.y = contentView.layoutMargins.top + (contentView.layoutHeight - visibleLabelsView.frame.height) / 2
9891
}
99-
100-
descriptionLabel.frame.origin.y = titleLabel.frame.maxY + labelVerticalSpace
10192
}
10293

10394
open override func sizeThatFits(_ size: CGSize) -> CGSize {
10495
layoutSubviews()
105-
return .init(width: size.width, height: max(avatarView.frame.maxY, descriptionLabel.frame.maxY) + contentView.layoutMargins.bottom)
96+
let visibleLabelsView = profileLabelsView.isHidden ? authLabelsView : profileLabelsView
97+
return .init(width: size.width, height: max(avatarView.frame.maxY, visibleLabelsView.frame.maxY) + contentView.layoutMargins.bottom)
10698
}
10799

108100
// MARK: - Internal
@@ -124,23 +116,64 @@ open class ProfileTableViewCell: SPTableViewCell {
124116
}
125117

126118
internal func updateAppearance() {
127-
if ProfileModel.isAuthed, let profileModel = ProfileModel.currentProfile {
128-
setProfile(profileModel, completion: nil)
119+
let profileModel = ProfileModel.currentProfile
120+
authLabelsView.titleLabel.text = Texts.Auth.sign_in
121+
profileLabelsView.titleLabel.text = profileModel?.name ?? profileModel?.email ?? Texts.Profile.placeholder_name
122+
123+
if ProfileModel.isAnonymous ?? true {
124+
avatarView.avatarAppearance = .placeholder
125+
authLabelsView.isHidden = false
126+
profileLabelsView.isHidden = true
129127
} else {
130-
setAuthAppearance()
128+
guard let profileModel = ProfileModel.currentProfile else { return }
129+
avatarView.setAvatar(of: profileModel)
130+
authLabelsView.isHidden = true
131+
profileLabelsView.isHidden = false
131132
}
133+
134+
layoutSubviews()
132135
}
133136

134-
internal func setAuthAppearance() {
135-
avatarView.avatarAppearance = .placeholder
136-
titleLabel.text = Texts.Auth.sign_in
137-
titleLabel.textColor = .tint
137+
// MARK: - Views
138+
139+
public class ProfileLabelsView: SPView {
140+
141+
public let titleLabel = SPLabel().do {
142+
$0.numberOfLines = 1
143+
$0.font = UIFont.preferredFont(forTextStyle: .title2, weight: .semibold)
144+
$0.textColor = .label
145+
}
146+
147+
public let descriptionLabel = SPLabel().do {
148+
$0.numberOfLines = 1
149+
$0.font = UIFont.preferredFont(forTextStyle: .footnote, weight: .regular)
150+
$0.textColor = .secondaryLabel
151+
}
152+
153+
public override func commonInit() {
154+
super.commonInit()
155+
layoutMargins = .zero
156+
addSubview(titleLabel)
157+
addSubview(descriptionLabel)
158+
}
159+
160+
public override func layoutSubviews() {
161+
super.layoutSubviews()
162+
titleLabel.layoutDynamicHeight(x: .zero, y: .zero, width: frame.width)
163+
descriptionLabel.layoutDynamicHeight(x: .zero, y: titleLabel.frame.maxY + 2, width: frame.width)
164+
}
165+
166+
public override func sizeThatFits(_ size: CGSize) -> CGSize {
167+
layoutSubviews()
168+
return .init(width: size.width, height: descriptionLabel.frame.maxY)
169+
}
138170
}
139171

140-
internal func setProfile(_ profileModel: ProfileModel, completion: (()->())? = nil) {
141-
titleLabel.text = profileModel.name ?? profileModel.email ?? Texts.Profile.placeholder_name
142-
avatarView.setAvatar(of: profileModel) {
143-
completion?()
172+
public class AuthLabelsView: ProfileLabelsView {
173+
174+
public override func commonInit() {
175+
super.commonInit()
176+
titleLabel.textColor = .tint
144177
}
145178
}
146179
}

Sources/SPProfiling/ProfileModelExtension.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,31 @@ extension ProfileModel {
9797
viewController.present(navigationController)
9898
}
9999

100+
public static func showAuth(
101+
title: String,
102+
description: String,
103+
features: [NativeOnboardingFeatureView.FeatureModel],
104+
completion: @escaping ()->Void,
105+
on viewController: UIViewController
106+
) {
107+
let controller = AuthController(title: title, description: description, completion: completion)
108+
controller.setFeatures(features)
109+
let navigationController = NativeNavigationController(rootViewController: controller)
110+
controller.navigationItem.rightBarButtonItem = controller.closeBarButtonItem
111+
112+
let horizontalMargin: CGFloat = NativeLayout.Spaces.Margins.modal_screen_horizontal
113+
controller.modalPresentationStyle = .formSheet
114+
controller.preferredContentSize = .init(width: 540, height: 620)
115+
controller.view.layoutMargins.left = horizontalMargin
116+
controller.view.layoutMargins.right = horizontalMargin
117+
118+
navigationController.inheritLayoutMarginsForNavigationBar = true
119+
navigationController.inheritLayoutMarginsForСhilds = true
120+
navigationController.viewDidLayoutSubviews()
121+
122+
viewController.present(navigationController)
123+
}
124+
100125

101126
// MARK: - Middleware
102127

0 commit comments

Comments
 (0)