WIP: landing screen (attributed text)

This commit is contained in:
ryanzhao 2023-08-16 13:43:33 +10:00
parent 2f9ca3c0f6
commit c9d97c10d0
27 changed files with 167 additions and 3 deletions

View File

@ -159,6 +159,7 @@
7BDCFC08242186E700641C39 /* NotificationServiceExtensionContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDCFC07242186E700641C39 /* NotificationServiceExtensionContext.swift */; };
7BDCFC0B2421EB7600641C39 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = B6F509951AA53F760068F56A /* Localizable.strings */; };
7BDE2A982A8B122900AE4393 /* LandingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDE2A972A8B122900AE4393 /* LandingView.swift */; };
7BDE2A9A2A8C59CF00AE4393 /* AttributedText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDE2A992A8C59CF00AE4393 /* AttributedText.swift */; };
7BF8D1FB2A70AF57005F1D6E /* SwiftUI+Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BF8D1FA2A70AF57005F1D6E /* SwiftUI+Theme.swift */; };
7BFA8AE32831D0D4001876F3 /* ContextMenuVC+EmojiReactsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BFA8AE22831D0D4001876F3 /* ContextMenuVC+EmojiReactsView.swift */; };
7BFD1A8A2745C4F000FB91B9 /* Permissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BFD1A892745C4F000FB91B9 /* Permissions.swift */; };
@ -1274,6 +1275,7 @@
7BDCFC0424206E7300641C39 /* SessionNotificationServiceExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SessionNotificationServiceExtension.entitlements; sourceTree = "<group>"; };
7BDCFC07242186E700641C39 /* NotificationServiceExtensionContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationServiceExtensionContext.swift; sourceTree = "<group>"; };
7BDE2A972A8B122900AE4393 /* LandingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LandingView.swift; sourceTree = "<group>"; };
7BDE2A992A8C59CF00AE4393 /* AttributedText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedText.swift; sourceTree = "<group>"; };
7BE2701D2A64C11500CEB71A /* SessionCarouselView+SwiftUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionCarouselView+SwiftUI.swift"; sourceTree = "<group>"; };
7BF8D1FA2A70AF57005F1D6E /* SwiftUI+Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SwiftUI+Theme.swift"; sourceTree = "<group>"; };
7BFA8AE22831D0D4001876F3 /* ContextMenuVC+EmojiReactsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ContextMenuVC+EmojiReactsView.swift"; sourceTree = "<group>"; };
@ -2946,6 +2948,7 @@
C38EF2A4255B6D93007E1867 /* ProfilePictureView.swift */,
FD71165A28E6DDBC00B47552 /* StyledNavigationController.swift */,
FD0B77AF29B69A65009169BA /* TopBannerController.swift */,
7BDE2A992A8C59CF00AE4393 /* AttributedText.swift */,
);
path = Components;
sourceTree = "<group>";
@ -5491,6 +5494,7 @@
FD37EA0128A60473003AE748 /* UIKit+Theme.swift in Sources */,
FD37E9CF28A1EB1B003AE748 /* Theme.swift in Sources */,
C331FFB92558FA8D00070591 /* UIView+Constraints.swift in Sources */,
7BDE2A9A2A8C59CF00AE4393 /* AttributedText.swift in Sources */,
FD0B77B029B69A65009169BA /* TopBannerController.swift in Sources */,
FD37E9F628A5F106003AE748 /* Configuration.swift in Sources */,
7BF8D1FB2A70AF57005F1D6E /* SwiftUI+Theme.swift in Sources */,

View File

@ -661,3 +661,6 @@
"onboarding_landing_title" = "Privacy in your pocket.";
"onboarding_landing_register_button_title" = "Create account";
"onboarding_landing_restore_button_title" = "I have an account";
"onboarding_T&C" = "By using this service, you agree to our %@ and %@";
"terms_of_service" = "Terms of Service";
"privacy_policy" = "Privacy Policy";

View File

