From b61c91ffbcb89566cc9830411550b6866b2fc548 Mon Sep 17 00:00:00 2001 From: Margarita Yakovleva Date: Thu, 7 Jul 2022 12:38:34 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20=D0=B4=D0=B8=D0=B7=D0=B0=D0=B9=D0=BD=20=D0=BA=D0=BD?= =?UTF-8?q?=D0=BE=D0=BF=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Расширены возможности кастомизации кнопки по размеру, форме и типографии. Добавлены альтернативные цветовые схемы. Добавлена иконка в кнопку без возможности конфигурации. Добавлено отображение дополнительной информации на кнопке (н-р, информации о cashback). Добавлена круглая кнопка с логотипом с 3 цветовыми стилями. Обновлен Example для демонстрации возможных конфигураций. --- Example/App/AppDelegate.swift | 16 +- Example/App/AuthViewController.swift | 5 +- .../App/TinkoffButtonsViewController.swift | 131 ++++++ Example/Podfile.lock | 6 +- .../project.pbxproj | 52 +-- README.md | 12 +- .../idLogoL.imageset/Contents.json | 12 + .../idLogoL.imageset/Group 1096.pdf | Bin 0 -> 42351 bytes .../idLogoM.imageset/Contents.json | 12 + .../idLogoM.imageset/Group 1095.pdf | Bin 0 -> 41515 bytes .../idLogoS.imageset/Contents.json | 12 + .../idLogoS.imageset/Group 1094.pdf | Bin 0 -> 41456 bytes .../logo.imageset/Contents.json | 14 +- Sources/Resources/en.lproj/TinkoffID.strings | 1 - Sources/Resources/ru.lproj/TinkoffID.strings | 1 - Sources/UI/Button/TinkoffIDButton.swift | 389 ++++++++++++++---- .../UI/Button/TinkoffIDButtonBuilder.swift | 76 +++- .../UI/Button/TinkoffIDButtonColorStyle.swift | 79 ++++ .../UI/Button/TinkoffIDCompactButton.swift | 89 ++++ 19 files changed, 771 insertions(+), 136 deletions(-) create mode 100644 Example/App/TinkoffButtonsViewController.swift create mode 100644 Sources/Resources/TinkoffID.xcassets/idLogoL.imageset/Contents.json create mode 100644 Sources/Resources/TinkoffID.xcassets/idLogoL.imageset/Group 1096.pdf create mode 100644 Sources/Resources/TinkoffID.xcassets/idLogoM.imageset/Contents.json create mode 100644 Sources/Resources/TinkoffID.xcassets/idLogoM.imageset/Group 1095.pdf create mode 100644 Sources/Resources/TinkoffID.xcassets/idLogoS.imageset/Contents.json create mode 100644 Sources/Resources/TinkoffID.xcassets/idLogoS.imageset/Group 1094.pdf delete mode 100644 Sources/Resources/en.lproj/TinkoffID.strings delete mode 100644 Sources/Resources/ru.lproj/TinkoffID.strings create mode 100644 Sources/UI/Button/TinkoffIDButtonColorStyle.swift create mode 100644 Sources/UI/Button/TinkoffIDCompactButton.swift diff --git a/Example/App/AppDelegate.swift b/Example/App/AppDelegate.swift index dd6b7f5..dc19b12 100644 --- a/Example/App/AppDelegate.swift +++ b/Example/App/AppDelegate.swift @@ -45,8 +45,20 @@ final class AppDelegate: UIResponder, UIApplicationDelegate { credentialsRefresher: tinkoffId, signOutInitializer: tinkoffId ) - - window?.rootViewController = authController + authController.tabBarItem = UITabBarItem(title: "Auth", image: nil, tag: 0) + + let tinkoffButtonsController = TinkoffButtonsViewController() + tinkoffButtonsController.tabBarItem = UITabBarItem(title: "UI", image: nil, tag: 1) + + let tabBarController = UITabBarController() + + if #available(iOS 13.0, *) { + authController.tabBarItem.image = UIImage(systemName: "person") + tinkoffButtonsController.tabBarItem.image = UIImage(systemName: "pencil") + } + tabBarController.viewControllers = [authController, tinkoffButtonsController] + + window?.rootViewController = tabBarController window?.makeKeyAndVisible() } diff --git a/Example/App/AuthViewController.swift b/Example/App/AuthViewController.swift index 609bab0..8dbe708 100644 --- a/Example/App/AuthViewController.swift +++ b/Example/App/AuthViewController.swift @@ -28,7 +28,10 @@ final class AuthViewController: UIViewController { // MARK: - UI lazy var credentialsLabel = UILabel() - lazy var signInButton = TinkoffIDButtonBuilder.build(.default) + lazy var signInButton = TinkoffIDButtonBuilder.build( + configuration: TinkoffIDButtonConfiguration(size: .large), + title: "Войти с " + ) lazy var signOutButton = UIButton() lazy var refreshButton = UIButton() diff --git a/Example/App/TinkoffButtonsViewController.swift b/Example/App/TinkoffButtonsViewController.swift new file mode 100644 index 0000000..e28d678 --- /dev/null +++ b/Example/App/TinkoffButtonsViewController.swift @@ -0,0 +1,131 @@ +// +// UIViewController.swift +// TinkoffIDExample +// +// Created by Margarita Shishkina on 14.07.2022. +// Copyright © 2022 Tinkoff. All rights reserved. +// + +import UIKit +import TinkoffID + +class TinkoffButtonsViewController: UIViewController { + + private lazy var stackView: UIStackView = { + let stackView = UIStackView() + stackView.translatesAutoresizingMaskIntoConstraints = false + stackView.alignment = .leading + stackView.axis = .vertical + stackView.distribution = .fill + stackView.spacing = 4 + return stackView + }() + + override func viewDidLoad() { + super.viewDidLoad() + + view.backgroundColor = .white + + let scrollView = UIScrollView() + scrollView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(scrollView) + NSLayoutConstraint.activate([ + scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 16), + scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -8), + scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 8), + scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -16) + ]) + + scrollView.addSubview(stackView) + NSLayoutConstraint.activate([ + stackView.topAnchor.constraint(equalTo: scrollView.topAnchor), + stackView.leftAnchor.constraint(equalTo: scrollView.leftAnchor), + stackView.rightAnchor.constraint(equalTo: scrollView.rightAnchor), + stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor), + stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor) + ]) + + setupButtons() + } + + private func setupButtons() { + let buttonSmallDark = TinkoffIDButtonBuilder.build( + configuration: TinkoffIDButtonConfiguration(colorStyle: .alternativeDark, size: .small) + ) + stackView.addArrangedSubview(createLabel(with: "Small, alternativeDark")) + stackView.addArrangedSubview(buttonSmallDark) + stackView.setCustomSpacing(15, after: buttonSmallDark) + + let buttonSmall = TinkoffIDButtonBuilder.build( + configuration: TinkoffIDButtonConfiguration(size: .small), + title: "Войти с " + ) + stackView.addArrangedSubview(createLabel(with: "Small, custom title")) + stackView.addArrangedSubview(buttonSmall) + stackView.setCustomSpacing(15, after: buttonSmall) + + let buttonMedium = TinkoffIDButtonBuilder.build( + configuration: TinkoffIDButtonConfiguration(colorStyle: .alternativeLight) + ) + stackView.addArrangedSubview(createLabel(with: "Medium, alternativeLight")) + stackView.addArrangedSubview(buttonMedium) + stackView.setCustomSpacing(15, after: buttonMedium) + + let buttonLarge = TinkoffIDButtonBuilder.build( + configuration: TinkoffIDButtonConfiguration( + colorStyle: .alternativeDark, + size: .large, + font: UIFont(name: "Noteworthy", size: 15)! + ), + title: "Войти с " + ) + stackView.addArrangedSubview(createLabel(with: "Large, alternativeDark, custom font")) + stackView.addArrangedSubview(buttonLarge) + stackView.setCustomSpacing(15, after: buttonLarge) + + let buttonSmallBadge = TinkoffIDButtonBuilder.build( + configuration: TinkoffIDButtonConfiguration(size: .small), + badge: "5% кэшбэк" + ) + stackView.addArrangedSubview(createLabel(with: "Small, badge")) + stackView.addArrangedSubview(buttonSmallBadge) + stackView.setCustomSpacing(15, after: buttonSmallBadge) + + let buttonCustomSizeBadge = TinkoffIDButtonBuilder.build( + configuration: TinkoffIDButtonConfiguration(colorStyle: .alternativeLight, cornerRadius: 20), + badge: "5% кэшбэк" + ) + stackView.addArrangedSubview(createLabel(with: "Custom size, badge, alternativeLight, corner radius 20")) + stackView.addArrangedSubview(buttonCustomSizeBadge) + stackView.setCustomSpacing(15, after: buttonCustomSizeBadge) + buttonCustomSizeBadge.heightAnchor.constraint(equalToConstant: 80).isActive = true + buttonCustomSizeBadge.widthAnchor.constraint(equalTo: stackView.widthAnchor).isActive = true + + let buttonBadge = TinkoffIDButtonBuilder.build( + configuration: TinkoffIDButtonConfiguration(colorStyle: .alternativeDark), + badge: "500000% кэшбэк" + ) + stackView.addArrangedSubview(createLabel(with: "badge, alternativeDark")) + stackView.addArrangedSubview(buttonBadge) + stackView.setCustomSpacing(15, after: buttonBadge) + + let compactButton = TinkoffIDButtonBuilder.buildCompact() + stackView.addArrangedSubview(createLabel(with: "Compact button")) + stackView.addArrangedSubview(compactButton) + stackView.setCustomSpacing(15, after: compactButton) + + let compactButtonLight = TinkoffIDButtonBuilder.buildCompact(colorStyle: .alternativeLight) + stackView.addArrangedSubview(createLabel(with: "Compact button, alternativeLight, custom size")) + stackView.addArrangedSubview(compactButtonLight) + compactButtonLight.heightAnchor.constraint(equalToConstant: 70).isActive = true + compactButtonLight.widthAnchor.constraint(equalToConstant: 70).isActive = true + } + + private func createLabel(with text: String) -> UILabel { + let label = UILabel() + label.textColor = .black + label.font = UIFont.systemFont(ofSize: 14) + label.text = text + return label + } +} diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 0348e4a..79bf1fc 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -1,7 +1,7 @@ PODS: - SnapKit (5.0.1) - - TinkoffID (0.0.1) - - TinkoffID/Tests (0.0.1) + - TinkoffID (1.1.0) + - TinkoffID/Tests (1.1.0) DEPENDENCIES: - SnapKit @@ -18,7 +18,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: SnapKit: 97b92857e3df3a0c71833cce143274bf6ef8e5eb - TinkoffID: ac03552becea632de0f13d9461621770444ae0b8 + TinkoffID: 5f8c16ed1ec6ab3c055d76b162d5770a324ad3db PODFILE CHECKSUM: ebbf3aa204a2c47033aee78dc783acf8bc5423bd diff --git a/Example/TinkoffIDExample.xcodeproj/project.pbxproj b/Example/TinkoffIDExample.xcodeproj/project.pbxproj index b88f963..44dc21d 100644 --- a/Example/TinkoffIDExample.xcodeproj/project.pbxproj +++ b/Example/TinkoffIDExample.xcodeproj/project.pbxproj @@ -12,10 +12,13 @@ 0A65BBBC2590E8F000F613D5 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0A65BBB92590E8F000F613D5 /* LaunchScreen.storyboard */; }; 0A65BBBD2590E8F000F613D5 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0A65BBBA2590E8F000F613D5 /* Images.xcassets */; }; 0ABFC7892590E86000168951 /* TinkoffID.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 0ABFC7882590E85F00168951 /* TinkoffID.podspec */; }; - 51600987FEAC3FA656A81460 /* Pods_TinkoffIDExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F2A6E6CE33587FF27858033 /* Pods_TinkoffIDExample.framework */; }; + 40741E50BFF4B766A19FC37A /* Pods_TinkoffIDExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 035CA265801E31090C779B3B /* Pods_TinkoffIDExample.framework */; }; + B8B1F7102880026C008EAB8E /* TinkoffButtonsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8B1F70F2880026C008EAB8E /* TinkoffButtonsViewController.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 02D6235BCEC7A72B88084B7A /* Pods-TinkoffIDExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TinkoffIDExample.release.xcconfig"; path = "Target Support Files/Pods-TinkoffIDExample/Pods-TinkoffIDExample.release.xcconfig"; sourceTree = ""; }; + 035CA265801E31090C779B3B /* Pods_TinkoffIDExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TinkoffIDExample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 0A65BBAE2590E8D300F613D5 /* AuthViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthViewController.swift; sourceTree = ""; }; 0A65BBB12590E8D300F613D5 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 0A65BBB92590E8F000F613D5 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; @@ -23,13 +26,10 @@ 0A65BBBB2590E8F000F613D5 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 0ABFC7882590E85F00168951 /* TinkoffID.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = TinkoffID.podspec; path = ../TinkoffID.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 25F4E23B300426AEB76132F3 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; - 44F9956D4542D8782CD4C3D8 /* Pods-TinkoffIDExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TinkoffIDExample.release.xcconfig"; path = "Target Support Files/Pods-TinkoffIDExample/Pods-TinkoffIDExample.release.xcconfig"; sourceTree = ""; }; + 5C61E8899896A5A3B2571A79 /* Pods-TinkoffIDExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TinkoffIDExample.debug.xcconfig"; path = "Target Support Files/Pods-TinkoffIDExample/Pods-TinkoffIDExample.debug.xcconfig"; sourceTree = ""; }; 607FACD01AFB9204008FA782 /* TinkoffIDExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TinkoffIDExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 7F2A6E6CE33587FF27858033 /* Pods_TinkoffIDExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TinkoffIDExample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 86F49E1AE66946E513814F6E /* Pods-TinkoffIDExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TinkoffIDExample.debug.xcconfig"; path = "Target Support Files/Pods-TinkoffIDExample/Pods-TinkoffIDExample.debug.xcconfig"; sourceTree = ""; }; - 93A7498398FBAC5533C5966F /* Pods-TinkoffSignIn_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TinkoffSignIn_Example.debug.xcconfig"; path = "Target Support Files/Pods-TinkoffSignIn_Example/Pods-TinkoffSignIn_Example.debug.xcconfig"; sourceTree = ""; }; + B8B1F70F2880026C008EAB8E /* TinkoffButtonsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TinkoffButtonsViewController.swift; sourceTree = ""; }; BA3AB1A1BD565FCA6D3E2744 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; - E32A0480955749A2CEF75FC4 /* Pods-TinkoffSignIn_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TinkoffSignIn_Example.release.xcconfig"; path = "Target Support Files/Pods-TinkoffSignIn_Example/Pods-TinkoffSignIn_Example.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -37,26 +37,19 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 51600987FEAC3FA656A81460 /* Pods_TinkoffIDExample.framework in Frameworks */, + 40741E50BFF4B766A19FC37A /* Pods_TinkoffIDExample.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 05689BF3C94E278BB77E91B9 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 7F2A6E6CE33587FF27858033 /* Pods_TinkoffIDExample.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; 0A65BBAD2590E8D300F613D5 /* App */ = { isa = PBXGroup; children = ( 0A65BBB12590E8D300F613D5 /* AppDelegate.swift */, 0A65BBAE2590E8D300F613D5 /* AuthViewController.swift */, + B8B1F70F2880026C008EAB8E /* TinkoffButtonsViewController.swift */, 0A65BBB82590E8F000F613D5 /* Resources */, ); path = App; @@ -72,6 +65,14 @@ path = Resources; sourceTree = ""; }; + 4EAEDD680A06A0C99D9474AF /* Frameworks */ = { + isa = PBXGroup; + children = ( + 035CA265801E31090C779B3B /* Pods_TinkoffIDExample.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; 607FACC71AFB9204008FA782 = { isa = PBXGroup; children = ( @@ -79,7 +80,7 @@ 0A65BBAD2590E8D300F613D5 /* App */, 607FACD11AFB9204008FA782 /* Products */, D4A376ECE1B32FFCA6022572 /* Pods */, - 05689BF3C94E278BB77E91B9 /* Frameworks */, + 4EAEDD680A06A0C99D9474AF /* Frameworks */, ); sourceTree = ""; }; @@ -104,10 +105,8 @@ D4A376ECE1B32FFCA6022572 /* Pods */ = { isa = PBXGroup; children = ( - 93A7498398FBAC5533C5966F /* Pods-TinkoffSignIn_Example.debug.xcconfig */, - E32A0480955749A2CEF75FC4 /* Pods-TinkoffSignIn_Example.release.xcconfig */, - 86F49E1AE66946E513814F6E /* Pods-TinkoffIDExample.debug.xcconfig */, - 44F9956D4542D8782CD4C3D8 /* Pods-TinkoffIDExample.release.xcconfig */, + 5C61E8899896A5A3B2571A79 /* Pods-TinkoffIDExample.debug.xcconfig */, + 02D6235BCEC7A72B88084B7A /* Pods-TinkoffIDExample.release.xcconfig */, ); path = Pods; sourceTree = ""; @@ -119,11 +118,11 @@ isa = PBXNativeTarget; buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "TinkoffIDExample" */; buildPhases = ( - 37CFEEDB18E1B7B1ED595B67 /* [CP] Check Pods Manifest.lock */, + 4AAE7DBEBDBA13C7FC4C7236 /* [CP] Check Pods Manifest.lock */, 607FACCC1AFB9204008FA782 /* Sources */, 607FACCD1AFB9204008FA782 /* Frameworks */, 607FACCE1AFB9204008FA782 /* Resources */, - 7C076F48CF4E01832D45CFB4 /* [CP] Embed Pods Frameworks */, + 82A91C430F311D4F3A9538D0 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -183,7 +182,7 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 37CFEEDB18E1B7B1ED595B67 /* [CP] Check Pods Manifest.lock */ = { + 4AAE7DBEBDBA13C7FC4C7236 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -205,7 +204,7 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 7C076F48CF4E01832D45CFB4 /* [CP] Embed Pods Frameworks */ = { + 82A91C430F311D4F3A9538D0 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -231,6 +230,7 @@ files = ( 0A65BBB62590E8D300F613D5 /* AppDelegate.swift in Sources */, 0A65BBB32590E8D300F613D5 /* AuthViewController.swift in Sources */, + B8B1F7102880026C008EAB8E /* TinkoffButtonsViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -345,7 +345,7 @@ }; 607FACF01AFB9204008FA782 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 86F49E1AE66946E513814F6E /* Pods-TinkoffIDExample.debug.xcconfig */; + baseConfigurationReference = 5C61E8899896A5A3B2571A79 /* Pods-TinkoffIDExample.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; @@ -370,7 +370,7 @@ }; 607FACF11AFB9204008FA782 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 44F9956D4542D8782CD4C3D8 /* Pods-TinkoffIDExample.release.xcconfig */; + baseConfigurationReference = 02D6235BCEC7A72B88084B7A /* Pods-TinkoffIDExample.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; diff --git a/README.md b/README.md index c1602d1..d45d75c 100755 --- a/README.md +++ b/README.md @@ -198,15 +198,15 @@ tinkoffId.signOut(with: credentials.accessToken, tokenTypeHint: .access, complet При получении `TinkoffTokenPayload` и наличии у него поля `refreshToken` имеет смысл сохранить значение этого поля чтобы иметь возможность запросить новый `accessToken`, когда прежний станет неактивным. Рекомендуемый способ хранения токена - [Keychain Services](https://developer.apple.com/documentation/security/keychain_services) ## UI -SDK поставляет фирменную кнопку входа через Тинькофф. Кнопка представлена в двух стилях: `.default` (высотой 56 точек) и `.compact` (40 точек). -Для получения экземпляра кнопки необходимо использовать статический метод `build` класса `TinkoffIDButtonBuilder`: - +SDK поставляет два варианта фирменных кнопок входа через Тинькофф. +Первый вариант - стандартная прямоугольная кнопка с текстом, с возможностью задать текст, радиус скругления и шрифт. Так же можно выбрать один из трех вариантов цветового стиля и размера. Есть возможность добавить дополнительный текст для привлечения клиентов. +Второй вариант - компактная кнопка без текста, так же можно выбрать один из трех цветовых стилей. ```swift override func viewDidLoad() { super.viewDidLoad() - // Создание кнопки входа - let button = TinkoffIDButtonBuilder.build(.default) + // Создание стандартной кнопки + let button = TinkoffIDButtonBuilder.build() // Добавление обработчика нажатия button.addTarget(self, action: #selector(signInButtonTapped), for: .touchUpInside) @@ -230,7 +230,7 @@ override func viewDidLoad() { Обратите внимание: после получения кнопки необходимо расположить её на экране, а также добавить обработчик события нажатия. Для верстки рекомендуется использовать `AutoLayout` без указания высоты так как она задается с помощью `intrinsicContentSize`. -Более подробно ознакомиться с правилами размещения кнопки Вы можете [здесь](https://www.figma.com/file/TsgXOeAqFEePVIosk0W7kP/Tinkoff-ID). +Более подробно ознакомиться с правилами размещения кнопки Вы можете [здесь](https://www.figma.com/file/Yj3o7yQotahvBxfIKhBmJc/Tinkoff-ID-guide). ## Отладка без приложения Тинькофф В случаях когда необходима отладка интеграции `Tinkoff ID` без приложения Тинькофф или на симуляторе iOS, SDK предоставляет реализацию TinkoffID для отладки. diff --git a/Sources/Resources/TinkoffID.xcassets/idLogoL.imageset/Contents.json b/Sources/Resources/TinkoffID.xcassets/idLogoL.imageset/Contents.json new file mode 100644 index 0000000..1f2cd8f --- /dev/null +++ b/Sources/Resources/TinkoffID.xcassets/idLogoL.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Group 1096.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Sources/Resources/TinkoffID.xcassets/idLogoL.imageset/Group 1096.pdf b/Sources/Resources/TinkoffID.xcassets/idLogoL.imageset/Group 1096.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b062109c6aa70d7a5cfd81de0ff0399381a0bb90 GIT binary patch literal 42351 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 literal 0 HcmV?d00001 diff --git a/Sources/Resources/TinkoffID.xcassets/idLogoS.imageset/Contents.json b/Sources/Resources/TinkoffID.xcassets/idLogoS.imageset/Contents.json new file mode 100644 index 0000000..148b2de --- /dev/null +++ b/Sources/Resources/TinkoffID.xcassets/idLogoS.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Group 1094.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Sources/Resources/TinkoffID.xcassets/idLogoS.imageset/Group 1094.pdf b/Sources/Resources/TinkoffID.xcassets/idLogoS.imageset/Group 1094.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1b43d6d834b333e614c38b2cfd7bf3e139106477 GIT binary patch literal 41456 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 UIColor { - switch state { - case .highlighted: - return UIColor(red: 1, green: 0.803922, blue: 0.2, alpha: 1) - default: - return UIColor(red: 1, green: 0.86, blue: 0.1764, alpha: 1) - } - } - - /// Возвращает цвет текста для соответствующего состояния - /// - Parameter state: Состояние кнопки - func titleColorFor(state: UIControl.State) -> UIColor { - UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 1.0) - } - +private extension TinkoffIDButtonSize { + /// Высота кнопки - var height: CGFloat { + var defaultHeight: CGFloat { switch self { - case .compact: + case .small: + return 30 + case .medium: return 40 - case .default: - return 56 + case .large: + return 60 } } - /// Степень скругления краёв - var cornerRadius: CGFloat { + /// Шрифт + var titleFontSize: CGFloat { switch self { - case .compact: - return 12 - case .default: - return 16 + case .small: + return 13 + case .medium: + return 15 + case .large: + return 19 } } - - /// Заголовок - var title: String? { - Bundle.resourcesBundle? - .localizedString("SignInButton.Title") - } - - /// Шрифт - var titleFont: UIFont { - let size: CGFloat - + + /// Отступ между иконкой и текстом + var imageRightPadding: CGFloat { switch self { - case .default: - size = 17 - case .compact: - size = 15 + case .small: + return 4 + case .medium, .large: + return 8 } - - return UIFont.systemFont(ofSize: size, weight: .regular) } - + /// Изображение var image: UIImage? { - Bundle.resourcesBundle? - .imageNamed("logo") + switch self { + case .small: + return Bundle.resourcesBundle? + .imageNamed("idLogoS") + case .medium: + return Bundle.resourcesBundle? + .imageNamed("idLogoM") + case .large: + return Bundle.resourcesBundle? + .imageNamed("idLogoL") + } } /// Отступы по горизонтали - var contentHorizontalPadding: CGFloat { 32 } + var contentHorizontalPadding: CGFloat { + switch self { + case .small: + return 32 + case .medium: + return 40 + case .large: + return 60 + } + } /// Отступы по вертикали - var contentVerticalPadding: CGFloat { 6 } - - /// Отступ между изображением и текстом - var imageRightPadding: CGFloat { 8 } + var contentVerticalPadding: CGFloat { + switch self { + case .small: + return 5 + case .medium: + return 10 + case .large: + return 16 + } + } + + /// Отступ от краев при отображении кэшбэка + var contentEdgePadding: CGFloat { + switch self { + case .small: + return 10 + case .medium: + return 13 + case .large: + return 20 + } + } + + /// Отступы внутри кэшбэка + var horizontalLabelOffset: CGFloat { + switch self { + case .small: + return 8 + case .medium: + return 13 + case .large: + return 16 + } + } + var verticalLabelOffset: CGFloat { + switch self { + case .small: + return 0 + case .medium: + return 4 + case .large: + return 4 + } + } + + + /// Шрифт кэшбэка + var badgeFontSize: CGFloat { + switch self { + case .small, .medium: + return 11 + case .large: + return 13 + } + } + + /// Минимальный отступ от бейджа слева + var badgeLeftOffset: CGFloat { + switch self { + case .small: + return 20 + case .medium: + return 26 + case .large: + return 40 + } + } + + /// Ширина окантовки лого + var borderWidth: CGFloat { 2 } +} + +private extension UIFont { + func createBoldFont() -> UIFont { + guard let descriptor = self.fontDescriptor.withSymbolicTraits(UIFontDescriptor.SymbolicTraits.traitBold) else { + return self + } + return UIFont(descriptor: descriptor, size: 0) + } } diff --git a/Sources/UI/Button/TinkoffIDButtonBuilder.swift b/Sources/UI/Button/TinkoffIDButtonBuilder.swift index 108d7ab..c7c2816 100644 --- a/Sources/UI/Button/TinkoffIDButtonBuilder.swift +++ b/Sources/UI/Button/TinkoffIDButtonBuilder.swift @@ -18,21 +18,79 @@ import UIKit -/// Стиль кнопки входа -public enum TinkoffIDButtonStyle { - /// Стандартная желтая кнопка высотой 56 точек +/// Конфигурация кнопки +public struct TinkoffIDButtonConfiguration { + /// Стиль кнопки + let colorStyle: TinkoffIDButtonColorStyle + /// Размер + let size: TinkoffIDButtonSize + /// Радиус скругления + let cornerRadius: CGFloat + /// Шрифт + let font: UIFont + + public init( + colorStyle: TinkoffIDButtonColorStyle = .default, + size: TinkoffIDButtonSize = .medium, + cornerRadius: CGFloat = 8, + font: UIFont = UIFont.systemFont(ofSize: 15) + ) { + self.colorStyle = colorStyle + self.size = size + self.cornerRadius = cornerRadius + self.font = font + } +} + +/// Размер кнопки входа +public enum TinkoffIDButtonSize { + /// Размер от 30 до 40, по дефолту 30 + case small + /// Размер от 40 до 60, по дефолту 40 + case medium + /// Размер от 60, по дефолту 60 + case large + + init(height: CGFloat) { + if height < 40 { + self = .small + } else if height < 60 { + self = .medium + } else { + self = .large + } + } +} + +/// Цветовой стиль кнопки входа +public enum TinkoffIDButtonColorStyle { + /// Стандартная желтая тема case `default` - /// Желтая кнопка высотой 40 точек - case compact + /// Светлая тема + case alternativeLight + /// Темная тема + case alternativeDark } /// Сборщик кнопки входа через Тинькофф public final class TinkoffIDButtonBuilder { - /// Создает кнопку входа через Тинькофф - /// - Parameter style: Стиль кнопки + /// Создает прямоугольную кнопку входа через Тинькофф + /// - Parameter configuration: Конфигурация кнопки + /// - Parameter title: Текст кнопки + /// - Parameter badge: Дополнительный текст на бейдже + /// - Returns: Контрол кнопки + public static func build( + configuration: TinkoffIDButtonConfiguration = TinkoffIDButtonConfiguration(), + title: String? = nil, + badge: String? = nil + ) -> UIControl { + TinkoffIDButton(configuration: configuration, title: title, badge: badge) + } + /// Создает круглую кнопку входа через Тинькофф + /// - Parameter colorStyle: Цветовая тема кнопки /// - Returns: Контрол кнопки - public static func build(_ style: TinkoffIDButtonStyle) -> UIControl { - TinkoffIDButton(style) + public static func buildCompact(colorStyle: TinkoffIDButtonColorStyle = .default) -> UIControl { + TinkoffIDCompactButton(colorStyle: colorStyle) } } diff --git a/Sources/UI/Button/TinkoffIDButtonColorStyle.swift b/Sources/UI/Button/TinkoffIDButtonColorStyle.swift new file mode 100644 index 0000000..3cd1d77 --- /dev/null +++ b/Sources/UI/Button/TinkoffIDButtonColorStyle.swift @@ -0,0 +1,79 @@ +// +// TinkoffIDButtonColorStyle+Extension.swift +// TinkoffID +// +// Created by Margarita Shishkina on 13.07.2022. +// + +import Foundation + +extension TinkoffIDButtonColorStyle { + /// Возвращает цвет фона для соответствующего состояния + /// - Parameter state: Состояние кнопки + func backgroundColorFor(state: UIControl.State) -> UIColor { + switch state { + case .highlighted: + return highlightedBackgroundColor + default: + return backgroundColor + } + } + + /// цвет текста для соответствующего состояния + var titleColor: UIColor { + switch self { + case .alternativeDark: + return UIColor(red: 1, green: 1, blue: 1, alpha: 1) + case .alternativeLight: + return UIColor(red: 51 / 255, green: 51 / 255, blue: 51 / 255, alpha: 1) + case .default: + return UIColor(red: 51 / 255, green: 51 / 255, blue: 51 / 255, alpha: 1) + } + } + + /// Цвет поля кэшбэка + var badgeFieldColor: UIColor { + switch self { + case .alternativeDark: + return UIColor(red: 61 / 255, green: 61 / 255, blue: 61 / 255, alpha: 1) + case .alternativeLight: + return UIColor(red: 1, green: 1, blue: 1, alpha: 1) + case .default: + return UIColor(red: 1, green: 238 / 255, blue: 149 / 255, alpha: 1) + } + } + + /// Цвет текста кэшбэка + var badgeTextColor: UIColor { + switch self { + case .alternativeDark: + return UIColor(red: 1, green: 1, blue: 1, alpha: 1) + case .alternativeLight: + return UIColor(red: 51 / 255, green: 51 / 255, blue: 51 / 255, alpha: 1) + case .default: + return UIColor(red: 51 / 255, green: 51 / 255, blue: 51 / 255, alpha: 1) + } + } + + private var highlightedBackgroundColor: UIColor { + switch self { + case .alternativeDark: + return UIColor(red: 51 / 255, green: 51 / 255, blue: 51 / 255, alpha: 1) + case .alternativeLight: + return UIColor(red: 206 / 255, green: 206 / 255, blue: 207 / 255, alpha: 1) + case .default: + return UIColor(red: 250 / 255, green: 182 / 255, blue: 25 / 255, alpha: 1) + } + } + + private var backgroundColor: UIColor { + switch self { + case .alternativeDark: + return UIColor(red: 0, green: 0, blue: 0, alpha: 1) + case .alternativeLight: + return UIColor(red: 245 / 255, green: 245 / 255, blue: 246 / 255, alpha: 1) + case .default: + return UIColor(red: 255 / 255, green: 221 / 255, blue: 45 / 255, alpha: 1) + } + } +} diff --git a/Sources/UI/Button/TinkoffIDCompactButton.swift b/Sources/UI/Button/TinkoffIDCompactButton.swift new file mode 100644 index 0000000..22b0ab5 --- /dev/null +++ b/Sources/UI/Button/TinkoffIDCompactButton.swift @@ -0,0 +1,89 @@ +// +// TinkoffIDRoundButton.swift +// TinkoffID +// +// Copyright (c) 2022 Tinkoff +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import UIKit + +final class TinkoffIDCompactButton: UIButton { + + /// Высота кнопки + private var size: CGFloat { 56 } + + /// Изображение + private var image: UIImage? { + Bundle.resourcesBundle? + .imageNamed("logo") + } + + private let colorStyle: TinkoffIDButtonColorStyle + + override var isHighlighted: Bool { + didSet { + updateAppearanceForCurrentState() + } + } + + init(colorStyle: TinkoffIDButtonColorStyle) { + self.colorStyle = colorStyle + + super.init(frame: .zero) + + didInitialize() + } + + required init?(coder: NSCoder) { + self.colorStyle = .default + + super.init(coder: coder) + didInitialize() + } + + override var intrinsicContentSize: CGSize { + CGSize(width: size, height: size) + } + + override func layoutSubviews() { + super.layoutSubviews() + + layer.cornerRadius = bounds.height/2 + } + + // MARK: - Private + + private func didInitialize() { + configure() + updateAppearanceForCurrentState() + } + + private func configure() { + + // Image + imageView?.contentMode = .scaleToFill + setImage(image, for: .normal) + setImage(image, for: .highlighted) + contentHorizontalAlignment = .fill + contentVerticalAlignment = .fill + + setContentHuggingPriority(.required, for: .vertical) + + contentEdgeInsets = UIEdgeInsets(top: 12, left: 10, bottom: 12, right: 10) + } + + private func updateAppearanceForCurrentState() { + backgroundColor = colorStyle.backgroundColorFor(state: state) + } +}