Add the Use Case selection screen to the onboarding flow.

This commit is contained in:
Doug
2022-02-02 12:24:22 +00:00
parent ad7c8dfa1b
commit 2cef1a7398
48 changed files with 1178 additions and 134 deletions
@@ -42,18 +42,13 @@ struct AnalyticsPromptViewState: BindableState {
/// A collection of strings for the UI that need to be created in
/// the coordinator or mocked in the RiotSwiftUI target.
protocol AnalyticsPromptStringsProtocol {
var appDisplayName: String { get }
var point1: NSAttributedString { get }
var point2: NSAttributedString { get }
var termsNewUser: NSAttributedString { get }
var termsUpgrade: NSAttributedString { get }
}
enum AnalyticsPromptType {
case newUser(termsString: NSAttributedString)
case upgrade(termsString: NSAttributedString)
case newUser
case upgrade
}
extension AnalyticsPromptType {
@@ -67,11 +62,23 @@ extension AnalyticsPromptType {
}
}
/// The terms string that should be displayed.
var termsStrings: NSAttributedString {
/// The main part of the terms string that should be displayed.
var mainTermsString: String {
switch self {
case .newUser(let termsString), .upgrade(let termsString):
return termsString
case .newUser:
return VectorL10n.analyticsPromptTermsNewUser("%@")
case .upgrade:
return VectorL10n.analyticsPromptTermsUpgrade("%@")
}
}
/// The tappable part of the terms string that should be displayed.
var termsLinkString: String {
switch self {
case .newUser:
return VectorL10n.analyticsPromptTermsLinkNewUser
case .upgrade:
return VectorL10n.analyticsPromptTermsLinkUpgrade
}
}
@@ -96,15 +103,7 @@ extension AnalyticsPromptType {
}
}
extension AnalyticsPromptType: CaseIterable {
static var allCases: [AnalyticsPromptType] {
let strings = MockAnalyticsPromptStrings()
return [
.newUser(termsString: strings.termsNewUser),
.upgrade(termsString: strings.termsUpgrade)
]
}
}
extension AnalyticsPromptType: CaseIterable { }
extension AnalyticsPromptType: Identifiable {
var id: String {
@@ -52,9 +52,9 @@ final class AnalyticsPromptCoordinator: Coordinator, Presentable {
let promptType: AnalyticsPromptType
if Analytics.shared.promptShouldDisplayUpgradeMessage {
promptType = .upgrade(termsString: strings.termsUpgrade)
promptType = .upgrade
} else {
promptType = .newUser(termsString: strings.termsNewUser)
promptType = .newUser
}
let viewModel = AnalyticsPromptViewModel(promptType: promptType, strings: strings, termsURL: BuildSettings.analyticsTermsURL)
@@ -18,16 +18,7 @@ import Foundation
@available(iOS 14.0, *)
struct AnalyticsPromptStrings: AnalyticsPromptStringsProtocol {
let appDisplayName = AppInfo.current.displayName
let point1 = HTMLFormatter().formatHTML(VectorL10n.analyticsPromptPoint1, withAllowedTags: ["b", "p"], fontSize: UIFont.systemFontSize)
let point2 = HTMLFormatter().formatHTML(VectorL10n.analyticsPromptPoint2, withAllowedTags: ["b", "p"], fontSize: UIFont.systemFontSize)
let termsNewUser = HTMLFormatter().format(VectorL10n.analyticsPromptTermsNewUser("%@"),
with: VectorL10n.analyticsPromptTermsLinkNewUser,
using: BuildSettings.analyticsTermsURL)
let termsUpgrade = HTMLFormatter().format(VectorL10n.analyticsPromptTermsUpgrade("%@"),
with: VectorL10n.analyticsPromptTermsLinkUpgrade,
using: BuildSettings.analyticsTermsURL)
}
@@ -17,14 +17,9 @@
import UIKit
struct MockAnalyticsPromptStrings: AnalyticsPromptStringsProtocol {
var appDisplayName = "Element"
let point1: NSAttributedString
let point2: NSAttributedString
let termsNewUser: NSAttributedString
let termsUpgrade: NSAttributedString
let shortString = NSAttributedString(string: "This is a short string.")
let longString = NSAttributedString(string: "This is a very long string that will be used to test the layout over multiple lines of text to ensure everything is correct.")
@@ -38,15 +33,5 @@ struct MockAnalyticsPromptStrings: AnalyticsPromptStringsProtocol {
point2.append(NSAttributedString(string: "don't", attributes: [.font: UIFont.boldSystemFont(ofSize: UIFont.systemFontSize)]))
point2.append(NSAttributedString(string: " share information with third parties"))
self.point2 = point2
let termsNewUser = NSMutableAttributedString(string: "You can read all our terms ")
termsNewUser.append(NSAttributedString(string: "here", attributes: [.link: URL(string: "https://element.io/cookie-policy")!]))
termsNewUser.append(NSAttributedString(string: "."))
self.termsNewUser = termsNewUser
let termsUpgrade = NSMutableAttributedString(string: "Read all our terms ")
termsUpgrade.append(NSAttributedString(string: "here", attributes: [.link: URL(string: "https://element.io/cookie-policy")!]))
termsUpgrade.append(NSAttributedString(string: ". Is that OK?"))
self.termsUpgrade = termsUpgrade
}
}
@@ -42,12 +42,10 @@ struct AnalyticsPrompt: View {
VStack {
Text("\(viewModel.viewState.promptType.message)\n")
AnalyticsPromptTermsText(attributedString: viewModel.viewState.promptType.termsStrings)
.accessibilityLabel(Text(viewModel.viewState.promptType.termsStrings.string))
.accessibilityValue(Text(VectorL10n.accessibilityButtonLabel))
.onTapGesture {
viewModel.send(viewAction: .openTermsURL)
}
InlineTextButton(viewModel.viewState.promptType.mainTermsString,
tappableText: viewModel.viewState.promptType.termsLinkString) {
viewModel.send(viewAction: .openTermsURL)
}
}
}
@@ -71,7 +69,7 @@ struct AnalyticsPrompt: View {
Image(uiImage: Asset.Images.analyticsLogo.image)
.padding(.bottom, 25)
Text(VectorL10n.analyticsPromptTitle(viewModel.viewState.strings.appDisplayName))
Text(VectorL10n.analyticsPromptTitle(AppInfo.current.displayName))
.font(theme.fonts.title2B)
.foregroundColor(theme.colors.primaryContent)
.padding(.bottom, 2)
@@ -125,6 +123,7 @@ struct AnalyticsPrompt: View {
.padding(.bottom, geometry.safeAreaInsets.bottom > 0 ? 0 : 16)
}
.background(theme.colors.background.ignoresSafeArea())
.accentColor(theme.colors.accent)
}
}
}
@@ -1,74 +0,0 @@
//
// Copyright 2021 New Vector Ltd
//
// 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 SwiftUI
@available(iOS 14.0, *)
/// The last line of text in the description with highlighting on the link string.
struct AnalyticsPromptTermsText: View {
// MARK: - Properties
// MARK: Private
@Environment(\.theme) private var theme
/// A string with a link attribute.
private struct StringComponent {
let string: String
let isLink: Bool
}
/// Internal representation of the string as composable parts.
private let components: [StringComponent]
// MARK: - Setup
init(attributedString: NSAttributedString) {
var components = [StringComponent]()
let range = NSRange(location: 0, length: attributedString.length)
let string = attributedString.string as NSString
attributedString.enumerateAttributes(in: range, options: []) { attributes, range, stop in
let isLink = attributes.keys.contains(.link)
components.append(StringComponent(string: string.substring(with: range), isLink: isLink))
}
self.components = components
}
// MARK: - Views
var body: some View {
components.reduce(Text("")) {
$0 + Text($1.string).foregroundColor($1.isLink ? theme.colors.accent : nil)
}
}
}
// MARK: - Previews
@available(iOS 14.0, *)
struct AnalyticsPromptTermsText_Previews: PreviewProvider {
static let strings = MockAnalyticsPromptStrings()
static var previews: some View {
VStack(spacing: 8) {
AnalyticsPromptTermsText(attributedString: strings.termsNewUser)
AnalyticsPromptTermsText(attributedString: strings.termsUpgrade)
}
}
}