@ -661,3 +661,6 @@
"onboarding_landing_title" = "Privacy in your pocket.";
"onboarding_landing_register_button_title" = "Create account";
"onboarding_landing_restore_button_title" = "I have an account";
"onboarding_T&C" = "By using this service, you agree to our %@ and %@";
"terms_of_service" = "Terms of Service";
"privacy_policy" = "Privacy Policy";

View File

@ -661,3 +661,6 @@
"onboarding_landing_title" = "Privacy in your pocket.";
"onboarding_landing_register_button_title" = "Create account";
"onboarding_landing_restore_button_title" = "I have an account";
"onboarding_T&C" = "By using this service, you agree to our %@ and %@";
"terms_of_service" = "Terms of Service";
"privacy_policy" = "Privacy Policy";

View File

@ -661,3 +661,6 @@
"onboarding_landing_title" = "Privacy in your pocket.";
"onboarding_landing_register_button_title" = "Create account";
"onboarding_landing_restore_button_title" = "I have an account";
"onboarding_T&C" = "By using this service, you agree to our %@ and %@";
"terms_of_service" = "Terms of Service";
"privacy_policy" = "Privacy Policy";

View File

@ -661,3 +661,6 @@
"onboarding_landing_title" = "Privacy in your pocket.";
"onboarding_landing_register_button_title" = "Create account";
"onboarding_landing_restore_button_title" = "I have an account";
"onboarding_T&C" = "By using this service, you agree to our %@ and %@";
"terms_of_service" = "Terms of Service";
"privacy_policy" = "Privacy Policy";

View File

@ -661,3 +661,6 @@
"onboarding_landing_title" = "Privacy in your pocket.";
"onboarding_landing_register_button_title" = "Create account";
"onboarding_landing_restore_button_title" = "I have an account";
"onboarding_T&C" = "By using this service, you agree to our %@ and %@";
"terms_of_service" = "Terms of Service";
"privacy_policy" = "Privacy Policy";

View File

@ -661,3 +661,6 @@
"onboarding_landing_title" = "Privacy in your pocket.";
"onboarding_landing_register_button_title" = "Create account";
"onboarding_landing_restore_button_title" = "I have an account";
"onboarding_T&C" = "By using this service, you agree to our %@ and %@";
"terms_of_service" = "Terms of Service";
"privacy_policy" = "Privacy Policy";

View File

@ -661,3 +661,6 @@
"onboarding_landing_title" = "Privacy in your pocket.";
"onboarding_landing_register_button_title" = "Create account";
"onboarding_landing_restore_button_title" = "I have an account";
"onboarding_T&C" = "By using this service, you agree to our %@ and %@";
"terms_of_service" = "Terms of Service";
"privacy_policy" = "Privacy Policy";

View File

@ -661,3 +661,6 @@
"onboarding_landing_title" = "Privacy in your pocket.";
"onboarding_landing_register_button_title" = "Create account";
"onboarding_landing_restore_button_title" = "I have an account";
"onboarding_T&C" = "By using this service, you agree to our %@ and %@";
"terms_of_service" = "Terms of Service";
"privacy_policy" = "Privacy Policy";

View File

@ -661,3 +661,6 @@
"onboarding_landing_title" = "Privacy in your pocket.";
"onboarding_landing_register_button_title" = "Create account";
"onboarding_landing_restore_button_title" = "I have an account";
"onboarding_T&C" = "By using this service, you agree to our %@ and %@";
"terms_of_service" = "Terms of Service";
"privacy_policy" = "Privacy Policy";

View File

@ -661,3 +661,6 @@
"onboarding_landing_title" = "Privacy in your pocket.";
"onboarding_landing_register_button_title" = "Create account";
"onboarding_landing_restore_button_title" = "I have an account";
"onboarding_T&C" = "By using this service, you agree to our %@ and %@";
"terms_of_service" = "Terms of Service";
"privacy_policy" = "Privacy Policy";

View File

@ -661,3 +661,6 @@
"onboarding_landing_title" = "Privacy in your pocket.";
"onboarding_landing_register_button_title" = "Create account";
"onboarding_landing_restore_button_title" = "I have an account";
"onboarding_T&C" = "By using this service, you agree to our %@ and %@";
"terms_of_service" = "Terms of Service";
"privacy_policy" = "Privacy Policy";

