|
@@ -30,6 +30,8 @@ private enum SettingsAction: Int {
|
|
|
case moreApps = 3
|
|
case moreApps = 3
|
|
|
case shareApp = 4
|
|
case shareApp = 4
|
|
|
case upgrade = 5
|
|
case upgrade = 5
|
|
|
|
|
+ case privacyPolicy = 6
|
|
|
|
|
+ case termsOfServices = 7
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private enum PremiumPlan: Int {
|
|
private enum PremiumPlan: Int {
|
|
@@ -865,10 +867,11 @@ private extension ViewController {
|
|
|
case .rateUs:
|
|
case .rateUs:
|
|
|
openRateUsDestination()
|
|
openRateUsDestination()
|
|
|
case .support:
|
|
case .support:
|
|
|
- if let supportURL = Bundle.main.object(forInfoDictionaryKey: "SupportURL") as? String,
|
|
|
|
|
- let url = URL(string: supportURL) {
|
|
|
|
|
- openInAppBrowser(with: url, policy: inAppBrowserDefaultPolicy)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ openSettingsLink(infoKey: "SupportURL")
|
|
|
|
|
+ case .privacyPolicy:
|
|
|
|
|
+ openSettingsLink(infoKey: "PrivacyPolicyURL")
|
|
|
|
|
+ case .termsOfServices:
|
|
|
|
|
+ openSettingsLink(infoKey: "TermsOfServiceURL")
|
|
|
case .moreApps:
|
|
case .moreApps:
|
|
|
if let moreAppsURL = Bundle.main.object(forInfoDictionaryKey: "MoreAppsURL") as? String,
|
|
if let moreAppsURL = Bundle.main.object(forInfoDictionaryKey: "MoreAppsURL") as? String,
|
|
|
let url = URL(string: moreAppsURL) {
|
|
let url = URL(string: moreAppsURL) {
|
|
@@ -881,6 +884,13 @@ private extension ViewController {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private func openSettingsLink(infoKey: String) {
|
|
|
|
|
+ let defaultURL = (Bundle.main.object(forInfoDictionaryKey: "AppLaunchPlaceholderURL") as? String) ?? "https://example.com/app-link-coming-soon"
|
|
|
|
|
+ let urlString = (Bundle.main.object(forInfoDictionaryKey: infoKey) as? String) ?? defaultURL
|
|
|
|
|
+ guard let url = URL(string: urlString) else { return }
|
|
|
|
|
+ openInAppBrowser(with: url, policy: inAppBrowserDefaultPolicy)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private func showSimpleAlert(title: String, message: String) {
|
|
private func showSimpleAlert(title: String, message: String) {
|
|
|
let alert = NSAlert()
|
|
let alert = NSAlert()
|
|
|
alert.messageText = title
|
|
alert.messageText = title
|
|
@@ -1512,10 +1522,28 @@ private extension ViewController {
|
|
|
let panel = NSView()
|
|
let panel = NSView()
|
|
|
panel.translatesAutoresizingMaskIntoConstraints = false
|
|
panel.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
|
|
|
|
|
|
+ let scroll = NSScrollView()
|
|
|
|
|
+ scroll.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
|
+ scroll.drawsBackground = false
|
|
|
|
|
+ scroll.hasHorizontalScroller = false
|
|
|
|
|
+ scroll.hasVerticalScroller = true
|
|
|
|
|
+ scroll.autohidesScrollers = true
|
|
|
|
|
+ scroll.borderType = .noBorder
|
|
|
|
|
+ scroll.scrollerStyle = .overlay
|
|
|
|
|
+ scroll.automaticallyAdjustsContentInsets = false
|
|
|
|
|
+ let clip = TopAlignedClipView()
|
|
|
|
|
+ clip.drawsBackground = false
|
|
|
|
|
+ scroll.contentView = clip
|
|
|
|
|
+ panel.addSubview(scroll)
|
|
|
|
|
+
|
|
|
|
|
+ let content = NSView()
|
|
|
|
|
+ content.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
|
+ scroll.documentView = content
|
|
|
|
|
+
|
|
|
let card = roundedContainer(cornerRadius: 16, color: palette.sectionCard)
|
|
let card = roundedContainer(cornerRadius: 16, color: palette.sectionCard)
|
|
|
card.translatesAutoresizingMaskIntoConstraints = false
|
|
card.translatesAutoresizingMaskIntoConstraints = false
|
|
|
styleSurface(card, borderColor: palette.inputBorder, borderWidth: 1, shadow: true)
|
|
styleSurface(card, borderColor: palette.inputBorder, borderWidth: 1, shadow: true)
|
|
|
- panel.addSubview(card)
|
|
|
|
|
|
|
+ content.addSubview(card)
|
|
|
|
|
|
|
|
let stack = NSStackView()
|
|
let stack = NSStackView()
|
|
|
stack.translatesAutoresizingMaskIntoConstraints = false
|
|
stack.translatesAutoresizingMaskIntoConstraints = false
|
|
@@ -1552,12 +1580,22 @@ private extension ViewController {
|
|
|
stack.addArrangedSubview(rateButton)
|
|
stack.addArrangedSubview(rateButton)
|
|
|
rateButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
|
|
rateButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
|
|
|
}
|
|
}
|
|
|
- let supportButton = makeSettingsActionButton(icon: "💬", title: "Support", action: .support)
|
|
|
|
|
- stack.addArrangedSubview(supportButton)
|
|
|
|
|
- supportButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
|
|
|
|
|
let shareButton = makeSettingsActionButton(icon: "⤴︎", title: "Share App", action: .shareApp)
|
|
let shareButton = makeSettingsActionButton(icon: "⤴︎", title: "Share App", action: .shareApp)
|
|
|
stack.addArrangedSubview(shareButton)
|
|
stack.addArrangedSubview(shareButton)
|
|
|
shareButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
|
|
shareButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
|
|
|
|
|
+ stack.setCustomSpacing(24, after: shareButton)
|
|
|
|
|
+
|
|
|
|
|
+ let legalTitle = textLabel("Help & Legal", font: typography.joinWithURLTitle, color: palette.textPrimary)
|
|
|
|
|
+ stack.addArrangedSubview(legalTitle)
|
|
|
|
|
+ let privacyButton = makeSettingsActionButton(icon: "🔒", title: "Privacy Policy", action: .privacyPolicy)
|
|
|
|
|
+ stack.addArrangedSubview(privacyButton)
|
|
|
|
|
+ privacyButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
|
|
|
|
|
+ let supportButton = makeSettingsActionButton(icon: "💬", title: "Support", action: .support)
|
|
|
|
|
+ stack.addArrangedSubview(supportButton)
|
|
|
|
|
+ supportButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
|
|
|
|
|
+ let termsButton = makeSettingsActionButton(icon: "📄", title: "Terms of Services", action: .termsOfServices)
|
|
|
|
|
+ stack.addArrangedSubview(termsButton)
|
|
|
|
|
+ termsButton.widthAnchor.constraint(equalTo: stack.widthAnchor).isActive = true
|
|
|
if storeKitCoordinator.hasPremiumAccess && !storeKitCoordinator.hasLifetimeAccess {
|
|
if storeKitCoordinator.hasPremiumAccess && !storeKitCoordinator.hasLifetimeAccess {
|
|
|
let upgradeButton = makeSettingsActionButton(icon: "⬆︎", title: "Upgrade", action: .upgrade)
|
|
let upgradeButton = makeSettingsActionButton(icon: "⬆︎", title: "Upgrade", action: .upgrade)
|
|
|
stack.addArrangedSubview(upgradeButton)
|
|
stack.addArrangedSubview(upgradeButton)
|
|
@@ -1565,13 +1603,24 @@ private extension ViewController {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
NSLayoutConstraint.activate([
|
|
NSLayoutConstraint.activate([
|
|
|
- card.centerXAnchor.constraint(equalTo: panel.centerXAnchor),
|
|
|
|
|
- card.topAnchor.constraint(equalTo: panel.topAnchor, constant: 36),
|
|
|
|
|
- card.bottomAnchor.constraint(lessThanOrEqualTo: panel.bottomAnchor, constant: -36),
|
|
|
|
|
|
|
+ scroll.leadingAnchor.constraint(equalTo: panel.leadingAnchor),
|
|
|
|
|
+ scroll.trailingAnchor.constraint(equalTo: panel.trailingAnchor),
|
|
|
|
|
+ scroll.topAnchor.constraint(equalTo: panel.topAnchor),
|
|
|
|
|
+ scroll.bottomAnchor.constraint(equalTo: panel.bottomAnchor),
|
|
|
|
|
+
|
|
|
|
|
+ content.leadingAnchor.constraint(equalTo: scroll.contentView.leadingAnchor),
|
|
|
|
|
+ content.trailingAnchor.constraint(equalTo: scroll.contentView.trailingAnchor),
|
|
|
|
|
+ content.topAnchor.constraint(equalTo: scroll.contentView.topAnchor),
|
|
|
|
|
+ content.bottomAnchor.constraint(greaterThanOrEqualTo: scroll.contentView.bottomAnchor),
|
|
|
|
|
+ content.widthAnchor.constraint(equalTo: scroll.contentView.widthAnchor),
|
|
|
|
|
+
|
|
|
|
|
+ card.centerXAnchor.constraint(equalTo: content.centerXAnchor),
|
|
|
|
|
+ card.topAnchor.constraint(equalTo: content.topAnchor, constant: 36),
|
|
|
|
|
+ content.bottomAnchor.constraint(greaterThanOrEqualTo: card.bottomAnchor, constant: 36),
|
|
|
card.widthAnchor.constraint(lessThanOrEqualToConstant: 620),
|
|
card.widthAnchor.constraint(lessThanOrEqualToConstant: 620),
|
|
|
card.widthAnchor.constraint(greaterThanOrEqualToConstant: 460),
|
|
card.widthAnchor.constraint(greaterThanOrEqualToConstant: 460),
|
|
|
- card.leadingAnchor.constraint(greaterThanOrEqualTo: panel.leadingAnchor, constant: 30),
|
|
|
|
|
- card.trailingAnchor.constraint(lessThanOrEqualTo: panel.trailingAnchor, constant: -30),
|
|
|
|
|
|
|
+ card.leadingAnchor.constraint(greaterThanOrEqualTo: content.leadingAnchor, constant: 30),
|
|
|
|
|
+ card.trailingAnchor.constraint(lessThanOrEqualTo: content.trailingAnchor, constant: -30),
|
|
|
|
|
|
|
|
stack.leadingAnchor.constraint(equalTo: card.leadingAnchor, constant: 28),
|
|
stack.leadingAnchor.constraint(equalTo: card.leadingAnchor, constant: 28),
|
|
|
stack.trailingAnchor.constraint(equalTo: card.trailingAnchor, constant: -28),
|
|
stack.trailingAnchor.constraint(equalTo: card.trailingAnchor, constant: -28),
|
|
@@ -1684,8 +1733,6 @@ private extension ViewController {
|
|
|
scheduleConnectClicked()
|
|
scheduleConnectClicked()
|
|
|
} else {
|
|
} else {
|
|
|
performGoogleSignOut()
|
|
performGoogleSignOut()
|
|
|
- pageCache[.settings] = nil
|
|
|
|
|
- showSidebarPage(.settings)
|
|
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -4526,7 +4573,9 @@ private final class SettingsMenuViewController: NSViewController {
|
|
|
if showRateUsInSettings {
|
|
if showRateUsInSettings {
|
|
|
stack.addArrangedSubview(settingsActionRow(icon: "★", title: "Rate Us", action: .rateUs))
|
|
stack.addArrangedSubview(settingsActionRow(icon: "★", title: "Rate Us", action: .rateUs))
|
|
|
}
|
|
}
|
|
|
|
|
+ stack.addArrangedSubview(settingsActionRow(icon: "🔒", title: "Privacy Policy", action: .privacyPolicy))
|
|
|
stack.addArrangedSubview(settingsActionRow(icon: "💬", title: "Support", action: .support))
|
|
stack.addArrangedSubview(settingsActionRow(icon: "💬", title: "Support", action: .support))
|
|
|
|
|
+ stack.addArrangedSubview(settingsActionRow(icon: "📄", title: "Terms of Services", action: .termsOfServices))
|
|
|
stack.addArrangedSubview(settingsActionRow(icon: "⤴︎", title: "Share App", action: .shareApp))
|
|
stack.addArrangedSubview(settingsActionRow(icon: "⤴︎", title: "Share App", action: .shareApp))
|
|
|
if showUpgradeInSettings {
|
|
if showUpgradeInSettings {
|
|
|
stack.addArrangedSubview(settingsActionRow(icon: "⬆︎", title: "Upgrade", action: .upgrade))
|
|
stack.addArrangedSubview(settingsActionRow(icon: "⬆︎", title: "Upgrade", action: .upgrade))
|
|
@@ -6252,16 +6301,15 @@ private extension ViewController {
|
|
|
private func performGoogleSignOut() {
|
|
private func performGoogleSignOut() {
|
|
|
do {
|
|
do {
|
|
|
try googleOAuth.signOut()
|
|
try googleOAuth.signOut()
|
|
|
|
|
+ applyGoogleProfile(nil)
|
|
|
|
|
+ updateGoogleAuthButtonTitle()
|
|
|
|
|
+ pageCache[.joinMeetings] = nil
|
|
|
pageCache[.photo] = nil
|
|
pageCache[.photo] = nil
|
|
|
|
|
+ pageCache[.video] = nil
|
|
|
pageCache[.settings] = nil
|
|
pageCache[.settings] = nil
|
|
|
- if selectedSidebarPage == .photo {
|
|
|
|
|
- showSidebarPage(.photo)
|
|
|
|
|
- } else if selectedSidebarPage == .settings {
|
|
|
|
|
- showSidebarPage(.settings)
|
|
|
|
|
- } else {
|
|
|
|
|
- Task { [weak self] in
|
|
|
|
|
- await self?.loadSchedule()
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ showSidebarPage(selectedSidebarPage)
|
|
|
|
|
+ Task { [weak self] in
|
|
|
|
|
+ await self?.loadSchedule()
|
|
|
}
|
|
}
|
|
|
} catch {
|
|
} catch {
|
|
|
showSimpleError("Couldn’t logout Google account.", error: error)
|
|
showSimpleError("Couldn’t logout Google account.", error: error)
|