Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
signalapp
GitHub Repository: signalapp/Signal-iOS
Path: blob/main/Signal/Backups/Onboarding/BackupOnboardingIntroViewController.swift
1 views
//
// Copyright 2025 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//

import SignalServiceKit
import SignalUI
import SwiftUI

class BackupOnboardingIntroViewController: HostingController<BackupOnboardingIntroView> {
    init(
        onContinue: @escaping () -> Void,
        onNotNow: @escaping () -> Void,
    ) {
        super.init(wrappedView: BackupOnboardingIntroView(
            onContinue: onContinue,
            onNotNow: onNotNow,
        ))

        OWSTableViewController2.removeBackButtonText(viewController: self)
    }
}

// MARK: -

struct BackupOnboardingIntroView: View {
    private struct BulletPoint: Identifiable {
        let image: UIImage
        let text: String

        var id: String { text }
    }

    fileprivate let onContinue: () -> Void
    fileprivate let onNotNow: () -> Void

    private let bulletPoints: [BulletPoint] = [
        BulletPoint(
            image: .lock,
            text: OWSLocalizedString(
                "BACKUP_ONBOARDING_INTRO_BULLET_1",
                comment: "Bullet point on a view introducing Backups during an onboarding flow.",
            ),
        ),
        BulletPoint(
            image: .checkSquare,
            text: OWSLocalizedString(
                "BACKUP_ONBOARDING_INTRO_BULLET_2",
                comment: "Bullet point on a view introducing Backups during an onboarding flow.",
            ),
        ),
        BulletPoint(
            image: .trash,
            text: OWSLocalizedString(
                "BACKUP_ONBOARDING_INTRO_BULLET_3",
                comment: "Bullet point on a view introducing Backups during an onboarding flow.",
            ),
        ),
    ]

    private var titleString: AttributedString {
        var attributedString = AttributedString("BETA")
        attributedString.backgroundColor = Color.Signal.secondaryFill
        return attributedString
    }

    var body: some View {
        ScrollableContentPinnedFooterView {
            VStack {
                Spacer().frame(height: 20)

                Image(.backupsLogo)
                    .frame(width: 80, height: 80)

                Spacer().frame(height: 16)
                HStack {
                    Text(OWSLocalizedString(
                        "BACKUP_ONBOARDING_INTRO_TITLE",
                        comment: "Title for a view introducing Backups during an onboarding flow.",
                    ))
                    .font(Font(UIFont.dynamicTypeFont(ofStandardSize: 26)))
                    .fontWeight(.semibold)
                    .foregroundStyle(Color.Signal.label)
                }
                .padding(.horizontal, 32)
                .multilineTextAlignment(.center)

                Spacer().frame(height: 12)

                Text(OWSLocalizedString(
                    "BACKUP_ONBOARDING_INTRO_SUBTITLE",
                    comment: "Subtitle for a view introducing Backups during an onboarding flow.",
                ))
                .font(.body)
                .foregroundStyle(Color.Signal.secondaryLabel)
                .multilineTextAlignment(.center)
                .padding(.horizontal, 32)

                Spacer().frame(height: 32)

                VStack(alignment: .leading, spacing: 26) {
                    ForEach(bulletPoints) { bulletPoint in
                        HStack {
                            Label {
                                Text(bulletPoint.text)
                            } icon: {
                                Image(uiImage: bulletPoint.image)
                            }

                            Spacer()
                        }
                    }
                }
                .padding(.horizontal, 56)
                .frame(maxWidth: .infinity)
                .foregroundStyle(Color.Signal.label)
                .padding(.horizontal)
            }
        } pinnedFooter: {
            Button {
                onContinue()
            } label: {
                Text(CommonStrings.continueButton)
            }
            .buttonStyle(Registration.UI.LargePrimaryButtonStyle())
            .padding(.horizontal, 40)

            Spacer().frame(height: 16)

            Button {
                onNotNow()
            } label: {
                Text(CommonStrings.notNowButton)
            }
            .buttonStyle(Registration.UI.LargeSecondaryButtonStyle())
            .padding(.horizontal, 40)
        }
        .background(Color.Signal.groupedBackground)
    }
}

// MARK: -

#if DEBUG

@available(iOS 17, *)
#Preview {
    SheetPreviewViewController(sheet: OWSNavigationController(rootViewController: BackupOnboardingIntroViewController(
        onContinue: { print("Continuing...!") },
        onNotNow: { print("Not now...!") },
    )))
}

#endif