Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
1
1weather
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Dmitriy Stepanets
1weather
Commits
cfd25127
Commit
cfd25127
authored
Sep 16, 2021
by
Dmitry Stepanets
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
- Added in-app checked
- Updated UI
parent
f1cc460a
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
429 additions
and
46 deletions
+429
-46
1Weather/AppDelegate.swift
+2
-1
1Weather/InApps/Configuration.storekit
+15
-1
1Weather/InApps/StoreManager.swift
+50
-5
1Weather/Resources/Assets.xcassets/menu/menu_restore.imageset/Contents.json
+16
-0
1Weather/Resources/Assets.xcassets/menu/menu_restore.imageset/menu_restore.pdf
+283
-0
1Weather/Resources/en.lproj/Localizable.strings
+1
-0
1Weather/UI/View controllers/Menu/Cells/MenuCellFactory.swift
+20
-7
1Weather/UI/View controllers/Menu/Header/MenuHeaderView.swift
+32
-29
1Weather/UI/View controllers/Menu/MenuViewController.swift
+4
-0
1Weather/UI/View controllers/Subscriptions/SubscriptionOverviewViewController.swift
+1
-1
1Weather/ViewModels/MenuViewModel.swift
+4
-0
1Weather/ViewModels/SubscriptionViewModel.swift
+1
-2
No files found.
1Weather/AppDelegate.swift
View file @
cfd25127
...
...
@@ -164,7 +164,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func
applicationDidBecomeActive
(
_
application
:
UIApplication
)
{
LocationManager
.
shared
.
updateEverythingIfNeeded
()
storeManager
.
verifySubscriptions
()
storeManager
.
verifyPurchases
()
if
#available(iOS 14, *)
{
WidgetManager
.
shared
.
refreshAnalytics
()
...
...
1Weather/InApps/Configuration.storekit
View file @
cfd25127
...
...
@@ -4,7 +4,21 @@
],
"products" : [
{
"displayPrice" : "1.99",
"familyShareable" : false,
"internalID" : "22A7BDE0",
"localizations" : [
{
"description" : "",
"displayName" : "Upgrade to 1Weather Pro",
"locale" : "en_US"
}
],
"productID" : "com.onelouder.oneweather.inapp1",
"referenceName" : "1Weather Pro ",
"type" : "NonConsumable"
}
],
"settings" : {
"_timeRate" : 6
...
...
1Weather/InApps/StoreManager.swift
View file @
cfd25127
...
...
@@ -91,7 +91,7 @@ public class StoreManager {
self
.
checkSubscriptionExpirationLocally
()
self
.
completeTransactions
()
self
.
updateProductInfo
()
self
.
verify
Subscription
s
()
self
.
verify
Purchase
s
()
#warning("Not implemented!")
//TODO: implement
...
...
@@ -187,9 +187,44 @@ public class StoreManager {
}
}
public
func
verifySubscriptions
()
{
public
func
purchaseInApp
()
{
let
log
=
self
.
log
log
.
info
(
"Verify subscriptions..."
)
log
.
info
(
"Purchase In-app start"
)
SwiftyStoreKit
.
purchaseProduct
(
kInAppOneWeatherProId
,
atomically
:
true
)
{
result
in
switch
result
{
case
.
success
(
let
product
):
if
product
.
needsFinishTransaction
{
SwiftyStoreKit
.
finishTransaction
(
product
.
transaction
)
}
log
.
info
(
"In app bought"
)
self
.
removeAdsPurchased
=
true
case
.
error
(
error
:
let
error
):
log
.
error
(
"Purchase in-app: error for
\(
kInAppOneWeatherProId
)
:
\(
error
)
"
)
}
}
}
public
func
restoreInApp
()
{
SwiftyStoreKit
.
restorePurchases
(
atomically
:
true
)
{[
weak
self
]
results
in
if
results
.
restoreFailedPurchases
.
count
>
0
{
self
?
.
log
.
error
(
"Restore Failed:
\(
results
.
restoreFailedPurchases
)
"
)
}
else
if
results
.
restoredPurchases
.
count
>
0
{
let
ids
=
results
.
restoredPurchases
.
compactMap
{
$0
.
productId
}
if
(
ids
.
contains
{
$0
==
kInAppOneWeatherProId
})
{
self
?
.
log
.
info
(
"Restore Success:
\(
results
.
restoredPurchases
)
"
)
self
?
.
removeAdsPurchased
=
true
}
}
else
{
self
?
.
log
.
info
(
"Nothing to Restore"
)
}
}
}
public
func
verifyPurchases
()
{
let
log
=
self
.
log
log
.
info
(
"Verify purchases..."
)
let
service
:
AppleReceiptValidator
.
VerifyReceiptURLType
#if DEBUG
service
=
.
sandbox
...
...
@@ -201,6 +236,16 @@ public class StoreManager {
SwiftyStoreKit
.
verifyReceipt
(
using
:
appleValidator
)
{
result
in
switch
result
{
case
.
success
(
let
receipt
):
//In-app
let
purchaseInAppResult
=
SwiftyStoreKit
.
verifyPurchase
(
productId
:
kInAppOneWeatherProId
,
inReceipt
:
receipt
)
switch
purchaseInAppResult
{
case
.
purchased
:
self
.
removeAdsPurchased
=
true
case
.
notPurchased
:
self
.
removeAdsPurchased
=
false
}
//Subscriptions
let
purchaseResult
=
SwiftyStoreKit
.
verifySubscriptions
(
ofType
:
.
autoRenewable
,
productIds
:
self
.
allSubscriptionIds
,
inReceipt
:
receipt
)
switch
purchaseResult
{
case
.
purchased
(
let
expiryDate
,
let
items
):
...
...
@@ -223,11 +268,11 @@ public class StoreManager {
log
.
error
(
"Receipt verification failed:
\(
error
)
"
)
self
.
hasSubscription
=
false
self
.
everHadSubscription
=
false
self
.
removeAdsPurchased
=
false
self
.
subscriptionExpirationDate
=
nil
}
}
}
//MARK: - Observers management
public
func
add
(
observer
:
StoreManagerObserver
)
{
...
...
@@ -264,6 +309,6 @@ public class StoreManager {
extension
StoreManager
:
ConfigManagerDelegate
{
public
func
dataUpdated
(
by
configManager
:
ConfigManager
)
{
self
.
updateProductInfo
()
self
.
verify
Subscription
s
()
self
.
verify
Purchase
s
()
}
}
1Weather/Resources/Assets.xcassets/menu/menu_restore.imageset/Contents.json
0 → 100644
View file @
cfd25127
{
"images"
:
[
{
"filename"
:
"menu_restore.pdf"
,
"idiom"
:
"universal"
}
],
"info"
:
{
"author"
:
"xcode"
,
"version"
:
1
},
"properties"
:
{
"preserves-vector-representation"
:
true
,
"template-rendering-intent"
:
"template"
}
}
1Weather/Resources/Assets.xcassets/menu/menu_restore.imageset/menu_restore.pdf
0 → 100644
View file @
cfd25127
No preview for this file type
1Weather/Resources/en.lproj/Localizable.strings
View file @
cfd25127
...
...
@@ -202,6 +202,7 @@
"menu.upgradeNow" = "Upgrade now";
"menu.settings" = "Settings";
"menu.subscriptionOverview" = "Premium";
"menu.restorePurchases" = "Restore purchases";
"menu.about" = "About us";
"menu.ad" = "Ad choices";
"menu.rateUs" = "Rate us";
...
...
1Weather/UI/View controllers/Menu/Cells/MenuCellFactory.swift
View file @
cfd25127
...
...
@@ -10,6 +10,7 @@ import UIKit
public
enum
MenuRow
{
case
settings
case
subscriptionOverview
case
restorePurchases
case
about
case
ad
case
rateUs
...
...
@@ -38,6 +39,8 @@ public enum MenuRow {
return
UIImage
(
named
:
"menu_device_id"
)
case
.
subscriptionOverview
:
return
UIImage
(
named
:
"menu_crown"
)
case
.
restorePurchases
:
return
UIImage
(
named
:
"menu_restore"
)
}
}
...
...
@@ -61,22 +64,26 @@ public enum MenuRow {
return
"menu.deviceId"
.
localized
()
case
.
subscriptionOverview
:
return
"menu.subscriptionOverview"
.
localized
()
case
.
restorePurchases
:
return
"menu.restorePurchases"
.
localized
()
}
}
var
roundedCorners
:
CACornerMask
{
switch
self
{
case
.
settings
:
if
StoreManager
.
shared
.
hasSubscription
{
return
[
.
layerMinXMinYCorner
,
.
layerMaxXMinYCorner
]
if
!
StoreManager
.
shared
.
hasSubscription
&&
StoreManager
.
shared
.
removeAdsPurchased
{
return
[
.
layerMinXMinYCorner
,
.
layerMaxXMinYCorner
,
.
layerMinXMaxYCorner
,
.
layerMaxXMaxYCorner
]
}
else
{
return
[
.
layerMinXMinYCorner
,
.
layerMaxXMinYCorner
,
.
layerMinXMaxYCorner
,
.
layerMaxXMaxYCorner
]
return
[
.
layerMinXMinYCorner
,
.
layerMaxXMinYCorner
]
}
case
.
about
:
return
[
.
layerMinXM
inYCorner
,
.
layerMaxXMin
YCorner
]
case
.
restorePurchases
:
return
[
.
layerMinXM
axYCorner
,
.
layerMaxXMax
YCorner
]
case
.
subscriptionOverview
:
return
[
.
layerMinXMaxYCorner
,
.
layerMaxXMaxYCorner
]
case
.
about
:
return
[
.
layerMinXMinYCorner
,
.
layerMaxXMinYCorner
]
case
.
ad
:
return
[]
case
.
rateUs
:
...
...
@@ -131,8 +138,14 @@ class MenuCellFactory<T>: CellFactory {
rows
:
[
.
settings
,
.
subscriptionOverview
])
}
else
{
infoSectionItem
=
SectionItem
(
type
:
.
info
,
rows
:
[
.
settings
])
if
StoreManager
.
shared
.
removeAdsPurchased
{
infoSectionItem
=
SectionItem
(
type
:
.
info
,
rows
:
[
.
settings
])
}
else
{
infoSectionItem
=
SectionItem
(
type
:
.
info
,
rows
:
[
.
settings
,
.
restorePurchases
])
}
}
let
settingsSectionItem
=
SectionItem
(
type
:
.
settings
,
...
...
1Weather/UI/View controllers/Menu/Header/MenuHeaderView.swift
View file @
cfd25127
...
...
@@ -23,6 +23,7 @@ class MenuHeaderView: UIView {
prepareView
()
preparePremium
()
updateUI
()
reload
()
}
required
init
?(
coder
:
NSCoder
)
{
...
...
@@ -34,6 +35,37 @@ class MenuHeaderView: UIView {
updateUI
()
}
public
func
reload
()
{
if
StoreManager
.
shared
.
removeAdsPurchased
{
premiumHeadingLabel
.
font
=
AppFont
.
SFPro
.
regular
(
size
:
16
)
premiumHeadingLabel
.
text
=
"menu.upgradeTo"
.
localized
()
let
descParagpraphStyle
=
NSMutableParagraphStyle
()
descParagpraphStyle
.
minimumLineHeight
=
20
let
descriptionAttrString
=
NSAttributedString
(
string
:
"menu.premiumMembership"
.
localized
(),
attributes
:
[
.
foregroundColor
:
UIColor
.
white
,
.
paragraphStyle
:
descParagpraphStyle
,
.
font
:
AppFont
.
SFPro
.
bold
(
size
:
24
)])
premiumDescriptionLabel
.
attributedText
=
descriptionAttrString
buyButton
.
setTitle
(
"menu.upgradeNow"
.
localized
(),
for
:
.
normal
)
}
else
{
premiumHeadingLabel
.
font
=
AppFont
.
SFPro
.
bold
(
size
:
23
)
premiumHeadingLabel
.
text
=
"menu.goPremium"
.
localized
()
let
descParagpraphStyle
=
NSMutableParagraphStyle
()
descParagpraphStyle
.
minimumLineHeight
=
20
let
descriptionAttrString
=
NSAttributedString
(
string
:
"menu.premium.desc"
.
localized
(),
attributes
:
[
.
foregroundColor
:
UIColor
.
white
,
.
paragraphStyle
:
descParagpraphStyle
,
.
font
:
AppFont
.
SFPro
.
regular
(
size
:
14
)])
premiumDescriptionLabel
.
attributedText
=
descriptionAttrString
buyButton
.
setTitle
(
"menu.buyNow"
.
localized
(),
for
:
.
normal
)
}
}
//Prvaite
private
func
updateUI
()
{
backgroundColor
=
ThemeManager
.
currentTheme
.
baseBackgroundColor
...
...
@@ -80,35 +112,6 @@ private extension MenuHeaderView {
buyButton
.
addTarget
(
self
,
action
:
#selector(
handleBuyButton
)
,
for
:
.
touchUpInside
)
premiumContainer
.
addSubview
(
buyButton
)
if
StoreManager
.
shared
.
removeAdsPurchased
{
premiumHeadingLabel
.
font
=
AppFont
.
SFPro
.
regular
(
size
:
16
)
premiumHeadingLabel
.
text
=
"menu.upgradeTo"
.
localized
()
let
descParagpraphStyle
=
NSMutableParagraphStyle
()
descParagpraphStyle
.
minimumLineHeight
=
20
let
descriptionAttrString
=
NSAttributedString
(
string
:
"menu.premiumMembership"
.
localized
(),
attributes
:
[
.
foregroundColor
:
UIColor
.
white
,
.
paragraphStyle
:
descParagpraphStyle
,
.
font
:
AppFont
.
SFPro
.
bold
(
size
:
24
)])
premiumDescriptionLabel
.
attributedText
=
descriptionAttrString
buyButton
.
setTitle
(
"menu.upgradeNow"
.
localized
(),
for
:
.
normal
)
}
else
{
premiumHeadingLabel
.
font
=
AppFont
.
SFPro
.
bold
(
size
:
23
)
premiumHeadingLabel
.
text
=
"menu.goPremium"
.
localized
()
let
descParagpraphStyle
=
NSMutableParagraphStyle
()
descParagpraphStyle
.
minimumLineHeight
=
20
let
descriptionAttrString
=
NSAttributedString
(
string
:
"menu.premium.desc"
.
localized
(),
attributes
:
[
.
foregroundColor
:
UIColor
.
white
,
.
paragraphStyle
:
descParagpraphStyle
,
.
font
:
AppFont
.
SFPro
.
regular
(
size
:
14
)])
premiumDescriptionLabel
.
attributedText
=
descriptionAttrString
buyButton
.
setTitle
(
"menu.buyNow"
.
localized
(),
for
:
.
normal
)
}
//Constraints
premiumContainer
.
snp
.
makeConstraints
{
(
make
)
in
make
.
top
.
equalTo
(
30
)
...
...
1Weather/UI/View controllers/Menu/MenuViewController.swift
View file @
cfd25127
...
...
@@ -63,6 +63,7 @@ class MenuViewController: UIViewController {
super
.
viewWillAppear
(
animated
)
menuCellFactory
.
reload
()
menuHeaderView
.
reload
()
tableView
.
reloadData
()
}
...
...
@@ -157,6 +158,8 @@ extension MenuViewController: UITableViewDelegate {
viewModel
.
showDeviceId
()
case
.
subscriptionOverview
:
coordinator
.
openSubscriptionOverview
()
case
.
restorePurchases
:
viewModel
.
restorePurchases
()
default
:
break
}
...
...
@@ -168,6 +171,7 @@ extension MenuViewController: StoreManagerObserver {
func
storeManagerUpdatedStatus
(
_
storeManager
:
StoreManager
)
{
onMain
{
self
.
menuCellFactory
.
reload
()
self
.
menuHeaderView
.
reload
()
self
.
tableView
.
reloadData
()
}
}
...
...
1Weather/UI/View controllers/Subscriptions/SubscriptionOverviewViewController.swift
View file @
cfd25127
...
...
@@ -33,7 +33,7 @@ class SubscriptionOverviewViewController: UIViewController {
prepareScrollView
()
//Verify new subscription
StoreManager
.
shared
.
verify
Subscription
s
()
StoreManager
.
shared
.
verify
Purchase
s
()
}
}
...
...
1Weather/ViewModels/MenuViewModel.swift
View file @
cfd25127
...
...
@@ -69,6 +69,10 @@ class MenuViewModel: NSObject, ViewModelProtocol {
}
}
public
func
restorePurchases
()
{
storeManager
.
restoreInApp
()
}
public
func
viewAboutUs
()
{
self
.
delegate
?
.
presentWebView
(
url
:
ONE_WEATHER_ABOUT_US_URL
)
analytics
(
log
:
.
ANALYTICS_VIEW_ABOUT
)
...
...
1Weather/ViewModels/SubscriptionViewModel.swift
View file @
cfd25127
...
...
@@ -22,8 +22,7 @@ class SubscriptionViewModel: ViewModelProtocol {
}
public
var
isProUser
:
Bool
{
return
true
// storeManager.removeAdsPurchased
storeManager
.
removeAdsPurchased
}
public
func
purchase
(
subscription
:
SKProduct
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment