|
|
@@ -696,6 +696,51 @@ private extension ViewController {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private func openRateUsDestination() {
|
|
|
+ let configured = (Bundle.main.object(forInfoDictionaryKey: "RateUsURL") as? String)?
|
|
|
+ .trimmingCharacters(in: .whitespacesAndNewlines)
|
|
|
+ let placeholder = (Bundle.main.object(forInfoDictionaryKey: "AppLaunchPlaceholderURL") as? String)?
|
|
|
+ .trimmingCharacters(in: .whitespacesAndNewlines)
|
|
|
+ let hardcodedRateUsURL = "https://apps.apple.com/pk/app/meeting-app-for-google-meet/id6654920763?mt=12"
|
|
|
+
|
|
|
+ var candidateStrings = [String]()
|
|
|
+ if let configured, !configured.isEmpty {
|
|
|
+ candidateStrings.append(configured)
|
|
|
+ if let appID = extractAppleAppID(from: configured) {
|
|
|
+ candidateStrings.append("macappstore://apps.apple.com/app/id\(appID)")
|
|
|
+ candidateStrings.append("macappstore://itunes.apple.com/app/id\(appID)")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ candidateStrings.append(hardcodedRateUsURL)
|
|
|
+ candidateStrings.append("macappstore://apps.apple.com/app/id6654920763")
|
|
|
+ candidateStrings.append("macappstore://itunes.apple.com/app/id6654920763")
|
|
|
+ if let placeholder, !placeholder.isEmpty {
|
|
|
+ candidateStrings.append(placeholder)
|
|
|
+ }
|
|
|
+
|
|
|
+ for candidate in candidateStrings {
|
|
|
+ guard let url = URL(string: candidate) else { continue }
|
|
|
+ if NSWorkspace.shared.open(url) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ showSimpleAlert(
|
|
|
+ title: "Unable to Open Rate Page",
|
|
|
+ message: "Could not open the App Store rating page. Please try again."
|
|
|
+ )
|
|
|
+
|
|
|
+ requestAppRatingIfEligible(markAsRated: true)
|
|
|
+ }
|
|
|
+
|
|
|
+ private func extractAppleAppID(from urlString: String) -> String? {
|
|
|
+ guard let match = urlString.range(of: "id[0-9]+", options: .regularExpression) else {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ let token = String(urlString[match])
|
|
|
+ return String(token.dropFirst())
|
|
|
+ }
|
|
|
+
|
|
|
private func openInSafari(url: URL) {
|
|
|
guard let safariAppURL = NSWorkspace.shared.urlForApplication(withBundleIdentifier: "com.apple.Safari") else {
|
|
|
NSWorkspace.shared.open(url)
|
|
|
@@ -836,18 +881,19 @@ private extension ViewController {
|
|
|
case .rateUs:
|
|
|
settingsPopover?.performClose(nil)
|
|
|
settingsPopover = nil
|
|
|
- requestAppRatingIfEligible(markAsRated: true)
|
|
|
+ openRateUsDestination()
|
|
|
case .support:
|
|
|
settingsPopover?.performClose(nil)
|
|
|
settingsPopover = nil
|
|
|
- if let url = URL(string: "https://support.google.com/meet") {
|
|
|
+ if let supportURL = Bundle.main.object(forInfoDictionaryKey: "SupportURL") as? String,
|
|
|
+ let url = URL(string: supportURL) {
|
|
|
openInAppBrowser(with: url, policy: inAppBrowserDefaultPolicy)
|
|
|
}
|
|
|
case .moreApps:
|
|
|
settingsPopover?.performClose(nil)
|
|
|
settingsPopover = nil
|
|
|
- // Replace with your App Store developer page URL.
|
|
|
- if let url = URL(string: "https://apps.apple.com/developer/id0000000000") {
|
|
|
+ if let moreAppsURL = Bundle.main.object(forInfoDictionaryKey: "MoreAppsURL") as? String,
|
|
|
+ let url = URL(string: moreAppsURL) {
|
|
|
openInAppBrowser(with: url, policy: inAppBrowserDefaultPolicy)
|
|
|
}
|
|
|
case .shareApp:
|
|
|
@@ -1056,10 +1102,11 @@ private extension ViewController {
|
|
|
@objc private func paywallFooterLinkClicked(_ sender: NSClickGestureRecognizer) {
|
|
|
guard let view = sender.view else { return }
|
|
|
let text = (view.subviews.first { $0 is NSTextField } as? NSTextField)?.stringValue ?? "Link"
|
|
|
+ let defaultURL = (Bundle.main.object(forInfoDictionaryKey: "AppLaunchPlaceholderURL") as? String) ?? "https://example.com/app-link-coming-soon"
|
|
|
let map: [String: String] = [
|
|
|
- "Privacy Policy": "https://policies.google.com/privacy",
|
|
|
- "Support": "https://support.google.com/meet",
|
|
|
- "Terms of Services": "https://policies.google.com/terms"
|
|
|
+ "Privacy Policy": (Bundle.main.object(forInfoDictionaryKey: "PrivacyPolicyURL") as? String) ?? defaultURL,
|
|
|
+ "Support": (Bundle.main.object(forInfoDictionaryKey: "SupportURL") as? String) ?? defaultURL,
|
|
|
+ "Terms of Services": (Bundle.main.object(forInfoDictionaryKey: "TermsOfServiceURL") as? String) ?? defaultURL
|
|
|
]
|
|
|
if let urlString = map[text], let url = URL(string: urlString) {
|
|
|
openInAppBrowser(with: url, policy: inAppBrowserDefaultPolicy)
|
|
|
@@ -1251,7 +1298,7 @@ private extension ViewController {
|
|
|
}
|
|
|
|
|
|
private var shouldShowRateUsInSettings: Bool {
|
|
|
- storeKitCoordinator.hasPremiumAccess && !userHasRated && hasReachedRatingUsageThreshold
|
|
|
+ true
|
|
|
}
|
|
|
|
|
|
private func migrateLegacyRatingStateIfNeeded() {
|
|
|
@@ -4360,9 +4407,14 @@ private final class SettingsMenuViewController: NSViewController {
|
|
|
}
|
|
|
|
|
|
private func settingsActionRow(icon: String, title: String, action: SettingsAction) -> NSView {
|
|
|
- let row = HoverTrackingView()
|
|
|
+ let row = HoverButton(title: "", target: self, action: #selector(settingsActionButtonPressed(_:)))
|
|
|
+ row.tag = action.rawValue
|
|
|
+ row.isBordered = false
|
|
|
row.translatesAutoresizingMaskIntoConstraints = false
|
|
|
row.heightAnchor.constraint(equalToConstant: 42).isActive = true
|
|
|
+ row.wantsLayer = true
|
|
|
+ row.layer?.cornerRadius = 10
|
|
|
+ row.layer?.backgroundColor = NSColor.clear.cgColor
|
|
|
|
|
|
let iconLabel = NSTextField(labelWithString: icon)
|
|
|
iconLabel.translatesAutoresizingMaskIntoConstraints = false
|
|
|
@@ -4384,12 +4436,7 @@ private final class SettingsMenuViewController: NSViewController {
|
|
|
titleLabel.centerYAnchor.constraint(equalTo: row.centerYAnchor)
|
|
|
])
|
|
|
|
|
|
- let click = NSClickGestureRecognizer(target: self, action: #selector(settingsActionClicked(_:)))
|
|
|
- row.addGestureRecognizer(click)
|
|
|
- row.identifier = NSUserInterfaceItemIdentifier(rawValue: "\(action.rawValue)")
|
|
|
row.onHoverChanged = { hovering in
|
|
|
- row.wantsLayer = true
|
|
|
- row.layer?.cornerRadius = 10
|
|
|
row.layer?.backgroundColor = (hovering ? self.palette.inputBackground : NSColor.clear).cgColor
|
|
|
}
|
|
|
row.onHoverChanged?(false)
|
|
|
@@ -4401,12 +4448,11 @@ private final class SettingsMenuViewController: NSViewController {
|
|
|
onToggleDarkMode(sender.state == .on)
|
|
|
}
|
|
|
|
|
|
- @objc private func settingsActionClicked(_ sender: NSClickGestureRecognizer) {
|
|
|
- guard let view = sender.view,
|
|
|
- let raw = Int(view.identifier?.rawValue ?? ""),
|
|
|
- let action = SettingsAction(rawValue: raw) else { return }
|
|
|
+ @objc private func settingsActionButtonPressed(_ sender: NSButton) {
|
|
|
+ guard let action = SettingsAction(rawValue: sender.tag) else { return }
|
|
|
onAction(action)
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
|
|
|
private extension ViewController {
|