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
e5083f2c
Commit
e5083f2c
authored
Apr 28, 2021
by
Demid Merzlyakov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fetch FIPS codes & set FIPS_LIST.
parent
5719c7d2
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
204 additions
and
1 deletions
+204
-1
1Weather.xcodeproj/project.pbxproj
+12
-0
1Weather/Model/LocationManager.swift
+19
-1
1Weather/Network/Notifications/BlendFIPSSource.swift
+108
-0
1Weather/Network/Notifications/FIPSSource.swift
+14
-0
1Weather/Network/Notifications/Model/FIPSResponse.swift
+46
-0
1Weather/Network/PushNotificationsManager.swift
+5
-0
No files found.
1Weather.xcodeproj/project.pbxproj
View file @
e5083f2c
...
...
@@ -199,6 +199,8 @@
CE308B2A2637EA8E001ECD8A
/* _CoreNWSAlert.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CE308B282637EA8E001ECD8A
/* _CoreNWSAlert.swift */
;
};
CE308B2B2637EA8E001ECD8A
/* _CoreNotifications.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CE308B292637EA8E001ECD8A
/* _CoreNotifications.swift */
;
};
CE376C98261EE484000B1159
/* LaunchScreen.storyboard in Resources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CE376C97261EE484000B1159
/* LaunchScreen.storyboard */
;
};
CE3A36C72638A77E002CACC3
/* BlendFIPSSource.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CE3A36C62638A77E002CACC3
/* BlendFIPSSource.swift */
;
};
CE3A36ED2638A825002CACC3
/* FIPSResponse.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CE3A36EC2638A825002CACC3
/* FIPSResponse.swift */
;
};
CE578FD325F7E89400E8B85D
/* DayTimeWeather.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CE578FD225F7E89400E8B85D
/* DayTimeWeather.swift */
;
};
CE578FE525FB415F00E8B85D
/* CityCell.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CE578FE225FB415F00E8B85D
/* CityCell.swift */
;
};
CE578FE625FB415F00E8B85D
/* LocationViewController.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CE578FE325FB415F00E8B85D
/* LocationViewController.swift */
;
};
...
...
@@ -236,6 +238,7 @@
CEAFF0A325E0FF0800DF4EBF
/* LocationManager.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CEAFF0A225E0FF0800DF4EBF
/* LocationManager.swift */
;
};
CEBAC1C62638236D00A89681
/* PushNotificationsManager.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CEBAC1C52638236D00A89681
/* PushNotificationsManager.swift */
;
};
CEBAC1C82638240800A89681
/* DeeplinksRouter.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CEBAC1C72638240800A89681
/* DeeplinksRouter.swift */
;
};
CEBAC2122638968D00A89681
/* FIPSSource.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CEBAC2112638968D00A89681
/* FIPSSource.swift */
;
};
CEC526FA25E7959A00DA58A5
/* WeatherSource.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CEC526F925E7959A00DA58A5
/* WeatherSource.swift */
;
};
CEC526FD25E795F700DA58A5
/* WdtWeatherSource.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CEC526FC25E795F700DA58A5
/* WdtWeatherSource.swift */
;
};
CEC5270025E7BACB00DA58A5
/* WdtLocation.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CEC526FF25E7BACB00DA58A5
/* WdtLocation.swift */
;
};
...
...
@@ -484,6 +487,8 @@
CE308B282637EA8E001ECD8A
/* _CoreNWSAlert.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
_CoreNWSAlert.swift
;
sourceTree
=
"<group>"
;
};
CE308B292637EA8E001ECD8A
/* _CoreNotifications.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
_CoreNotifications.swift
;
sourceTree
=
"<group>"
;
};
CE376C97261EE484000B1159
/* LaunchScreen.storyboard */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
file.storyboard
;
path
=
LaunchScreen.storyboard
;
sourceTree
=
"<group>"
;
};
CE3A36C62638A77E002CACC3
/* BlendFIPSSource.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
BlendFIPSSource.swift
;
sourceTree
=
"<group>"
;
};
CE3A36EC2638A825002CACC3
/* FIPSResponse.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
FIPSResponse.swift
;
sourceTree
=
"<group>"
;
};
CE578FD225F7E89400E8B85D
/* DayTimeWeather.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
DayTimeWeather.swift
;
sourceTree
=
"<group>"
;
};
CE578FE225FB415F00E8B85D
/* CityCell.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
CityCell.swift
;
sourceTree
=
"<group>"
;
};
CE578FE325FB415F00E8B85D
/* LocationViewController.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
LocationViewController.swift
;
sourceTree
=
"<group>"
;
};
...
...
@@ -521,6 +526,7 @@
CEAFF0A225E0FF0800DF4EBF
/* LocationManager.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
LocationManager.swift
;
sourceTree
=
"<group>"
;
};
CEBAC1C52638236D00A89681
/* PushNotificationsManager.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
PushNotificationsManager.swift
;
sourceTree
=
"<group>"
;
};
CEBAC1C72638240800A89681
/* DeeplinksRouter.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
DeeplinksRouter.swift
;
sourceTree
=
"<group>"
;
};
CEBAC2112638968D00A89681
/* FIPSSource.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
FIPSSource.swift
;
sourceTree
=
"<group>"
;
};
CEC526F925E7959A00DA58A5
/* WeatherSource.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
WeatherSource.swift
;
sourceTree
=
"<group>"
;
};
CEC526FC25E795F700DA58A5
/* WdtWeatherSource.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
WdtWeatherSource.swift
;
sourceTree
=
"<group>"
;
};
CEC526FF25E7BACB00DA58A5
/* WdtLocation.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
WdtLocation.swift
;
sourceTree
=
"<group>"
;
};
...
...
@@ -1227,6 +1233,8 @@
CE13B98026272A13007CBD4D
/* Model */
,
CE0456232629C04C003D252B
/* NWSAlertsManager.swift */
,
CEE0A1A326317A8F0044C257
/* NWSAlertInfoParser.swift */
,
CEBAC2112638968D00A89681
/* FIPSSource.swift */
,
CE3A36C62638A77E002CACC3
/* BlendFIPSSource.swift */
,
);
path
=
Notifications
;
sourceTree
=
"<group>"
;
...
...
@@ -1239,6 +1247,7 @@
CEE0A1A126317A3F0044C257
/* NWSSeverityLevel.swift */
,
CEE0A19F26317A1E0044C257
/* NWSAlertExtendedInfo.swift */
,
CEE0A17A263179E50044C257
/* NWSAlertInfoBlock.swift */
,
CE3A36EC2638A825002CACC3
/* FIPSResponse.swift */
,
);
path
=
Model
;
sourceTree
=
"<group>"
;
...
...
@@ -1737,6 +1746,7 @@
CD67617C2625A60B0079D273
/* MapLayersDismissAnimator.swift in Sources */
,
CEAFF08C25DFC6BD00DF4EBF
/* DailyWeather.swift in Sources */
,
CEDE4F0B25EFA3A7007457E9
/* UpdatableModelObject.swift in Sources */
,
CE3A36C72638A77E002CACC3
/* BlendFIPSSource.swift in Sources */
,
CE13B814262480B3007CBD4D
/* BRNativeBannerView.swift in Sources */
,
CE13B7E126247BF9007CBD4D
/* UserDefaultsOptionalValue.swift in Sources */
,
CE8962A626175DF500CA274A
/* _CoreHealth.swift in Sources */
,
...
...
@@ -1839,6 +1849,7 @@
CE9F01C1261B3776009BA500
/* CoreDataUtils.swift in Sources */
,
CD67616D262587D30079D273
/* UITabBarController+Hide.swift in Sources */
,
CDC6126225E8DAB800188DA7
/* MoonPhaseCell.swift in Sources */
,
CEBAC2122638968D00A89681
/* FIPSSource.swift in Sources */
,
CD37D3D6260C93B3002669D6
/* MenuCellFactory.swift in Sources */
,
CD8B60AD263819400055CB3F
/* NWSAlertInfoBlockTableViewCell.swift in Sources */
,
87D815AC2636D61D0015A6D1
/* NWSAlertViewModel.swift in Sources */
,
...
...
@@ -1877,6 +1888,7 @@
CD32CE0B260C744A00235081
/* MenuCoordinator.swift in Sources */
,
CD55E0BB2615EE2400CC4DC7
/* PollutantView.swift in Sources */
,
CE308B2A2637EA8E001ECD8A
/* _CoreNWSAlert.swift in Sources */
,
CE3A36ED2638A825002CACC3
/* FIPSResponse.swift in Sources */
,
CD8B60B3263819790055CB3F
/* NWSAlertCell.swift in Sources */
,
CE13B81C262480B3007CBD4D
/* Interstitial.swift in Sources */
,
CDDE8D7C262EED3C00267931
/* MapLegendSevereView.swift in Sources */
,
...
...
1Weather/Model/LocationManager.swift
View file @
e5083f2c
...
...
@@ -21,6 +21,7 @@ public class LocationManager {
private
let
weatherUpdateSource
:
WeatherSource
private
let
healthSource
:
HealthSource
private
let
fipsSource
:
FIPSSource
public
let
nwsAlertsManager
:
NWSAlertsManager
private
let
storage
:
Storage
private
var
defaultLocation
=
Location
(
deviceLocation
:
false
,
...
...
@@ -154,15 +155,17 @@ public class LocationManager {
weatherUpdateSource
:
WdtWeatherSource
(),
healthSource
:
BlendHealthSource
(),
nwsAlertsManager
:
NWSAlertsManager
(),
fipsSource
:
BlendFIPSSource
(),
storage
:
DelayedSaveStorage
(
storage
:
CoreDataStorage
(),
delay
:
2
))
public
let
maxLocationsCount
=
12
public
init
(
weatherUpdateSource
:
WeatherSource
,
healthSource
:
HealthSource
,
nwsAlertsManager
:
NWSAlertsManager
,
storage
:
Storage
)
{
public
init
(
weatherUpdateSource
:
WeatherSource
,
healthSource
:
HealthSource
,
nwsAlertsManager
:
NWSAlertsManager
,
fipsSource
:
FIPSSource
,
storage
:
Storage
)
{
self
.
weatherUpdateSource
=
weatherUpdateSource
self
.
healthSource
=
healthSource
self
.
deviceLocationMonitor
=
DeviceLocationMonitor
()
self
.
nwsAlertsManager
=
nwsAlertsManager
self
.
fipsSource
=
fipsSource
self
.
storage
=
storage
self
.
deviceLocationMonitor
.
delegate
=
self
...
...
@@ -204,6 +207,21 @@ public class LocationManager {
}
updateHealth
(
for
:
location
)
updateNotifications
(
for
:
location
)
getFipsIfNeeded
(
for
:
location
)
}
}
public
func
getFipsIfNeeded
(
for
location
:
Location
)
{
if
location
.
fipsCode
==
nil
{
fipsSource
.
getFipsCode
(
for
:
location
)
{
[
weak
self
]
(
fipsCode
)
in
if
let
fipsCode
=
fipsCode
{
self
?
.
makeChanges
(
to
:
location
,
in
:
"getFips"
)
{
(
location
)
->
Location
in
var
updatedLocation
=
location
updatedLocation
.
fipsCode
=
fipsCode
return
updatedLocation
}
}
}
}
}
...
...
1Weather/Network/Notifications/BlendFIPSSource.swift
0 → 100644
View file @
e5083f2c
//
// BlendFIPSSource.swift
// 1Weather
//
// Created by Demid Merzlyakov on 28.04.2021.
//
import
Foundation
class
BlendFIPSSource
:
FIPSSource
{
private
let
log
=
Logger
(
componentName
:
"BlendFIPSSource"
)
private
let
baseUrlProduction
=
"https://nwsalert.onelouder.com"
private
let
baseUrlStaging
=
"https://sta-nwsalert.onelouder.com"
private
static
let
blendAPIKeyHeaderName
=
"blend-api-key"
private
static
let
blendAPIKey
=
"0imfnc8mVLWwsAawjYr4Rx-Af50DDqtlx"
#if DEBUG
public
var
useStaging
=
true
#else
public
var
useStaging
=
false
#endif
private
var
baseUrl
:
String
{
useStaging
?
baseUrlStaging
:
baseUrlProduction
}
/// This queue is needed to synchronize access to locationsBeingUpdated. Also, to make logging more clear.
private
let
internalQueue
:
OperationQueue
=
{
let
queue
=
OperationQueue
()
queue
.
name
=
"BlendHealthSource Queue"
queue
.
maxConcurrentOperationCount
=
1
return
queue
}()
private
var
locationsBeingUpdated
=
Set
<
Location
>
()
public
func
getFipsCode
(
for
location
:
Location
,
completion
:
@escaping
FIPSSourceeCompletion
)
{
internalQueue
.
addOperation
{
[
weak
self
]
in
let
extendedCompletion
:
FIPSSourceeCompletion
=
{
[
weak
self
]
(
fipsCode
)
in
self
?
.
internalQueue
.
addOperation
{
completion
(
fipsCode
)
self
?
.
locationsBeingUpdated
.
remove
(
location
)
}
}
self
?
.
getFipsCodeInternal
(
for
:
location
,
completion
:
extendedCompletion
)
}
}
private
func
getFipsCodeInternal
(
for
location
:
Location
,
completion
:
@escaping
FIPSSourceeCompletion
)
{
guard
!
locationsBeingUpdated
.
contains
(
location
)
else
{
completion
(
nil
)
return
}
locationsBeingUpdated
.
insert
(
location
)
guard
let
url
=
URL
(
string
:
self
.
baseUrl
+
"/1weather/api/v1/location"
)
else
{
assertionFailure
(
"Should never happen. The URL should be correct."
)
return
}
var
queryParameters
=
[
String
:
String
]()
if
let
coordinates
=
location
.
coordinates
{
queryParameters
[
"lat"
]
=
String
(
format
:
"%.5f"
,
coordinates
.
latitude
)
queryParameters
[
"lon"
]
=
String
(
format
:
"%.5f"
,
coordinates
.
longitude
)
}
queryParameters
[
"zip"
]
=
location
.
zip
queryParameters
[
"city"
]
=
location
.
cityName
queryParameters
[
"state"
]
=
location
.
region
queryParameters
[
"country"
]
=
location
.
countryCode
guard
!
queryParameters
.
isEmpty
else
{
completion
(
nil
)
log
.
error
(
"Not enough information about location."
)
return
}
log
.
debug
(
"Network request (
\(
location
)
):
\(
url
)
"
)
var
request
=
URLRequest
(
url
:
url
)
let
encoder
=
JSONEncoder
()
guard
let
requestBody
=
try
?
encoder
.
encode
(
queryParameters
)
else
{
completion
(
nil
)
log
.
error
(
"Couldn't encode request body:
\(
queryParameters
)
"
)
return
}
request
.
httpBody
=
requestBody
var
headers
=
request
.
allHTTPHeaderFields
??
[
String
:
String
]()
headers
[
BlendFIPSSource
.
blendAPIKeyHeaderName
]
=
BlendFIPSSource
.
blendAPIKey
headers
[
"Content-Type"
]
=
"application/json"
request
.
allHTTPHeaderFields
=
headers
request
.
httpMethod
=
"POST"
let
urlSession
=
URLSession
.
shared
let
dataTask
=
urlSession
.
dataTask
(
with
:
request
)
{
(
data
,
reponse
,
error
)
in
// TODO: check response HTTP code
guard
let
data
=
data
else
{
self
.
log
.
debug
(
"Network response (
\(
location
)
): error
\(
String
(
describing
:
error
)
)
"
)
completion
(
nil
)
return
}
let
responseBodyString
=
String
(
data
:
data
,
encoding
:
.
utf8
)
??
"<couldn't show as string"
self
.
log
.
debug
(
"Network response (
\(
location
)
):
\(
responseBodyString
)
"
)
completion
(
FIPSResponse
(
data
:
data
)?
.
fipsCode
)
}
dataTask
.
resume
()
}
}
1Weather/Network/Notifications/FIPSSource.swift
0 → 100644
View file @
e5083f2c
//
// FIPSSource.swift
// 1Weather
//
// Created by Demid Merzlyakov on 27.04.2021.
//
import
Foundation
public
typealias
FIPSSourceeCompletion
=
(
String
?)
->
()
public
protocol
FIPSSource
{
func
getFipsCode
(
for
location
:
Location
,
completion
:
@escaping
FIPSSourceeCompletion
)
}
1Weather/Network/Notifications/Model/FIPSResponse.swift
0 → 100644
View file @
e5083f2c
//
// FIPSResponse.swift
// 1Weather
//
// Created by Demid Merzlyakov on 28.04.2021.
//
import
Foundation
struct
FIPSResponse
:
Codable
{
let
fipsCode
,
s2CellID
:
String
enum
CodingKeys
:
String
,
CodingKey
{
case
fipsCode
=
"fips_code"
case
s2CellID
=
"s2_cell_id"
}
}
// MARK: Convenience initializers
extension
FIPSResponse
{
init
?(
data
:
Data
)
{
guard
let
me
=
try
?
JSONDecoder
()
.
decode
(
FIPSResponse
.
self
,
from
:
data
)
else
{
return
nil
}
self
=
me
}
init
?(
_
json
:
String
,
using
encoding
:
String
.
Encoding
=
.
utf8
)
{
guard
let
data
=
json
.
data
(
using
:
encoding
)
else
{
return
nil
}
self
.
init
(
data
:
data
)
}
init
?(
fromURL
url
:
String
)
{
guard
let
url
=
URL
(
string
:
url
)
else
{
return
nil
}
guard
let
data
=
try
?
Data
(
contentsOf
:
url
)
else
{
return
nil
}
self
.
init
(
data
:
data
)
}
var
jsonData
:
Data
?
{
return
try
?
JSONEncoder
()
.
encode
(
self
)
}
var
json
:
String
?
{
guard
let
data
=
self
.
jsonData
else
{
return
nil
}
return
String
(
data
:
data
,
encoding
:
.
utf8
)
}
}
1Weather/Network/PushNotificationsManager.swift
View file @
e5083f2c
...
...
@@ -41,6 +41,11 @@ class PushNotificationsManager: NSObject {
}
}
public
func
updateNwsSubscriptions
(
for
locations
:
[
Location
])
{
let
fipsCodes
=
locations
.
compactMap
{
$0
.
fipsCode
}
MoEngage
.
sharedInstance
()
.
setUserAttribute
(
fipsCodes
.
joined
(
separator
:
","
),
forKey
:
"FIPS_LIST"
)
}
public
func
set
(
pushToken
:
Data
)
{
let
tokenString
=
pushToken
.
map
{
String
(
format
:
"%02.2hhx"
,
$0
)
}
.
joined
()
log
.
info
(
"Got new APNS token:
\(
tokenString
)
"
)
...
...
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