Link opening improvements

This commit is contained in:
Kylmakalle 2025-03-18 10:52:53 +02:00
parent c58119a137
commit ee138ed453
6 changed files with 97 additions and 33 deletions

View File

@ -159,8 +159,6 @@ public func sgDebugController(context: AccountContext) -> ViewController {
} }
#endif #endif
case .restorePurchases: case .restorePurchases:
context.sharedContext.SGIAP?.restorePurchases {
DispatchQueue.main.async {
presentControllerImpl?(UndoOverlayController( presentControllerImpl?(UndoOverlayController(
presentationData: presentationData, presentationData: presentationData,
content: .info(title: nil, text: "PayWall.Button.Restoring".i18n(args: context.sharedContext.currentPresentationData.with { $0 }.strings.baseLanguageCode), timeout: nil, customUndoText: nil), content: .info(title: nil, text: "PayWall.Button.Restoring".i18n(args: context.sharedContext.currentPresentationData.with { $0 }.strings.baseLanguageCode), timeout: nil, customUndoText: nil),
@ -168,8 +166,7 @@ public func sgDebugController(context: AccountContext) -> ViewController {
action: { _ in return false } action: { _ in return false }
), ),
nil) nil)
} context.sharedContext.SGIAP?.restorePurchases {}
}
case .setIAP: case .setIAP:
#if DEBUG #if DEBUG
#endif #endif

View File

@ -13,7 +13,7 @@ import TelegramUIPreferences
@available(iOS 13.0, *) @available(iOS 13.0, *)
public func sgPayWallController(statusSignal: Signal<Int64, NoError>, replacementController: ViewController, presentationData: PresentationData? = nil, SGIAPManager: SGIAPManager, openUrl: @escaping (String) -> Void, paymentsEnabled: Bool, canBuyInBeta: Bool, openAppStorePage: @escaping () -> Void) -> ViewController { public func sgPayWallController(statusSignal: Signal<Int64, NoError>, replacementController: ViewController, presentationData: PresentationData? = nil, SGIAPManager: SGIAPManager, openUrl: @escaping (String, Bool) -> Void /* url, forceExternal */, paymentsEnabled: Bool, canBuyInBeta: Bool, openAppStorePage: @escaping () -> Void, proSupportUrl: String?) -> ViewController {
// let theme = presentationData?.theme ?? (UITraitCollection.current.userInterfaceStyle == .dark ? defaultDarkColorPresentationTheme : defaultPresentationTheme) // let theme = presentationData?.theme ?? (UITraitCollection.current.userInterfaceStyle == .dark ? defaultDarkColorPresentationTheme : defaultPresentationTheme)
let theme = defaultDarkColorPresentationTheme let theme = defaultDarkColorPresentationTheme
let strings = presentationData?.strings ?? defaultPresentationStrings let strings = presentationData?.strings ?? defaultPresentationStrings
@ -31,7 +31,7 @@ public func sgPayWallController(statusSignal: Signal<Int64, NoError>, replacemen
let swiftUIView = SGSwiftUIView<SGPayWallView>( let swiftUIView = SGSwiftUIView<SGPayWallView>(
legacyController: legacyController, legacyController: legacyController,
content: { content: {
SGPayWallView(wrapperController: legacyController, replacementController: replacementController, SGIAP: SGIAPManager, statusSignal: statusSignal, openUrl: openUrl, openAppStorePage: openAppStorePage, paymentsEnabled: paymentsEnabled, canBuyInBeta: canBuyInBeta) SGPayWallView(wrapperController: legacyController, replacementController: replacementController, SGIAP: SGIAPManager, statusSignal: statusSignal, openUrl: openUrl, openAppStorePage: openAppStorePage, paymentsEnabled: paymentsEnabled, canBuyInBeta: canBuyInBeta, proSupportUrl: proSupportUrl)
} }
) )
let controller = UIHostingController(rootView: swiftUIView, ignoreSafeArea: true) let controller = UIHostingController(rootView: swiftUIView, ignoreSafeArea: true)
@ -101,7 +101,7 @@ struct SGPayWallFeatureDetails: View {
let dismissAction: () -> Void let dismissAction: () -> Void
var bottomOffset: CGFloat = 0.0 var bottomOffset: CGFloat = 0.0
let contentHeight: CGFloat = 666.0 // heh let contentHeight: CGFloat = 690.0
let features: [SGProFeature] let features: [SGProFeature]
@State var shownFeature: SGProFeatureId? @State var shownFeature: SGProFeatureId?
@ -326,10 +326,11 @@ struct SGPayWallView: View {
let replacementController: ViewController let replacementController: ViewController
let SGIAP: SGIAPManager let SGIAP: SGIAPManager
let statusSignal: Signal<Int64, NoError> let statusSignal: Signal<Int64, NoError>
let openUrl: (String) -> Void let openUrl: (String, Bool) -> Void // url, forceExternal
let openAppStorePage: () -> Void let openAppStorePage: () -> Void
let paymentsEnabled: Bool let paymentsEnabled: Bool
let canBuyInBeta: Bool let canBuyInBeta: Bool
let proSupportUrl: String?
private enum PayWallState: Equatable { private enum PayWallState: Equatable {
case ready // ready to buy case ready // ready to buy
@ -519,7 +520,7 @@ struct SGPayWallView: View {
private var purchaseSection: some View { private var purchaseSection: some View {
VStack(spacing: 0) { VStack(spacing: 0) {
Divider() Divider()
VStack(spacing: 8) {
Button(action: handlePurchase) { Button(action: handlePurchase) {
Text(buttonTitle) Text(buttonTitle)
.fontWeight(.semibold) .fontWeight(.semibold)
@ -531,8 +532,24 @@ struct SGPayWallView: View {
} }
.disabled((state != .ready || !canPurchase) && !(currentStatus > 1)) .disabled((state != .ready || !canPurchase) && !(currentStatus > 1))
.opacity(((state != .ready || !canPurchase) && !(currentStatus > 1)) ? 0.5 : 1.0) .opacity(((state != .ready || !canPurchase) && !(currentStatus > 1)) ? 0.5 : 1.0)
if let proSupportUrl = proSupportUrl {
HStack(alignment: .center, spacing: 4) {
Text("PayWall.ProSupport.Title".i18n(lang))
.font(.caption)
.foregroundColor(.secondary)
Button(action: {
openUrl(proSupportUrl, false)
}) {
Text("PayWall.ProSupport.Contact".i18n(lang))
.font(.caption)
.foregroundColor(Color(hex: accentColorHex))
}
}
}
}
.padding([.horizontal, .top]) .padding([.horizontal, .top])
.padding(.bottom, sgBottomSafeAreaInset(containerViewLayout)) .padding(.bottom, sgBottomSafeAreaInset(containerViewLayout) + 2.0)
} }
.foregroundColor(Color.black) .foregroundColor(Color.black)
.backgroundIfAvailable(material: .ultraThinMaterial) .backgroundIfAvailable(material: .ultraThinMaterial)
@ -547,7 +564,7 @@ struct SGPayWallView: View {
.tint(Color(hex: accentColorHex)) .tint(Color(hex: accentColorHex))
.foregroundColor(.secondary) .foregroundColor(.secondary)
.environment(\.openURL, OpenURLAction { url in .environment(\.openURL, OpenURLAction { url in
openUrl(url.absoluteString) openUrl(url.absoluteString, false)
return .handled return .handled
}) })
} else { } else {
@ -556,14 +573,14 @@ struct SGPayWallView: View {
.foregroundColor(.secondary) .foregroundColor(.secondary)
HStack(alignment: .top, spacing: 8) { HStack(alignment: .top, spacing: 8) {
Button(action: { Button(action: {
openUrl("PayWall.PrivacyURL".i18n(lang)) openUrl("PayWall.PrivacyURL".i18n(lang), true)
}) { }) {
Text("PayWall.Privacy".i18n(lang)) Text("PayWall.Privacy".i18n(lang))
.font(.caption) .font(.caption)
.foregroundColor(Color(hex: accentColorHex)) .foregroundColor(Color(hex: accentColorHex))
} }
Button(action: { Button(action: {
openUrl("PayWall.TermsURL".i18n(lang)) openUrl("PayWall.TermsURL".i18n(lang), true)
}) { }) {
Text("PayWall.Terms".i18n(lang)) Text("PayWall.Terms".i18n(lang))
.font(.caption) .font(.caption)
@ -592,7 +609,7 @@ struct SGPayWallView: View {
} }
HStack { HStack {
Button(action: { Button(action: {
openUrl("PayWall.About.SignatureURL".i18n(lang)) openUrl("PayWall.About.SignatureURL".i18n(lang), false)
}) { }) {
Text("PayWall.About.Signature".i18n(lang)) Text("PayWall.About.Signature".i18n(lang))
.font(.caption) .font(.caption)

View File

@ -214,10 +214,14 @@
"PayWall.About.Title" = "About Swiftgram Pro"; "PayWall.About.Title" = "About Swiftgram Pro";
"PayWall.About.Notice" = "Free version of Swiftgram provides dozens of features and improvements over Telegram app. Innovating and keeping Swiftgram in sync with monthly Telegram updates is a huge effort that requires a lot of time and expensive hardware.\n\nSwiftgram is an open-source app that respects your privacy and doesn't bother you with ads. Subscribing to Swiftgram Pro you get access to exclusive features and support an independent developer."; "PayWall.About.Notice" = "Free version of Swiftgram provides dozens of features and improvements over Telegram app. Innovating and keeping Swiftgram in sync with monthly Telegram updates is a huge effort that requires a lot of time and expensive hardware.\n\nSwiftgram is an open-source app that respects your privacy and doesn't bother you with ads. Subscribing to Swiftgram Pro you get access to exclusive features and support an independent developer.";
/* DO NOT TRANSLATE */
"PayWall.About.Signature" = "@Kylmakalle"; "PayWall.About.Signature" = "@Kylmakalle";
/* DO NOT TRANSLATE */ /* DO NOT TRANSLATE */
"PayWall.About.SignatureURL" = "https://t.me/Kylmakalle"; "PayWall.About.SignatureURL" = "https://t.me/Kylmakalle";
"PayWall.ProSupport.Title" = "Troubles with payment?";
"PayWall.ProSupport.Contact" = "No worries!";
"PayWall.RestorePurchases" = "Restore Purchases"; "PayWall.RestorePurchases" = "Restore Purchases";
"PayWall.Terms" = "Terms of Service"; "PayWall.Terms" = "Terms of Service";
"PayWall.Privacy" = "Privacy Policy"; "PayWall.Privacy" = "Privacy Policy";

View File

@ -5,7 +5,7 @@ public struct SGWebSettings: Codable, Equatable {
public let user: SGUserSettings public let user: SGUserSettings
public static var defaultValue: SGWebSettings { public static var defaultValue: SGWebSettings {
return SGWebSettings(global: SGGlobalSettings(ytPip: true, qrLogin: true, storiesAvailable: false, canViewMessages: true, canEditSettings: false, canShowTelescope: false, announcementsData: nil, regdateFormat: "month", botMonkeys: [], forceReasons: [], unforceReasons: [], paymentsEnabled: true, duckyAppIconAvailable: true, canGrant: false), user: SGUserSettings(contentReasons: [], canSendTelescope: false, canBuyInBeta: true)) return SGWebSettings(global: SGGlobalSettings(ytPip: true, qrLogin: true, storiesAvailable: false, canViewMessages: true, canEditSettings: false, canShowTelescope: false, announcementsData: nil, regdateFormat: "month", botMonkeys: [], forceReasons: [], unforceReasons: [], paymentsEnabled: true, duckyAppIconAvailable: true, canGrant: false, proSupportUrl: nil), user: SGUserSettings(contentReasons: [], canSendTelescope: false, canBuyInBeta: true))
} }
} }
@ -24,6 +24,7 @@ public struct SGGlobalSettings: Codable, Equatable {
public let paymentsEnabled: Bool public let paymentsEnabled: Bool
public let duckyAppIconAvailable: Bool public let duckyAppIconAvailable: Bool
public let canGrant: Bool public let canGrant: Bool
public let proSupportUrl: String?
} }
public struct SGBotMonkeys: Codable, Equatable { public struct SGBotMonkeys: Codable, Equatable {

View File

@ -4,6 +4,8 @@ import SGConfig
import SGSettingsUI import SGSettingsUI
import SGDebugUI import SGDebugUI
import SFSafariViewControllerPlus import SFSafariViewControllerPlus
import UndoUI
//
import ContactListUI import ContactListUI
import Foundation import Foundation
import Display import Display
@ -1041,6 +1043,33 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur
} }
} }
} }
case "restart":
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let lang = presentationData.strings.baseLanguageCode
context.sharedContext.presentGlobalController(
UndoOverlayController(
presentationData: presentationData,
content: .info(title: nil,
text: "Common.RestartRequired".i18n(lang),
timeout: nil,
customUndoText: "Common.RestartNow".i18n(lang)
),
elevatedLayout: false,
action: { action in if action == .undo { exit(0) }; return true }
),
nil
)
case "restore_purchases", "pro_restore", "validate", "restore":
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let lang = presentationData.strings.baseLanguageCode
context.sharedContext.presentGlobalController(UndoOverlayController(
presentationData: presentationData,
content: .info(title: nil, text: "PayWall.Button.Restoring".i18n(lang), timeout: nil, customUndoText: nil),
elevatedLayout: false,
action: { _ in return false }
),
nil)
context.sharedContext.SGIAP?.restorePurchases {}
default: default:
break break
} }

View File

@ -3625,7 +3625,23 @@ extension SharedAccountContextImpl {
let proController = self.makeSGProController(context: context) let proController = self.makeSGProController(context: context)
let sgWebSettings = context.currentAppConfiguration.with { $0 }.sgWebSettings let sgWebSettings = context.currentAppConfiguration.with { $0 }.sgWebSettings
let payWallController = sgPayWallController(statusSignal: statusSignal, replacementController: proController, presentationData: self.currentPresentationData.with { $0 }, SGIAPManager: sgIAP, openUrl: self.applicationBindings.openUrl, paymentsEnabled: sgWebSettings.global.paymentsEnabled, canBuyInBeta: sgWebSettings.user.canBuyInBeta, openAppStorePage: self.applicationBindings.openAppStorePage) let presentationData = self.currentPresentationData.with { $0 }
var payWallController: ViewController? = nil
let openUrl: ((String, Bool) -> Void) = { [weak self, weak context] url, forceExternal in
guard let strongSelf = self, let strongContext = context, let strongPayWallController = payWallController else {
return
}
let navigationController = strongPayWallController.navigationController as? NavigationController
Queue.mainQueue().async {
strongSelf.openExternalUrl(context: strongContext, urlContext: .generic, url: url, forceExternal: forceExternal, presentationData: presentationData, navigationController: navigationController, dismissInput: {})
}
}
var supportUrl: String? = nil
if let supportUrlString = sgWebSettings.global.proSupportUrl, !supportUrlString.isEmpty, let data = Data(base64Encoded: supportUrlString), let decodedString = String(data: data, encoding: .utf8) {
supportUrl = decodedString
}
payWallController = sgPayWallController(statusSignal: statusSignal, replacementController: proController, presentationData: presentationData, SGIAPManager: sgIAP, openUrl: openUrl, paymentsEnabled: sgWebSettings.global.paymentsEnabled, canBuyInBeta: sgWebSettings.user.canBuyInBeta, openAppStorePage: self.applicationBindings.openAppStorePage, proSupportUrl: supportUrl)
return payWallController return payWallController
} }