Skip to content

Commit

Permalink
Merge pull request #1 from catloafsoft/main
Browse files Browse the repository at this point in the history
Added macOS, tvOS and localization support
  • Loading branch information
frios authored Jul 4, 2023
2 parents 3835143 + 10d441e commit d912715
Show file tree
Hide file tree
Showing 24 changed files with 826 additions and 60 deletions.
23 changes: 23 additions & 0 deletions .github/workflows/swift.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# This workflow will build a Swift project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift

name: Swift

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:
build:

runs-on: macos-latest

steps:
- uses: actions/checkout@v3
- name: Build
run: swift build -v
- name: Check Package
run: swift package describe

14 changes: 7 additions & 7 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
// swift-tools-version:5.3
// swift-tools-version:5.5
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "WhatsNew",
defaultLocalization: "en",
platforms: [
.iOS(.v14)
.iOS(.v15),
.macOS(.v12),
.tvOS(.v15)
],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "WhatsNew",
targets: ["WhatsNew"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "WhatsNew",
dependencies: [])
dependencies: []
)
]
)
24 changes: 13 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@
This package is a simple way of adding What's New pages to your app. The pages
are dynamically created based on the number of items passed to the WhatsNewView.

How to use:
This framework supports iOS, iPadOS, tv)S (15.0 and above) and macOS (12.0 and above).

## How to use:

1) In your target's General Settings, make sure your app Display Name is set as you want it.

2) Create the content for each What's New page you want displayed. You can use What's New BulletPoint struct to add bullet points with images, bold titles and explanatory text. The compnent will use whatever accent color you set for the page.
2) Create the content for each What's New page you want displayed. You can use What's New `BulletPointView` struct to add bullet points with images, bold titles and explanatory text. The component will use whatever accent color you set for the page.

```
```swift
struct WhatsNewPageView: View {
var body: some View {
VStack (alignment: .leading, spacing: 10){
BulletPointView(title: "We now have SEARCH!!!",
imageName: "paintbrush.fill",
systemName: "paintbrush.fill",
text: "Search to find books that have been on previous best seller lists.")
BulletPointView(title: "More bugs squashed.",
imageName: "myTruck",
Expand All @@ -26,20 +28,20 @@ struct WhatsNewPageView: View {
.accentColor(Color.red)
}
}
```

... same for each additional page

```

3) Import WhatsNew into your startup file.

4) In your @main struct, create a state variable to control display of WhatsNew pages.
4) In your `@main` struct, create a state variable to control display of WhatsNew pages.

5) Instantiate a WhatsNew class. You can use the (alwaysShow: true) parameter to always display WhatsNew content for testing.
5) Instantiate a `WhatsNew` class. You can use the `(alwaysShow: true)` parameter to always display WhatsNew content for testing.

6) Add the .onAppear modifier to check for updates in the version number of the app. Add .sheet modifier to your ContentView() call to display the What's new compomnent.
6) Add the `.onAppear` modifier to check for updates in the version number of the app. Add the `.sheet` modifier to your `ContentView()` call to display the What's New compomnent.

```
```swift
import SwiftUI
import WhatsNew

