Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 16 additions & 20 deletions Sample/Sample/UI/NewFeatureOnboardingSheetView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import SwiftUI
import OnboardingUI

struct NewFeatureOnboardingSheetView: View {
@Environment(\.dismiss) private var dismiss

var action: () -> Void

init(action: @escaping () -> Void) {
Expand All @@ -19,33 +17,31 @@ struct NewFeatureOnboardingSheetView: View {

var body: some View {
OnboardingSheetView {
OnboardingTitle("What's New in\nOnboardingUI")
Text("What's New in\nOnboardingUI")
.onboardingTextFormatting(style: .title)
} content: {
OnboardingItem(systemName: "tree",shape: .green) {
OnboardingSubtitle("New AppVersionManager environment variable")
OnboardingContent("The new AppVersionManager environment variable allows you to display onboarding at the intended time.")
OnboardingItem(systemName: "wrench.and.screwdriver",shape: .red) {
Text("New AppVersionManager environment variable")
.onboardingTextFormatting(style: .subtitle)
Text("The new AppVersionManager environment variable allows you to display onboarding at the intended time.")
.onboardingTextFormatting(style: .content)
}

OnboardingItem(systemName: "building.columns",shape: .blue) {
OnboardingSubtitle("New Onboarding protocol and Feature structure")
OnboardingContent("The new Onboarding protocol and Feature structure make it easier to create onboarding. There is no need to build views.")
Text("New Onboarding protocol and Feature structure")
.onboardingTextFormatting(style: .subtitle)
Text("The new Onboarding protocol and Feature structure make it easier to create onboarding. There is no need to build views.")
.onboardingTextFormatting(style: .content)
}

OnboardingItem(systemName: "wrench.and.screwdriver",shape: .orange) {
OnboardingSubtitle("Customize the look and feel")
OnboardingContent("Of course, it is also customizable. You can build onboarding at will.")
}

#if os(tvOS)
OnboardingItem(systemName: "ellipsis",shape: .white) {
OnboardingSubtitle("Many other benefits")
OnboardingContent("Now, tvOS is also supported, making it easy to create onboarding. Now you can create onboarding for all platforms except watchOS.")
Text("Customize the look and feel")
.onboardingTextFormatting(style: .subtitle)
Text("Of course, it is also customizable. You can build onboarding at will.")
.onboardingTextFormatting(style: .content)
}
#endif
} button: {
ContinueButton(color: .accentColor, action: {
dismiss()
})
ContinueButton(color: .accentColor, action: action)
}
}
}
Expand Down
21 changes: 14 additions & 7 deletions Sample/Sample/UI/WelcomeOnboardingSheetView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,28 @@ struct WelcomeOnboardingSheetView: View {

var body: some View {
OnboardingSheetView {
OnboardingTitle("Welcome to\nOnboardingUI")
Text("Welcome to\nOnboardingUI")
.onboardingTextFormatting(style: .title)
} content: {
OnboardingItem(systemName: "applescript",shape: .red) {
OnboardingSubtitle("Easy to Make")
OnboardingContent("Onboarding screens like Apple's stock apps can be easily created with SwiftUI.")
Text("Easy to Make")
.onboardingTextFormatting(style: .subtitle)
Text("Onboarding screens like Apple's stock apps can be easily created with SwiftUI.")
.onboardingTextFormatting(style: .content)
}

OnboardingItem(systemName: "apple.logo") {
OnboardingSubtitle("Not only for iPhone, but also for Mac, iPad, Vision Pro")
OnboardingContent("It supports not only iPhone, but also Mac, iPad, and Vision Pro. Therefore, there is no need to rewrite the code for each device.")
Text("Not only for iPhone, but also for Mac, iPad, Vision Pro")
.onboardingTextFormatting(style: .subtitle)
Text("It supports not only iPhone, but also Mac, iPad, and Vision Pro. Therefore, there is no need to rewrite the code for each device.")
.onboardingTextFormatting(style: .content)
}

OnboardingItem(systemName: "circle.badge.checkmark",mode: .palette,primary: .primary,secondary: .blue) {
OnboardingSubtitle("Customize SF Symbols")
OnboardingContent("When using a highly customizable implementation method, multi-color and SF symbol hierarchies are supported and can be freely customized.")
Text("Customize SF Symbols")
.onboardingTextFormatting(style: .subtitle)
Text("When using a highly customizable implementation method, multi-color and SF symbol hierarchies are supported and can be freely customized.")
.onboardingTextFormatting(style: .content)
}

#if os(tvOS)
Expand Down
71 changes: 40 additions & 31 deletions Sources/OnboardingUI/Processing/AppVersionManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ public class AppVersionManager {
userDefaults.set(lastOpenedVersion, forKey: "LastOpenedVersion")
}
}
/// Whether or not this is the first activation
public var isTheFirstLaunch: Bool {
/// Whether or not this is the first activation.
public var isTheFirstActivation: Bool {
get {
return lastOpenedVersion == ""
}
Expand All @@ -35,53 +35,62 @@ public class AppVersionManager {
/// Variable to detect if the major version number has increased.
public var isMajorVersionUpdated: Bool {
get {
if !lastOpenedVersion.isEmpty {
let lastOpenedComponents = parseVersion(lastOpenedVersion)
let currentComponents = parseVersion(version)
return lastOpenedComponents.major < currentComponents.major
} else {
return false
}
let lastOpenedComponents = filled(splitByDot(lastOpenedVersion), count: 3)
let currentComponents = filled(splitByDot(version), count: 3)
return lastOpenedComponents[0] < currentComponents[0]
}

set {
lastOpenedVersion = version
}
}
/// Variable to detect if the minor version number or higher has increased.
public var isMinorVersionUpdated: Bool {
public var isMinorOrPatchVersionUpdated: Bool {
get {
if !lastOpenedVersion.isEmpty {
let lastOpenedComponents = parseVersion(lastOpenedVersion)
let currentComponents = parseVersion(version)
return lastOpenedComponents.major == currentComponents.major && lastOpenedComponents.minor < currentComponents.minor
} else {
return false
}
let lastOpenedComponents = filled(splitByDot(lastOpenedVersion), count: 3)
let currentComponents = filled(splitByDot(version), count: 3)
return lastOpenedComponents[0] == currentComponents[0] &&
(lastOpenedComponents[1] < currentComponents[1] ||
(lastOpenedComponents[1] == currentComponents[1] && lastOpenedComponents[2] < currentComponents[2]))
}

set {
lastOpenedVersion = version
}
}
/// Default initializer
/// Creates a new AppVersionManager instance.
public init() {
self.version = Bundle.main
.object(
forInfoDictionaryKey: "CFBundleShortVersionString"
) as! String
self.lastOpenedVersion = userDefaults
.string(forKey: "LastOpenedVersion") ?? ""
}

func parseVersion(_ versionString: String) -> (major: Int, minor: Int, patch: Int) {
var components = versionString.split(separator: ".").compactMap { Int($0) }
components = (0..<3).map { $0 < components.count ? components[$0] : 0 }
return (major: components[0], minor: components[1], patch: components[2])
self.version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
self.lastOpenedVersion = userDefaults.string(forKey: "LastOpenedVersion") ?? ""
}
}
/// AppVersionManager environment values
/// AppVersionManager environment key
/// The environment key for the AppVersionManager.
@available(iOS 17.0,macOS 14.0,watchOS 10.0,tvOS 17.0,visionOS 1.0,*)
public struct AppVersionManagerKey: EnvironmentKey {
public static var defaultValue = AppVersionManager()
}
/// AppVersionManager environment values
public extension EnvironmentValues {
@Entry var appVersionManager: AppVersionManager = AppVersionManager()
/// Accessor for the AppVersionManager value in EnvironmentValues.
var appVersionManager: AppVersionManager {
get { self[AppVersionManagerKey.self] }
set { self[AppVersionManagerKey.self] = newValue }
}
}
/// Function to split the version number dot by dot
@available(iOS 17.0,macOS 14.0,watchOS 10.0,tvOS 17.0,visionOS 1.0,*)
func splitByDot(_ versionNumber: String) -> [Int] {
return versionNumber.split(separator: ".").map { string -> Int in
return Int(string) ?? 0
}
}
/// Function to unify the number of elements in an array
@available(iOS 17.0,macOS 14.0,watchOS 10.0,tvOS 17.0,visionOS 1.0,*)
func filled(_ target: [Int], count: Int) -> [Int] {
return (0..<count).map { i -> Int in
(i < target.count) ? target[i] : 0
}
}

Loading
Loading