Skip to content

Commit 3d77f9f

Browse files
committed
Initial commit
0 parents  commit 3d77f9f

17 files changed

Lines changed: 1016 additions & 0 deletions

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
/*.xcodeproj
5+
xcuserdata/
6+
DerivedData/
7+
.swiftpm/config/registries.json
8+
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
9+
.netrc

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 GoodRequest
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

Package.resolved

Lines changed: 132 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// swift-tools-version: 6.0
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "GoodRemoteNotifier",
8+
platforms: [
9+
.iOS(.v16),
10+
.macOS(.v13)
11+
],
12+
products: [
13+
.library(
14+
name: "GoodRemoteNotifier",
15+
targets: ["GoodRemoteNotifier"]
16+
)
17+
],
18+
dependencies: [
19+
.package(url: "https://github.com/firebase/firebase-ios-sdk.git", .upToNextMajor(from: "11.9.0")),
20+
.package(url: "https://github.com/GoodRequest/GoodLogger.git", .upToNextMajor(from: "1.2.3"))
21+
],
22+
targets: [
23+
.target(
24+
name: "GoodRemoteNotifier",
25+
dependencies: [
26+
.product(name: "FirebaseCore", package: "firebase-ios-sdk"),
27+
.product(name: "FirebaseRemoteConfig", package: "firebase-ios-sdk"),
28+
.product(name: "GoodLogger", package: "GoodLogger")
29+
],
30+
path: "./Sources/GoodRemoteNotifier",
31+
swiftSettings: [.swiftLanguageMode(.v6)]
32+
),
33+
34+
]
35+
)

README.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# GoodRemoteNotifier
2+
3+
`GoodRemoteNotifier` is a Swift package designed to fetch and display remote notifications based on a JSON template. It allows you to integrate messages, titles, and buttons for different languages, all fetched from Firebase Remote Config.
4+
5+
This package is useful for applications that need to display localized messages and UI elements like update notifications, with multiple language capabilities and appearance customization.
6+
7+
## Features
8+
9+
- Fetches remote configuration based on a given topic.
10+
- Supports multi-language messages for app notifications (e.g., update alerts).
11+
- Displays customizable messages, titles, and buttons based on the selected language.
12+
- Supports debug mode for easier testing.
13+
- Allows customization of the appearance of messages.
14+
15+
## Installation
16+
17+
You can install `GoodRemoteNotifier` via Swift Package Manager by adding it to your `Package.swift` file:
18+
19+
```swift
20+
dependencies: [
21+
.package(url: "https://github.com/yourusername/GoodRemoteNotifier.git", from: "1.0.0")
22+
]
23+
```
24+
25+
## Configuration Data
26+
27+
The remote configuration is fetched from Firebase Remote Config in JSON format. The JSON template for the configuration should follow this structure:
28+
29+
- **frequency** (optional): Defines how often the notification should appear (e.g., once, daily, weekly, monthly). If not defined, the default value is `once`.
30+
- **title**: Localized titles for the notification. These will be displayed based on the user's selected language.
31+
- **message**: Localized messages containing the content of the notification. These messages explain what's new in the app or what the user should do.
32+
- **updateButton** (optional): Localized text for the action button, used for opening the app in the app store.
33+
- **closeButton** (optional): Localized text for the close button, used for dismissing the notification. If not defined, the message is not dismissible.
34+
35+
> **⚠️ Important**: If the `frequency`, `title`, or `message` values change for the specified language, the notification will be treated as a new message.
36+
37+
```JSON
38+
{
39+
"frequency": "daily",
40+
"title": {
41+
"en": "An Update is Available!",
42+
"de": "Ein Update ist verfügbar!"
43+
},
44+
"message": {
45+
"en": "The new version of the app is here...",
46+
"de": "Die neue Version der App ist da..."
47+
},
48+
"updateButton": {
49+
"en": "Update Now",
50+
"de": "Jetzt aktualisieren"
51+
},
52+
"closeButton": {
53+
"en": "Close",
54+
"de": "Schließen"
55+
}
56+
}
57+
```
58+
59+
## Usage
60+
61+
Make sure that you have imported the `GoogleService-Info.plist` file into your project.
62+
Additionally, ensure that `Firebase.configure()` is called before initializing the GoodRemote notifier.
63+
64+
Initialize the notifier in `AppDelegate` or in the `@main` App struct for SwiftUI. It will automatically listen for the selected topic and display notifications based on the chosen frequency.
65+
66+
```Swift
67+
import GoodRemoteNotifier
68+
69+
let notifier = GoodRemoteNotifier(
70+
appId: "123456789", // The App Store ID of the app for redirection.
71+
topic: "update", // Firebase remote config parameter key
72+
selectedLanguage: { "en" },
73+
appearance: RemoteMessageAppearance.default, // Configuration for how remote messages should be displayed.
74+
isDebugSession: { false } // If true, disables caching and sets the minimum fetching interval to 0.
75+
)
76+
```
77+
78+
## License
79+
80+
`GoodRemoteNotifier` is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//
2+
// SwiftUIExtensions.swift
3+
// GoodRemoteNotifier
4+
//
5+
// Created by Marek Vríčan on 17/04/2025.
6+
//
7+
8+
import Foundation
9+
10+
internal extension Bundle {
11+
12+
/// Retrieves the last icon file name from the app's primary icon settings in the Info.plist.
13+
/// - Returns: The name of the last icon file in the array of icon files, or `nil` if not found.
14+
var iconFileName: String? {
15+
guard let icons = infoDictionary?["CFBundleIcons"] as? [String: Any],
16+
let primaryIcon = icons["CFBundlePrimaryIcon"] as? [String: Any],
17+
let iconFiles = primaryIcon["CFBundleIconFiles"] as? [String],
18+
let iconFileName = iconFiles.last
19+
else { return nil }
20+
21+
return iconFileName
22+
}
23+
24+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//
2+
// UIViewControllerExtensions.swift
3+
// GoodRemoteNotifier
4+
//
5+
// Created by Marek Vríčan on 06/03/2025.
6+
//
7+
8+
import UIKit
9+
10+
internal extension UIViewController {
11+
12+
/// Adds a blur effect to the view with an animation.
13+
/// - Parameters:
14+
/// - duration: The duration of the blur effect animation. Default is `0.2` seconds.
15+
/// - completion: An optional closure that is called after the animation completes.
16+
func addBlurEffect(duration: TimeInterval = 0.2, completion: (() -> Void)? = nil) {
17+
let blurView = UIVisualEffectView(effect: UIBlurEffect(style: .systemThinMaterialDark))
18+
blurView.layer.opacity = 0
19+
blurView.frame = view.bounds
20+
blurView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
21+
view.addSubview(blurView)
22+
23+
UIView.animate(withDuration: duration) {
24+
blurView.layer.opacity = 1
25+
} completion: { _ in completion?() }
26+
}
27+
28+
29+
/// Removes the blur effect from the view with an animation.
30+
/// - Parameters:
31+
/// - duration: The duration of the blur effect removal animation. Default is `0.2` seconds.
32+
/// - completion: An optional closure that is called after the animation completes.
33+
func removeBlurEffect(duration: TimeInterval = 0.2, completion: (() -> Void)? = nil) {
34+
guard let blurView = view.subviews.first(where: { $0 is UIVisualEffectView }) else { return }
35+
36+
UIView.animate(withDuration: duration) {
37+
blurView.layer.opacity = 0
38+
} completion: { _ in completion?() }
39+
}
40+
41+
}

0 commit comments

Comments
 (0)