Expand All @@ -51,9 +53,9 @@ struct PackageTesterApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.onAppear(perform: {
.onAppear {
whatsNew.checkForUpdate(showWhatsNew: $showWhatsNew)
})
}
.sheet(isPresented: $showWhatsNew) {
WhatsNewView {
WhatsNewPageView()
Expand Down
58 changes: 40 additions & 18 deletions Sources/WhatsNew/BulletPointView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,49 @@ let frameWidth = 50.0

public struct BulletPointView: View {
let title: String
let imageName: String
let imageName: String?
let systemName: String?
let text : String

public init(title: String = "New feature",
imageName: String = "circle.fill",
text: String = "This is a new feature for this app. And this text should wrap.") {
self.title = title
self.imageName = imageName
self.systemName = nil
self.text = text
}

public init(title: String = "New feature",
systemName: String = "circle.fill",
text: String = "This is a new feature for this app with a system icon. And this text should wrap.") {
self.title = title
self.imageName = nil
self.systemName = systemName
self.text = text
}

public var body: some View {
HStack (alignment: .center){
if let image = UIImage(named: imageName) {
#if os(iOS)
if let name = imageName, let image = UIImage(named: name) {
Image(uiImage: image)
.resizable()
.renderingMode(.template)
.frame(height: frameWidth * (image.size.height/image.size.width))
.bulletStyle()
} else {
Image(systemName: imageName)
}
#elseif os(macOS)
if let name = imageName, let image = NSImage(named: NSImage.Name(name)) {
Image(nsImage: image)
.resizable()
.renderingMode(.template)
.frame(height: frameWidth * (CGFloat(image.size.height)/CGFloat(image.size.width)))
.bulletStyle()
}
#endif
if let system = systemName {
Image(systemName: system)
.renderingMode(.template)
.bulletStyle()
.font(.title)
Expand All @@ -51,20 +73,6 @@ public struct BulletPointView: View {
}
}

struct BulletPointView_Previews: PreviewProvider {
static var previews: some View {
VStack (alignment: .leading){
BulletPointView(imageName: "square.and.pencil")
BulletPointView(imageName: "hare.fill")
BulletPointView(imageName: "circle.fill")
BulletPointView(imageName: "car.2.fill")
BulletPointView(imageName: "switch.2")
BulletPointView(imageName: "ellipsis")
}.padding()
}
}


struct Bullet: ViewModifier {
func body(content: Content) -> some View {
content
Expand All @@ -80,3 +88,17 @@ extension View {
}
}

#if DEBUG
struct BulletPointView_Previews: PreviewProvider {
static var previews: some View {
VStack (alignment: .leading){
BulletPointView(systemName: "square.and.pencil")
BulletPointView(systemName: "hare.fill")
BulletPointView(systemName: "circle.fill")
BulletPointView(systemName: "car.2.fill")
BulletPointView(systemName: "switch.2")
BulletPointView(systemName: "ellipsis")
}.padding()
}
}
#endif
5 changes: 5 additions & 0 deletions Sources/WhatsNew/Resources/de.lproj/Localizable.strings
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* Button */
"Continue" = "Fortfahren";

/* Dialog Title */
"What's New\nin %@" = "Neues\nin %@";
6 changes: 6 additions & 0 deletions Sources/WhatsNew/Resources/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/* Button */
"Continue" = "Continue";

/* Dialog Title */
"What's New\nin %@" = "What's New\nin %@";

5 changes: 5 additions & 0 deletions Sources/WhatsNew/Resources/es.lproj/Localizable.strings
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* Button */
"Continue" = "Continuar";

/* Dialog Title */
"What's New\nin %@" = "Lo nuevo\nen %@";
5 changes: 5 additions & 0 deletions Sources/WhatsNew/Resources/fr.lproj/Localizable.strings
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* Button */
"Continue" = "Continuer";

/* Dialog Title */
"What's New\nin %@" = "Nouveautés\ndans %@";
5 changes: 5 additions & 0 deletions Sources/WhatsNew/Resources/it.lproj/Localizable.strings
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* Button */
"Continue" = "Continua";

/* Dialog Title */
"What's New\nin %@" = "Novità\nin %@";
5 changes: 5 additions & 0 deletions Sources/WhatsNew/Resources/nl.lproj/Localizable.strings
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* Button */
"Continue" = "Doorgaan";

/* Dialog Title */
"What's New\nin %@" = "Wat is er nieuw\nin %@";
5 changes: 5 additions & 0 deletions Sources/WhatsNew/Resources/pt-BR.lproj/Localizable.strings
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* Button */
"Continue" = "Continuar";

/* Dialog Title */
"What's New\nin %@" = "Novidades\nem %@";
47 changes: 40 additions & 7 deletions Sources/WhatsNew/WhatsNew.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,38 +10,71 @@ import SwiftUI

public class WhatsNew: ObservableObject {

@AppStorage("savedVersion") var savedVersion: String = "1.000.000"
@AppStorage("savedVersion") var savedVersion: String?

var alwaysShow = false

public init(alwaysShow: Bool = false) {
self.alwaysShow = alwaysShow
}

//check the currentVersion against the saved version
public func checkForUpdate( showWhatsNew: Binding<Bool> ) {
let currentVersion = getCurrentAppVersion()
print("Current Version: \(currentVersion)\nSaved Version: \(savedVersion)")
#if DEBUG
print("Current Version: \(currentVersion)\nSaved Version: \(savedVersion ?? "None")")
#endif
if alwaysShow {
showWhatsNew.wrappedValue = alwaysShow
return
}

if savedVersion < currentVersion {
savedVersion = currentVersion
// If this is the first launch (no saved version), save the current version and return
guard let savedVersion = savedVersion else {
self.savedVersion = currentVersion
return
}

if isVersion(savedVersion, lessThan: currentVersion) {
self.savedVersion = currentVersion
showWhatsNew.wrappedValue = true
} else if savedVersion > currentVersion {
} else if isVersion(savedVersion, greaterThan: currentVersion) {
#if DEBUG
print("App is behind!")
savedVersion = currentVersion
#endif
self.savedVersion = currentVersion
} else {
#if DEBUG
print("App is up to date!")
#endif
}
}

// Get current Version of the App
func getCurrentAppVersion() -> String {
return "\(Bundle.main.infoDictionary?["CFBundleShortVersionString"] as! String).\(Bundle.main.infoDictionary?["CFBundleVersion"] as! String)"
}

// Compare version strings as version numbers
private func isVersion(_ version1: String, lessThan version2: String) -> Bool {
let v1Components = version1.split(separator: ".").compactMap { Int($0) }
let v2Components = version2.split(separator: ".").compactMap { Int($0) }

for (v1, v2) in zip(v1Components, v2Components) {
if v1 < v2 {
return true
} else if v1 > v2 {
return false
}
}

return v1Components.count < v2Components.count
}

private func isVersion(_ version1: String, greaterThan version2: String) -> Bool {
return !isVersion(version1, lessThan: version2) && version1 != version2
}

}


Loading

0 comments on commit d912715

Please sign in to comment.