View File

@ -661,3 +661,6 @@
"onboarding_landing_title" = "Privacy in your pocket.";
"onboarding_landing_register_button_title" = "Create account";
"onboarding_landing_restore_button_title" = "I have an account";
"onboarding_T&C" = "By using this service, you agree to our %@ and %@";
"terms_of_service" = "Terms of Service";
"privacy_policy" = "Privacy Policy";

View File

@ -661,3 +661,6 @@
"onboarding_landing_title" = "Privacy in your pocket.";
"onboarding_landing_register_button_title" = "Create account";
"onboarding_landing_restore_button_title" = "I have an account";
"onboarding_T&C" = "By using this service, you agree to our %@ and %@";
"terms_of_service" = "Terms of Service";
"privacy_policy" = "Privacy Policy";

View File

@ -661,3 +661,6 @@
"onboarding_landing_title" = "Privacy in your pocket.";
"onboarding_landing_register_button_title" = "Create account";
"onboarding_landing_restore_button_title" = "I have an account";
"onboarding_T&C" = "By using this service, you agree to our %@ and %@";
"terms_of_service" = "Terms of Service";
"privacy_policy" = "Privacy Policy";

View File

@ -661,3 +661,6 @@
"onboarding_landing_title" = "Privacy in your pocket.";
"onboarding_landing_register_button_title" = "Create account";
"onboarding_landing_restore_button_title" = "I have an account";
"onboarding_T&C" = "By using this service, you agree to our %@ and %@";
"terms_of_service" = "Terms of Service";
"privacy_policy" = "Privacy Policy";

View File

@ -661,3 +661,6 @@
"onboarding_landing_title" = "Privacy in your pocket.";
"onboarding_landing_register_button_title" = "Create account";
"onboarding_landing_restore_button_title" = "I have an account";
"onboarding_T&C" = "By using this service, you agree to our %@ and %@";
"terms_of_service" = "Terms of Service";
"privacy_policy" = "Privacy Policy";

View File

@ -661,3 +661,6 @@
"onboarding_landing_title" = "Privacy in your pocket.";
"onboarding_landing_register_button_title" = "Create account";
"onboarding_landing_restore_button_title" = "I have an account";
"onboarding_T&C" = "By using this service, you agree to our %@ and %@";
"terms_of_service" = "Terms of Service";
"privacy_policy" = "Privacy Policy";

View File

@ -661,3 +661,6 @@
"onboarding_landing_title" = "Privacy in your pocket.";
"onboarding_landing_register_button_title" = "Create account";
"onboarding_landing_restore_button_title" = "I have an account";
"onboarding_T&C" = "By using this service, you agree to our %@ and %@";
"terms_of_service" = "Terms of Service";
"privacy_policy" = "Privacy Policy";

View File

@ -661,3 +661,6 @@
"onboarding_landing_title" = "Privacy in your pocket.";
"onboarding_landing_register_button_title" = "Create account";
"onboarding_landing_restore_button_title" = "I have an account";
"onboarding_T&C" = "By using this service, you agree to our %@ and %@";
"terms_of_service" = "Terms of Service";
"privacy_policy" = "Privacy Policy";

View File

@ -661,3 +661,6 @@
"onboarding_landing_title" = "Privacy in your pocket.";
"onboarding_landing_register_button_title" = "Create account";
"onboarding_landing_restore_button_title" = "I have an account";
"onboarding_T&C" = "By using this service, you agree to our %@ and %@";
"terms_of_service" = "Terms of Service";
"privacy_policy" = "Privacy Policy";

View File

@ -661,3 +661,6 @@
"onboarding_landing_title" = "Privacy in your pocket.";
"onboarding_landing_register_button_title" = "Create account";
"onboarding_landing_restore_button_title" = "I have an account";
"onboarding_T&C" = "By using this service, you agree to our %@ and %@";
"terms_of_service" = "Terms of Service";
"privacy_policy" = "Privacy Policy";

View File

