Skip to content

Commit

Permalink
Add trial notification for store kit
Browse files Browse the repository at this point in the history
  • Loading branch information
aromanov91 committed Jul 3, 2023
1 parent 51a54ad commit 449fd85
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 45 deletions.
17 changes: 14 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ let productionDependencies: [PackageDescription.Package.Dependency] = { [
.package(url: "https://github.com/oversizedev/OversizeComponents.git", .upToNextMajor(from: "1.2.0")),
.package(url: "https://github.com/oversizedev/OversizeResources.git", .upToNextMajor(from: "1.3.0")),
.package(url: "https://github.com/hmlongco/Factory.git", .upToNextMajor(from: "2.1.3")),
.package(url: "https://github.com/oversizedev/OversizeNetwork.git", .upToNextMajor(from: "0.1.0"))
// .package(name: "OversizeNetwork", path: "../OversizeNetwork"),
// .package(url: "https://github.com/apple/swift-openapi-runtime", .upToNextMinor(from: "0.1.0")),
// .package(url: "https://github.com/apple/swift-openapi-urlsession", .upToNextMinor(from: "0.1.0")),
// .package(url: "https://github.com/oversizedev/OversizeNetwork.git", .upToNextMajor(from: "0.1.0"))
] }()

let developmentDependencies: [PackageDescription.Package.Dependency] = { [
Expand All @@ -22,7 +25,9 @@ let developmentDependencies: [PackageDescription.Package.Dependency] = { [
.package(name: "OversizeComponents", path: "../OversizeComponents"),
.package(name: "OversizeResources", path: "../OversizeResources"),
.package(name: "OversizeNetwork", path: "../OversizeNetwork"),
.package(url: "https://github.com/hmlongco/Factory.git", .upToNextMajor(from: "2.1.3")),
// .package(url: "https://github.com/hmlongco/Factory.git", .upToNextMajor(from: "2.1.3")),
// .package(url: "https://github.com/apple/swift-openapi-runtime", .upToNextMinor(from: "0.1.0")),
// .package(url: "https://github.com/apple/swift-openapi-urlsession", .upToNextMinor(from: "0.1.0")),
] }()

let package = Package(
Expand Down Expand Up @@ -56,6 +61,7 @@ let package = Package(
.product(name: "OversizeComponents", package: "OversizeComponents"),
.product(name: "OversizeLocalizable", package: "OversizeLocalizable"),
.product(name: "OversizeResources", package: "OversizeResources"),
.product(name: "OversizeNotificationService", package: "OversizeServices"),
.product(name: "Factory", package: "Factory"),
]
),
Expand All @@ -66,7 +72,12 @@ let package = Package(
.product(name: "Factory", package: "Factory"),
.product(name: "OversizeUI", package: "OversizeUI"),
.product(name: "OversizeServices", package: "OversizeServices"),
.product(name: "OversizeNetwork", package: "OversizeNetwork"),
// .product(name: "OversizeNetwork", package: "OversizeNetwork"),
// .product(name: "OpenAPIRuntime", package: "swift-openapi-runtime"),
// .product(
// name: "OpenAPIURLSession",
// package: "swift-openapi-urlsession"
// ),
]
),
.target(
Expand Down
5 changes: 2 additions & 3 deletions Sources/OversizeAdsKit/AdView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ import OversizeUI
import SwiftUI

public struct AdView: View {

@Environment(\.isPremium) var isPremium: Bool

@StateObject var viewModel: AdViewModel

@State var isShowProduct = false
Expand Down Expand Up @@ -79,7 +78,7 @@ public struct AdView: View {
}
}
.surfaceContentInsets(.xSmall)
//.appStoreOverlay(isPresent: $isShowProduct, appId: String(viewModel.appAd?.id ?? 0))
.appStoreOverlay(isPresent: $isShowProduct, appId: viewModel.appAd?.id ?? "")
#else
EmptyView()
#endif
Expand Down
34 changes: 17 additions & 17 deletions Sources/OversizeAdsKit/AdViewModel.swift
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
//
// Copyright © 2023 Alexander Romanov
// AdViewModel.swift, created on 30.06.2023
//
//

import SwiftUI
import OversizeNetwork
import Factory
import OversizeServices
import SwiftUI
// import OversizeNetwork
// import Factory

@MainActor
public class AdViewModel: ObservableObject {
@Injected(\.networkService) var networkService
@Published var appAd = Info.all?.apps.filter { $0.id != Info.app.appStoreID }.randomElement()
/*
@Injected(\.networkService) var networkService

@Published var appAd: Components.Schemas.AdBanner?

public func fetchAdBanners() async {
let status = await networkService.fetchAdsBanners()
switch status {
case .success(let banners):
appAd = banners.filter { $0.id != Int(Info.app.appStoreID ?? "") }.randomElement()
case .failure:
break
}
}

public func fetchAdBanners() async {
let status = await networkService.fetchAdsBanners()
switch status {
case .success(let banners):
appAd = banners.filter { $0.id != Int(Info.app.appStoreID ?? "") }.randomElement()
case .failure:
break
}
}
*/
}
2 changes: 1 addition & 1 deletion Sources/OversizeKit/LauncherKit/LauncherViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public extension LauncherViewModel {
}

if let subscriptionStatus = status.1 {
if #available(iOS 15.4, *) {
if #available(iOS 15.4, macOS 12.3, *) {
log("📝 Subscription: \(subscriptionStatus.localizedDescription)")
}
subscriptionsState = subscriptionStatus
Expand Down
26 changes: 16 additions & 10 deletions Sources/OversizeKit/LockscreenKit/LockscreenView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ public enum LockscreenViewState {
}

public struct LockscreenView: View {
@Environment(\.verticalSizeClass) var verticalSizeClass: UserInterfaceSizeClass?
@Environment(\.horizontalSizeClass) var horizontalSizeClass: UserInterfaceSizeClass?
#if os(iOS)
@Environment(\.verticalSizeClass) var verticalSizeClass: UserInterfaceSizeClass?
@Environment(\.horizontalSizeClass) var horizontalSizeClass: UserInterfaceSizeClass?
#endif
@Environment(\.scenePhase) var scenePhase: ScenePhase

@Binding private var pinCode: String
Expand Down Expand Up @@ -44,15 +46,19 @@ public struct LockscreenView: View {
private let biometricType: BiometricType

private var isShowTitle: Bool {
if horizontalSizeClass == .compact, verticalSizeClass == .regular {
return true
} else if horizontalSizeClass == .regular, verticalSizeClass == .compact {
return false
} else if horizontalSizeClass == .regular, verticalSizeClass == .regular {
return true
} else {
#if os(iOS)
if horizontalSizeClass == .compact, verticalSizeClass == .regular {
return true
} else if horizontalSizeClass == .regular, verticalSizeClass == .compact {
return false
} else if horizontalSizeClass == .regular, verticalSizeClass == .regular {
return true
} else {
return true
}
#else
return true
}
#endif
}

public init(pinCode: Binding<String>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public struct StoreInstuctinsView: View {
}
.bottomToolbar(style: .none) {
VStack(spacing: .zero) {
StorePaymentButtonBar {
StorePaymentButtonBar(trialNotification: true) {
isShowAllPlans = true
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
withAnimation {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import Factory
import OversizeCore
import OversizeLocalizable
import OversizeNotificationService
import OversizeServices
import OversizeStoreService
import StoreKit
Expand All @@ -21,6 +22,8 @@ class StoreViewModel: ObservableObject {
}

@Injected(\.storeKitService) var storeKitService: StoreKitService
@Injected(\.localNotificationService) var localNotificationService: LocalNotificationServiceProtocol

@Published var state = State.initial

public var updateListenerTask: Task<Void, Error>?
Expand Down Expand Up @@ -68,31 +71,31 @@ extension StoreViewModel {
case .subscribed:
return L10n.Store.active
case .revoked:
if #available(iOS 15.4, *) {
if #available(iOS 15.4, macOS 12.3, *) {
return subscriptionStatus.localizedDescription
} else {
return "Revoked"
}
case .expired:
if #available(iOS 15.4, *) {
if #available(iOS 15.4, macOS 12.3, *) {
return subscriptionStatus.localizedDescription
} else {
return "Expired"
}
case .inBillingRetryPeriod:
if #available(iOS 15.4, *) {
if #available(iOS 15.4, macOS 12.3, *) {
return subscriptionStatus.localizedDescription
} else {
return "Billing retry"
}
case .inGracePeriod:
if #available(iOS 15.4, *) {
if #available(iOS 15.4, macOS 12.3, *) {
return subscriptionStatus.localizedDescription
} else {
return "Grace period"
}
default:
if #available(iOS 15.4, *) {
if #available(iOS 15.4, macOS 12.3, *) {
return subscriptionStatus.localizedDescription
} else {
return ""
Expand Down Expand Up @@ -273,7 +276,7 @@ extension StoreViewModel {
}
}

func buy(product: Product) async -> Bool {
func buy(product: Product, trialNotification: Bool = false) async -> Bool {
isBuyLoading = true
do {
let result = try await storeKitService.purchase(product)
Expand All @@ -282,6 +285,21 @@ extension StoreViewModel {
isPremium = true
isPremiumActivated = true
isBuyLoading = false
if trialNotification, product.type == .autoRenewable, product.subscription?.introductoryOffer != nil {
let result = await localNotificationService.requestAccess()
if case let .success(status) = result, status, let trialDaysCount = product.trialDaysCount {
let timeInterval = TimeInterval((trialDaysCount - 2) * 24 * 60 * 60)
let notificationTime = Date().addingTimeInterval(timeInterval)
let dateComponents = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute], from: notificationTime)
await localNotificationService.schedule(localNotification: .init(
id: UUID(),
title: "Trial ends soon",
body: "Subscription ends in 2 days",
dateComponents: dateComponents,
repeats: false
))
}
}
return true
case .failure:
isBuyLoading = false
Expand Down
4 changes: 2 additions & 2 deletions Sources/OversizeKit/StoreKit/Views/PrmiumBannerRow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public struct PrmiumBannerRow: View {
#endif

#if os(macOS)
Image(nsImage: Illustrations.Images.zap.image)
Resource.Store.zap
.padding(.horizontal, Space.xxSmall)
.padding(.vertical, Space.xxSmall)
#endif
Expand Down Expand Up @@ -107,7 +107,7 @@ public extension PrmiumBannerRow {
#endif

#if os(macOS)
Image(nsImage: OversizeCraft.Illustrations.Images.zap.image)
Resource.Store.zap
#endif

Text(Info.store.subscriptionsName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ struct StorePaymentButtonBar: View {
@EnvironmentObject var viewModel: StoreViewModel

let action: (() -> Void)?
let trialNotification: Bool

init(action: (() -> Void)? = nil) {
init(trialNotification: Bool = false, action: (() -> Void)? = nil) {
self.trialNotification = trialNotification
self.action = action
}

Expand All @@ -24,7 +26,7 @@ struct StorePaymentButtonBar: View {
Button {
if let selectedProduct = viewModel.selectedProduct {
Task {
await viewModel.buy(product: selectedProduct)
await viewModel.buy(product: selectedProduct, trialNotification: trialNotification)
}
}
} label: {
Expand Down

0 comments on commit 449fd85

Please sign in to comment.