Skip to content

Commit bbef0c5

Browse files
authored
Merge pull request #9 from gokhanamal/fix/settingsview-navigation-and-review
Fix SettingsView navigation + Write a Review action
2 parents 0085e2e + e9d6071 commit bbef0c5

File tree

2 files changed

+55
-18
lines changed

2 files changed

+55
-18
lines changed

Sources/IndieBuilderKit/Services/RatingService.swift

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,53 @@ import SwiftUI
55
/// Service for handling app rating requests using StoreKit's native rating dialog
66
public class RatingService {
77
public static let shared = RatingService()
8-
8+
9+
// These are placeholders for future “smart prompting” rules.
10+
// Kept for now to avoid a breaking change to any planned roadmap.
911
private let minimumLaunchCountForRating = 3
1012
private let minimumDaysSinceInstall = 7
1113
private let minimumDaysBetweenRatingRequests = 30
12-
14+
1315
private init() {}
14-
16+
1517
/// Force request rating (useful for manual "Rate App" buttons)
1618
@MainActor
1719
public func requestRating() {
1820
guard let windowScene = UIApplication.shared.connectedScenes
1921
.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene else {
2022
return
2123
}
22-
24+
2325
SKStoreReviewController.requestReview(in: windowScene)
2426
}
25-
26-
/// Open App Store review page directly
27+
28+
/// Open App Store review page directly.
29+
///
30+
/// - Parameter appId: The numeric App Store ID (e.g. "123456789").
2731
public func openAppStoreReview(appId: String) {
28-
let urlString = "https://apps.apple.com/app/id\(appId)?action=write-review"
29-
guard let url = URL(string: urlString) else { return }
30-
31-
if UIApplication.shared.canOpenURL(url) {
32-
UIApplication.shared.open(url)
32+
let trimmed = appId.trimmingCharacters(in: .whitespacesAndNewlines)
33+
guard !trimmed.isEmpty else { return }
34+
guard let url = URL(string: "https://apps.apple.com/app/id\(trimmed)?action=write-review") else { return }
35+
36+
UIApplication.shared.open(url)
37+
}
38+
39+
/// Open App Store review page using an App Store URL (extracts the app id from the URL).
40+
///
41+
/// If parsing fails, falls back to opening the provided URL.
42+
public func openAppStoreReview(appStoreURL: URL) {
43+
let s = appStoreURL.absoluteString
44+
45+
// Typical formats include:
46+
// - https://apps.apple.com/us/app/some-app/id123456789
47+
// - https://apps.apple.com/app/id123456789
48+
if let match = s.range(of: #"id(\d+)"#, options: .regularExpression) {
49+
let idPart = String(s[match]) // e.g. "id123456789"
50+
let appId = idPart.replacingOccurrences(of: "id", with: "")
51+
openAppStoreReview(appId: appId)
52+
return
3353
}
54+
55+
UIApplication.shared.open(appStoreURL)
3456
}
3557
}

Sources/IndieBuilderKit/UI/SettingsView.swift

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,20 +57,36 @@ public struct AppSettingsConfiguration {
5757

5858
public struct SettingsView: View {
5959
private let configuration: AppSettingsConfiguration
60+
private let embedInNavigation: Bool
61+
6062
@Environment(\.dismiss) private var dismiss
6163
@State private var showingMailComposer = false
6264
@State private var showingShareSheet = false
6365
#if canImport(MessageUI)
6466
@State private var mailResult: Result<MFMailComposeResult, Error>? = nil
6567
#endif
66-
67-
public init(configuration: AppSettingsConfiguration) {
68+
69+
/// - Parameter embedInNavigation: Set to `false` when presenting inside an existing `NavigationStack`
70+
/// to avoid a double navigation bar.
71+
public init(configuration: AppSettingsConfiguration, embedInNavigation: Bool = true) {
6872
self.configuration = configuration
73+
self.embedInNavigation = embedInNavigation
6974
}
70-
75+
7176
public var body: some View {
72-
NavigationView {
73-
List {
77+
Group {
78+
if embedInNavigation {
79+
NavigationStack {
80+
content
81+
}
82+
} else {
83+
content
84+
}
85+
}
86+
}
87+
88+
private var content: some View {
89+
List {
7490
// App Actions Section
7591
Section {
7692
SettingsRow(
@@ -265,7 +281,6 @@ public struct SettingsView: View {
265281
])
266282
}
267283
}
268-
}
269284
}
270285

271286
private var hasSupportSection: Bool {
@@ -294,7 +309,7 @@ public struct SettingsView: View {
294309
}
295310

296311
private func handleWriteReview(url: URL) {
297-
RatingService.shared.openAppStoreReview(appId: "")
312+
RatingService.shared.openAppStoreReview(appStoreURL: url)
298313
}
299314

300315
private func handleContactUs() {

0 commit comments

Comments
 (0)