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
13c10ce9
Commit
13c10ce9
authored
Apr 13, 2021
by
Demid Merzlyakov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Ads integrated on the Today screen.
parent
225696ee
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
67 additions
and
23 deletions
+67
-23
1Weather.xcodeproj/project.pbxproj
+4
-4
1Weather/Ads/Helpers/AdLogger.swift
+4
-0
1Weather/Analytics/Analytics.swift
+6
-7
1Weather/UI/View controllers/Today/Cells/AdCell.swift
+21
-3
1Weather/UI/View controllers/Today/Cells/TodayCellFactory.swift
+28
-9
1Weather/UI/View controllers/Today/TodayViewController.swift
+4
-0
No files found.
1Weather.xcodeproj/project.pbxproj
View file @
13c10ce9
...
@@ -73,7 +73,7 @@
...
@@ -73,7 +73,7 @@
CD80917B2578E4A8003541A4
/* UIViewController+Alert.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD80917A2578E4A8003541A4
/* UIViewController+Alert.swift */
;
};
CD80917B2578E4A8003541A4
/* UIViewController+Alert.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD80917A2578E4A8003541A4
/* UIViewController+Alert.swift */
;
};
CD822FF525D6817000A05501
/* TodayForecastCell.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD822FF425D6817000A05501
/* TodayForecastCell.swift */
;
};
CD822FF525D6817000A05501
/* TodayForecastCell.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD822FF425D6817000A05501
/* TodayForecastCell.swift */
;
};
CD822FFA25D6890900A05501
/* OneWeatherColorsAsset.xcassets in Resources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD822FF925D6890900A05501
/* OneWeatherColorsAsset.xcassets */
;
};
CD822FFA25D6890900A05501
/* OneWeatherColorsAsset.xcassets in Resources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD822FF925D6890900A05501
/* OneWeatherColorsAsset.xcassets */
;
};
CD822FFE25D6976F00A05501
/*
TodayAdCell.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD822FFD25D6976F00A05501
/* Today
AdCell.swift */
;
};
CD822FFE25D6976F00A05501
/*
AdCell.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD822FFD25D6976F00A05501
/*
AdCell.swift */
;
};
CD82300325D69DE400A05501
/* TodayConditionsCell.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD82300225D69DE400A05501
/* TodayConditionsCell.swift */
;
};
CD82300325D69DE400A05501
/* TodayConditionsCell.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD82300225D69DE400A05501
/* TodayConditionsCell.swift */
;
};
CD82300725D6A73F00A05501
/* TodayConditionButton.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD82300625D6A73E00A05501
/* TodayConditionButton.swift */
;
};
CD82300725D6A73F00A05501
/* TodayConditionButton.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD82300625D6A73E00A05501
/* TodayConditionButton.swift */
;
};
CD82300A25D6B2AF00A05501
/* AppTabBarController.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD82300925D6B2AF00A05501
/* AppTabBarController.swift */
;
};
CD82300A25D6B2AF00A05501
/* AppTabBarController.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD82300925D6B2AF00A05501
/* AppTabBarController.swift */
;
};
...
@@ -299,7 +299,7 @@
...
@@ -299,7 +299,7 @@
CD80917A2578E4A8003541A4
/* UIViewController+Alert.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
"UIViewController+Alert.swift"
;
sourceTree
=
"<group>"
;
};
CD80917A2578E4A8003541A4
/* UIViewController+Alert.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
"UIViewController+Alert.swift"
;
sourceTree
=
"<group>"
;
};
CD822FF425D6817000A05501
/* TodayForecastCell.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
TodayForecastCell.swift
;
sourceTree
=
"<group>"
;
};
CD822FF425D6817000A05501
/* TodayForecastCell.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
TodayForecastCell.swift
;
sourceTree
=
"<group>"
;
};
CD822FF925D6890900A05501
/* OneWeatherColorsAsset.xcassets */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
folder.assetcatalog
;
path
=
OneWeatherColorsAsset.xcassets
;
sourceTree
=
"<group>"
;
};
CD822FF925D6890900A05501
/* OneWeatherColorsAsset.xcassets */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
folder.assetcatalog
;
path
=
OneWeatherColorsAsset.xcassets
;
sourceTree
=
"<group>"
;
};
CD822FFD25D6976F00A05501
/*
TodayAdCell.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Today
AdCell.swift
;
sourceTree
=
"<group>"
;
};
CD822FFD25D6976F00A05501
/*
AdCell.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
AdCell.swift
;
sourceTree
=
"<group>"
;
};
CD82300225D69DE400A05501
/* TodayConditionsCell.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
TodayConditionsCell.swift
;
sourceTree
=
"<group>"
;
};
CD82300225D69DE400A05501
/* TodayConditionsCell.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
TodayConditionsCell.swift
;
sourceTree
=
"<group>"
;
};
CD82300625D6A73E00A05501
/* TodayConditionButton.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
TodayConditionButton.swift
;
sourceTree
=
"<group>"
;
};
CD82300625D6A73E00A05501
/* TodayConditionButton.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
TodayConditionButton.swift
;
sourceTree
=
"<group>"
;
};
CD82300925D6B2AF00A05501
/* AppTabBarController.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
AppTabBarController.swift
;
sourceTree
=
"<group>"
;
};
CD82300925D6B2AF00A05501
/* AppTabBarController.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
AppTabBarController.swift
;
sourceTree
=
"<group>"
;
};
...
@@ -730,7 +730,7 @@
...
@@ -730,7 +730,7 @@
isa
=
PBXGroup
;
isa
=
PBXGroup
;
children
=
(
children
=
(
CDA5542725EF734200A2E08C
/* TodayCellFactory.swift */
,
CDA5542725EF734200A2E08C
/* TodayCellFactory.swift */
,
CD822FFD25D6976F00A05501
/*
Today
AdCell.swift */
,
CD822FFD25D6976F00A05501
/* AdCell.swift */
,
CD822FF425D6817000A05501
/* TodayForecastCell.swift */
,
CD822FF425D6817000A05501
/* TodayForecastCell.swift */
,
CD15DB4125DA806C00024727
/* TodayForecastTimePeriodCell.swift */
,
CD15DB4125DA806C00024727
/* TodayForecastTimePeriodCell.swift */
,
CD82300125D69DB900A05501
/* TodayConditions */
,
CD82300125D69DB900A05501
/* TodayConditions */
,
...
@@ -1529,7 +1529,7 @@
...
@@ -1529,7 +1529,7 @@
CDF4808F261727E00076E9F5
/* CLAuthorizationStatus+Localized.swift in Sources */
,
CDF4808F261727E00076E9F5
/* CLAuthorizationStatus+Localized.swift in Sources */
,
CE13B81D262480B3007CBD4D
/* BRMoPubAdView.m in Sources */
,
CE13B81D262480B3007CBD4D
/* BRMoPubAdView.m in Sources */
,
CD37D3DE260C9E37002669D6
/* MenuCell.swift in Sources */
,
CD37D3DE260C9E37002669D6
/* MenuCell.swift in Sources */
,
CD822FFE25D6976F00A05501
/*
Today
AdCell.swift in Sources */
,
CD822FFE25D6976F00A05501
/* AdCell.swift in Sources */
,
CEF959A626035A2600975FAA
/* DeviceLocationMonitor.swift in Sources */
,
CEF959A626035A2600975FAA
/* DeviceLocationMonitor.swift in Sources */
,
CD32CDFF260B2E5400235081
/* ForecastDescriptionView.swift in Sources */
,
CD32CDFF260B2E5400235081
/* ForecastDescriptionView.swift in Sources */
,
CEC5275D25E8E50B00DA58A5
/* WdtDailySummary.swift in Sources */
,
CEC5275D25E8E50B00DA58A5
/* WdtDailySummary.swift in Sources */
,
...
...
1Weather/Ads/Helpers/AdLogger.swift
View file @
13c10ce9
...
@@ -21,7 +21,11 @@ class AdLogger: NSObject {
...
@@ -21,7 +21,11 @@ class AdLogger: NSObject {
case
error
case
error
}
}
#if DEBUG
static
var
debugMode
:
Bool
=
true
#else
static
var
debugMode
:
Bool
=
false
static
var
debugMode
:
Bool
=
false
#endif
static
func
setDebugMode
(
_
on
:
Bool
)
{
static
func
setDebugMode
(
_
on
:
Bool
)
{
debugMode
=
on
debugMode
=
on
...
...
1Weather/Analytics/Analytics.swift
View file @
13c10ce9
...
@@ -9,7 +9,7 @@ import Foundation
...
@@ -9,7 +9,7 @@ import Foundation
public
class
Analytics
{
public
class
Analytics
{
private
let
services
:
[
AnalyticsService
]
private
let
services
:
[
AnalyticsService
]
private
let
log
=
Logger
(
componentName
:
"Analytics"
)
private
let
log
=
Logger
(
componentName
:
"
⬜
Analytics"
)
public
init
(
services
:
[
AnalyticsService
])
{
public
init
(
services
:
[
AnalyticsService
])
{
self
.
services
=
services
self
.
services
=
services
...
@@ -30,15 +30,14 @@ public class Analytics {
...
@@ -30,15 +30,14 @@ public class Analytics {
}
}
let
loggedToString
=
loggedTo
.
joined
(
separator
:
", "
)
let
loggedToString
=
loggedTo
.
joined
(
separator
:
", "
)
if
let
params
=
params
{
if
let
params
=
params
{
if
let
prettyPrintableParams
=
params
as?
[
AnalyticsParameter
:
Any
]
{
var
readableParams
=
[
String
:
Any
](
minimumCapacity
:
params
.
count
)
log
.
info
(
"Event
\(
event
.
rawValue
)
params:
\(
prettyPrintableParams
)
sent to
\(
loggedToString
)
)"
)
for
(
key
,
value
)
in
params
{
}
readableParams
[
key
.
rawValue
]
=
value
else
{
log
.
info
(
"Event
\(
event
.
rawValue
)
params:
\(
params
)
sent to
\(
loggedToString
)
)"
)
}
}
log
.
info
(
"Event
\(
event
.
rawValue
)
params:
\(
readableParams
)
sent to
\(
loggedToString
)
"
)
}
}
else
{
else
{
log
.
info
(
"Event
\(
event
.
rawValue
)
sent to
\(
loggedToString
)
)
"
)
log
.
info
(
"Event
\(
event
.
rawValue
)
sent to
\(
loggedToString
)
"
)
}
}
}
}
}
}
1Weather/UI/View controllers/Today/Cells/
Today
AdCell.swift
→
1Weather/UI/View controllers/Today/Cells/AdCell.swift
View file @
13c10ce9
...
@@ -7,10 +7,18 @@
...
@@ -7,10 +7,18 @@
import
UIKit
import
UIKit
class
Today
AdCell
:
UITableViewCell
{
class
AdCell
:
UITableViewCell
{
//Private
//Private
private
let
container
=
UIView
()
private
let
container
=
UIView
()
private
let
label
=
UILabel
()
private
let
label
=
UILabel
()
public
var
adView
:
AdView
?
=
nil
{
didSet
{
guard
adView
!=
oldValue
else
{
return
}
prepareAd
()
}
}
private
let
gradientView
=
GradientView
(
startColor
:
UIColor
.
white
.
withAlphaComponent
(
0
),
private
let
gradientView
=
GradientView
(
startColor
:
UIColor
.
white
.
withAlphaComponent
(
0
),
endColor
:
UIColor
(
hex
:
0xdaddec
),
endColor
:
UIColor
(
hex
:
0xdaddec
),
opacity
:
0.5
)
opacity
:
0.5
)
...
@@ -52,10 +60,9 @@ class TodayAdCell: UITableViewCell {
...
@@ -52,10 +60,9 @@ class TodayAdCell: UITableViewCell {
}
}
//MARK:- Prepare
//MARK:- Prepare
private
extension
Today
AdCell
{
private
extension
AdCell
{
func
prepareCellStyle
()
{
func
prepareCellStyle
()
{
selectionStyle
=
.
none
selectionStyle
=
.
none
}
}
func
prepareContainer
()
{
func
prepareContainer
()
{
...
@@ -71,6 +78,10 @@ private extension TodayAdCell {
...
@@ -71,6 +78,10 @@ private extension TodayAdCell {
}
}
func
prepareAd
()
{
func
prepareAd
()
{
for
subview
in
container
.
subviews
{
subview
.
removeFromSuperview
()
}
label
.
text
=
"Advertisment"
label
.
text
=
"Advertisment"
label
.
font
=
AppFont
.
SFPro
.
regular
(
size
:
14
)
label
.
font
=
AppFont
.
SFPro
.
regular
(
size
:
14
)
container
.
addSubview
(
label
)
container
.
addSubview
(
label
)
...
@@ -78,6 +89,13 @@ private extension TodayAdCell {
...
@@ -78,6 +89,13 @@ private extension TodayAdCell {
label
.
snp
.
makeConstraints
{
(
make
)
in
label
.
snp
.
makeConstraints
{
(
make
)
in
make
.
center
.
equalToSuperview
()
make
.
center
.
equalToSuperview
()
}
}
if
let
adView
=
adView
{
container
.
addSubview
(
adView
)
adView
.
snp
.
makeConstraints
{
(
make
)
in
make
.
center
.
equalToSuperview
()
make
.
size
.
equalToSuperview
()
}
}
}
}
func
prepareGradient
()
{
func
prepareGradient
()
{
...
...
1Weather/UI/View controllers/Today/Cells/TodayCellFactory.swift
View file @
13c10ce9
...
@@ -40,12 +40,8 @@ class TodayCellFactory: CellFactoryProtocol {
...
@@ -40,12 +40,8 @@ class TodayCellFactory: CellFactoryProtocol {
private
var
todaySection
=
TodaySection
(
rows
:
[
.
alert
,
.
forecast
,
.
ad
,
private
var
todaySection
=
TodaySection
(
rows
:
[
.
alert
,
.
forecast
,
.
ad
,
.
conditions
,
.
forecastPeriod
,
.
precipitation
,
.
conditions
,
.
forecastPeriod
,
.
precipitation
,
.
airQuality
,
.
dayTime
,
.
sun
,
.
moon
])
.
airQuality
,
.
dayTime
,
.
sun
,
.
moon
])
private
let
health
=
Health
(
lastUpdateTime
:
Date
(),
airQuality
:
.
init
(
index
:
140
,
advice
:
"Slightly elevated pollution, but general public likely not affected"
),
private
var
adViewCache
=
[
IndexPath
:
AdView
]()
pollutants
:
[
"pm25"
:
.
init
(
name
:
"PM 2.5"
,
value
:
48
),
"pm10"
:
.
init
(
name
:
"PM 10"
,
value
:
42
),
"no2"
:
.
init
(
name
:
"NO2"
,
value
:
74
),
"so2"
:
.
init
(
name
:
"SO2"
,
value
:
135
)])
//Public
//Public
init
(
viewModel
:
TodayViewModel
)
{
init
(
viewModel
:
TodayViewModel
)
{
...
@@ -63,7 +59,7 @@ class TodayCellFactory: CellFactoryProtocol {
...
@@ -63,7 +59,7 @@ class TodayCellFactory: CellFactoryProtocol {
public
func
registerCells
(
on
tableView
:
UITableView
)
{
public
func
registerCells
(
on
tableView
:
UITableView
)
{
registerCell
(
type
:
TodayAlertCell
.
self
,
tableView
:
tableView
)
registerCell
(
type
:
TodayAlertCell
.
self
,
tableView
:
tableView
)
registerCell
(
type
:
TodayForecastCell
.
self
,
tableView
:
tableView
)
registerCell
(
type
:
TodayForecastCell
.
self
,
tableView
:
tableView
)
registerCell
(
type
:
Today
AdCell
.
self
,
tableView
:
tableView
)
registerCell
(
type
:
AdCell
.
self
,
tableView
:
tableView
)
registerCell
(
type
:
TodayConditionsCell
.
self
,
tableView
:
tableView
)
registerCell
(
type
:
TodayConditionsCell
.
self
,
tableView
:
tableView
)
registerCell
(
type
:
TodayForecastTimePeriodCell
.
self
,
tableView
:
tableView
)
registerCell
(
type
:
TodayForecastTimePeriodCell
.
self
,
tableView
:
tableView
)
registerCell
(
type
:
PrecipitationCell
.
self
,
tableView
:
tableView
)
registerCell
(
type
:
PrecipitationCell
.
self
,
tableView
:
tableView
)
...
@@ -73,6 +69,17 @@ class TodayCellFactory: CellFactoryProtocol {
...
@@ -73,6 +69,17 @@ class TodayCellFactory: CellFactoryProtocol {
registerCell
(
type
:
MoonPhaseCell
.
self
,
tableView
:
tableView
)
registerCell
(
type
:
MoonPhaseCell
.
self
,
tableView
:
tableView
)
}
}
private
func
adView
(
for
indexPath
:
IndexPath
)
->
AdView
{
if
let
adView
=
adViewCache
[
indexPath
]
{
return
adView
}
let
adView
=
adViewCache
[
indexPath
]
??
AdView
()
adView
.
loggingAlias
=
"📍 Today Banner"
adView
.
set
(
placementName
:
placementNameTodayBanner
,
adType
:
.
banner
)
adViewCache
[
indexPath
]
=
adView
return
adView
}
public
func
cellFromTableView
(
tableView
:
UITableView
,
indexPath
:
IndexPath
)
->
UITableViewCell
{
public
func
cellFromTableView
(
tableView
:
UITableView
,
indexPath
:
IndexPath
)
->
UITableViewCell
{
let
cellType
=
todaySection
.
rows
[
indexPath
.
row
]
let
cellType
=
todaySection
.
rows
[
indexPath
.
row
]
guard
let
loc
=
self
.
todayViewModel
.
location
else
{
guard
let
loc
=
self
.
todayViewModel
.
location
else
{
...
@@ -87,7 +94,8 @@ class TodayCellFactory: CellFactoryProtocol {
...
@@ -87,7 +94,8 @@ class TodayCellFactory: CellFactoryProtocol {
cell
.
configure
(
with
:
loc
)
cell
.
configure
(
with
:
loc
)
return
cell
return
cell
case
.
ad
:
case
.
ad
:
let
cell
=
dequeueReusableCell
(
type
:
TodayAdCell
.
self
,
tableView
:
tableView
,
indexPath
:
indexPath
)
let
cell
=
dequeueReusableCell
(
type
:
AdCell
.
self
,
tableView
:
tableView
,
indexPath
:
indexPath
)
cell
.
adView
=
adView
(
for
:
indexPath
)
return
cell
return
cell
case
.
conditions
:
case
.
conditions
:
let
cell
=
dequeueReusableCell
(
type
:
TodayConditionsCell
.
self
,
tableView
:
tableView
,
indexPath
:
indexPath
)
let
cell
=
dequeueReusableCell
(
type
:
TodayConditionsCell
.
self
,
tableView
:
tableView
,
indexPath
:
indexPath
)
...
@@ -136,12 +144,23 @@ class TodayCellFactory: CellFactoryProtocol {
...
@@ -136,12 +144,23 @@ class TodayCellFactory: CellFactoryProtocol {
cellsToUpdate
=
[
.
condition
,
.
timePeriod
,
.
precipitation
,
.
dayTime
]
cellsToUpdate
=
[
.
condition
,
.
timePeriod
,
.
precipitation
,
.
dayTime
]
}
}
public
func
willDisplay
(
cell
:
UITableViewCell
)
{
public
func
willDisplay
(
cell
:
UITableViewCell
)
{
switch
cell
{
switch
cell
{
case
let
sunCell
as
SunPhaseCell
:
case
let
sunCell
as
SunPhaseCell
:
sunCell
.
updateSunPosition
()
sunCell
.
updateSunPosition
()
case
let
moonCell
as
MoonPhaseCell
:
case
let
moonCell
as
MoonPhaseCell
:
moonCell
.
updateMoonPosition
()
moonCell
.
updateMoonPosition
()
case
let
adCell
as
AdCell
:
adCell
.
adView
?
.
start
()
default
:
break
}
}
public
func
didHide
(
cell
:
UITableViewCell
)
{
switch
cell
{
case
let
adCell
as
AdCell
:
adCell
.
adView
?
.
stop
()
default
:
default
:
break
break
}
}
...
...
1Weather/UI/View controllers/Today/TodayViewController.swift
View file @
13c10ce9
...
@@ -131,6 +131,10 @@ extension TodayViewController: UITableViewDelegate {
...
@@ -131,6 +131,10 @@ extension TodayViewController: UITableViewDelegate {
func
tableView
(
_
tableView
:
UITableView
,
willDisplay
cell
:
UITableViewCell
,
forRowAt
indexPath
:
IndexPath
)
{
func
tableView
(
_
tableView
:
UITableView
,
willDisplay
cell
:
UITableViewCell
,
forRowAt
indexPath
:
IndexPath
)
{
todayCellFactory
.
willDisplay
(
cell
:
cell
)
todayCellFactory
.
willDisplay
(
cell
:
cell
)
}
}
func
tableView
(
_
tableView
:
UITableView
,
didEndDisplaying
cell
:
UITableViewCell
,
forRowAt
indexPath
:
IndexPath
)
{
todayCellFactory
.
didHide
(
cell
:
cell
)
}
}
}
//MARK:- ViewModel Delegate
//MARK:- ViewModel Delegate
...
...
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