@ -40,7 +40,7 @@ struct LandingView: View {
height: 40,
alignment: .center
)
.background(ThemeManager.currentTheme.colorSwiftUI(for: .sessionButton_filledBackground))
.backgroundColor(themeColor: .sessionButton_filledBackground)
.cornerRadius(20)
}
@ -58,14 +58,27 @@ struct LandingView: View {
)
.overlay(
Capsule()
.stroke(ThemeManager.currentTheme.colorSwiftUI(for: .sessionButton_border)!)
.stroke(themeColor: .sessionButton_border)
)
}
Button {
} label: {
Text("")
let attributedText: NSAttributedString = {
let text = String(format: "onboarding_T&C".localized(), "terms_of_service".localized(), "privacy_policy".localized())
let result = NSMutableAttributedString(
string: text,
attributes: [ .font : UIFont.systemFont(ofSize: Values.verySmallFontSize)]
)
result.addAttribute(.font, value: UIFont.boldSystemFont(ofSize: Values.verySmallFontSize), range: (text as NSString).range(of: "terms_of_service".localized()))
result.addAttribute(.font, value: UIFont.boldSystemFont(ofSize: Values.verySmallFontSize), range: (text as NSString).range(of: "privacy_policy".localized()))
return result
}()
AttributedText(attributedText)
.foregroundColor(themeColor: .textPrimary)
.frame(width: 262)
}
}
}

View File

@ -56,4 +56,27 @@ public class SessionHostingViewController<Content>: UIHostingController<Content>
navigationItem.titleView = container
}
internal func setUpNavBarSessionHeading() {
let headingImageView = UIImageView(
image: UIImage(named: "SessionHeading")?
.withRenderingMode(.alwaysTemplate)
)
headingImageView.themeTintColor = .textPrimary
headingImageView.contentMode = .scaleAspectFit
headingImageView.set(.width, to: 150)
headingImageView.set(.height, to: Values.mediumFontSize)
navigationItem.titleView = headingImageView
}
internal func setUpNavBarSessionIcon() {
let logoImageView = UIImageView()
logoImageView.image = #imageLiteral(resourceName: "SessionGreen32")
logoImageView.contentMode = .scaleAspectFit
logoImageView.set(.width, to: 32)
logoImageView.set(.height, to: 32)
navigationItem.titleView = logoImageView
}
}

View File

@ -0,0 +1,46 @@
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
import SwiftUI
struct AttributedTextBlock {
let content: String
let font: Font?
let color: Color?
}
public struct AttributedText: View {
var attributedText: NSAttributedString?
private var descriptions: [AttributedTextBlock] = []
public init(_ attributedText: NSAttributedString?) {
self.attributedText = attributedText
self.extractDescriptions()
}
private mutating func extractDescriptions() {
if let text = attributedText {
text.enumerateAttributes(in: NSMakeRange(0, text.length), options: [], using: { (attribute, range, stop) in
let substring = (text.string as NSString).substring(with: range)
let font = (attribute[.font] as? UIFont).map { Font($0) }
let color = (attribute[.foregroundColor] as? UIColor).map { Color($0) }
descriptions.append(AttributedTextBlock(content: substring,
font: font,
color: color))
})
}
}
public var body: some View {
let _ = print(descriptions)
descriptions.map { description in
var text: Text = Text(description.content)
if let font: Font = description.font { text = text.font(font) }
if let color: Color = description.color { text = text.foregroundColor(color) }
return text
}.reduce(Text("")) { (result, text) in
result + text
}
}
}

View File

@ -8,6 +8,12 @@ public extension View {
ThemeManager.currentTheme.colorSwiftUI(for: themeColor)
)
}
func backgroundColor(themeColor: ThemeValue) -> some View {
return self.background(
ThemeManager.currentTheme.colorSwiftUI(for: themeColor)
)
}
}
public extension Shape {
@ -16,4 +22,10 @@ public extension Shape {
ThemeManager.currentTheme.colorSwiftUI(for: themeColor) ?? Color.primary
)
}
func stroke(themeColor: ThemeValue) -> some View {
return self.stroke(
ThemeManager.currentTheme.colorSwiftUI(for: themeColor) ?? Color.primary
)
}
}