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
3117b368
Commit
3117b368
authored
Jul 22, 2021
by
Dmitriy Stepanets
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added widget analytics
parent
cb00631e
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
255 additions
and
12 deletions
+255
-12
1Weather.xcodeproj/project.pbxproj
+12
-0
1Weather/AppDelegate.swift
+12
-0
1Weather/Info.plist
+10
-0
1Weather/Widget/WidgetManager.swift
+200
-0
OneWeatherAnalytics/OneWeatherAnalytics/AnalyticsEvent.swift
+14
-0
OneWeatherAnalytics/OneWeatherAnalytics/AnalyticsParameter.swift
+1
-0
OneWeatherWidget/Widgets/PrecipitationWidget.swift
+1
-0
OneWeatherWidget/Widgets/TemperatureWidget.swift
+3
-0
OneWeatherWidget/Widgets/WindWidget.swift
+2
-0
PG.playground/Contents.swift
+0
-12
No files found.
1Weather.xcodeproj/project.pbxproj
View file @
3117b368
...
@@ -161,6 +161,7 @@
...
@@ -161,6 +161,7 @@
CDA5542825EF734200A2E08C
/* TodayCellFactory.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CDA5542725EF734200A2E08C
/* TodayCellFactory.swift */
;
};
CDA5542825EF734200A2E08C
/* TodayCellFactory.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CDA5542725EF734200A2E08C
/* TodayCellFactory.swift */
;
};
CDA5542D25EF7C9700A2E08C
/* ReusableCellProtocol.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CDA5542C25EF7C9700A2E08C
/* ReusableCellProtocol.swift */
;
};
CDA5542D25EF7C9700A2E08C
/* ReusableCellProtocol.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CDA5542C25EF7C9700A2E08C
/* ReusableCellProtocol.swift */
;
};
CDAC9B8526319B0500AC1BF4
/* MapTimeControlItem.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CDAC9B8426319B0500AC1BF4
/* MapTimeControlItem.swift */
;
};
CDAC9B8526319B0500AC1BF4
/* MapTimeControlItem.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CDAC9B8426319B0500AC1BF4
/* MapTimeControlItem.swift */
;
};
CDAD462C26A95ED800690CB1
/* WidgetManager.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CDAD462B26A95ED800690CB1
/* WidgetManager.swift */
;
};
CDAD97B1262042B2007FCFB1
/* MapButton.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CDAD97B0262042B2007FCFB1
/* MapButton.swift */
;
};
CDAD97B1262042B2007FCFB1
/* MapButton.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CDAD97B0262042B2007FCFB1
/* MapButton.swift */
;
};
CDAD97B426207D14007FCFB1
/* MapTimeControlView.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CDAD97B326207D14007FCFB1
/* MapTimeControlView.swift */
;
};
CDAD97B426207D14007FCFB1
/* MapTimeControlView.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CDAD97B326207D14007FCFB1
/* MapTimeControlView.swift */
;
};
CDC3F858269460E600AAE3BF
/* PromotionMediumWidgetView.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CDC3F857269460E600AAE3BF
/* PromotionMediumWidgetView.swift */
;
};
CDC3F858269460E600AAE3BF
/* PromotionMediumWidgetView.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CDC3F857269460E600AAE3BF
/* PromotionMediumWidgetView.swift */
;
};
...
@@ -473,6 +474,7 @@
...
@@ -473,6 +474,7 @@
CDA5542725EF734200A2E08C
/* TodayCellFactory.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
TodayCellFactory.swift
;
sourceTree
=
"<group>"
;
};
CDA5542725EF734200A2E08C
/* TodayCellFactory.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
TodayCellFactory.swift
;
sourceTree
=
"<group>"
;
};
CDA5542C25EF7C9700A2E08C
/* ReusableCellProtocol.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
ReusableCellProtocol.swift
;
sourceTree
=
"<group>"
;
};
CDA5542C25EF7C9700A2E08C
/* ReusableCellProtocol.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
ReusableCellProtocol.swift
;
sourceTree
=
"<group>"
;
};
CDAC9B8426319B0500AC1BF4
/* MapTimeControlItem.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
MapTimeControlItem.swift
;
sourceTree
=
"<group>"
;
};
CDAC9B8426319B0500AC1BF4
/* MapTimeControlItem.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
MapTimeControlItem.swift
;
sourceTree
=
"<group>"
;
};
CDAD462B26A95ED800690CB1
/* WidgetManager.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
WidgetManager.swift
;
sourceTree
=
"<group>"
;
};
CDAD97B0262042B2007FCFB1
/* MapButton.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
MapButton.swift
;
sourceTree
=
"<group>"
;
};
CDAD97B0262042B2007FCFB1
/* MapButton.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
MapButton.swift
;
sourceTree
=
"<group>"
;
};
CDAD97B326207D14007FCFB1
/* MapTimeControlView.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
MapTimeControlView.swift
;
sourceTree
=
"<group>"
;
};
CDAD97B326207D14007FCFB1
/* MapTimeControlView.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
MapTimeControlView.swift
;
sourceTree
=
"<group>"
;
};
CDC3F857269460E600AAE3BF
/* PromotionMediumWidgetView.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
PromotionMediumWidgetView.swift
;
sourceTree
=
"<group>"
;
};
CDC3F857269460E600AAE3BF
/* PromotionMediumWidgetView.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
PromotionMediumWidgetView.swift
;
sourceTree
=
"<group>"
;
};
...
@@ -672,6 +674,7 @@
...
@@ -672,6 +674,7 @@
CD1237DA255D5DFA00C98139
/* PG.playground */
,
CD1237DA255D5DFA00C98139
/* PG.playground */
,
87C171E725FF79CC00DA3464
/* Configuration */
,
87C171E725FF79CC00DA3464
/* Configuration */
,
CE9D181425ECB8370028D9D7
/* Common */
,
CE9D181425ECB8370028D9D7
/* Common */
,
CDAD462A26A95EB800690CB1
/* Widget */
,
CEAFF09925DFC78200DF4EBF
/* Network */
,
CEAFF09925DFC78200DF4EBF
/* Network */
,
CEAFF08125DFC66F00DF4EBF
/* Model */
,
CEAFF08125DFC66F00DF4EBF
/* Model */
,
CD647D0025ED07AF0034578B
/* ViewModels */
,
CD647D0025ED07AF0034578B
/* ViewModels */
,
...
@@ -1095,6 +1098,14 @@
...
@@ -1095,6 +1098,14 @@
path
=
Cells
;
path
=
Cells
;
sourceTree
=
"<group>"
;
sourceTree
=
"<group>"
;
};
};
CDAD462A26A95EB800690CB1
/* Widget */
=
{
isa
=
PBXGroup
;
children
=
(
CDAD462B26A95ED800690CB1
/* WidgetManager.swift */
,
);
path
=
Widget
;
sourceTree
=
"<group>"
;
};
CDAD97AF26204285007FCFB1
/* Controls */
=
{
CDAD97AF26204285007FCFB1
/* Controls */
=
{
isa
=
PBXGroup
;
isa
=
PBXGroup
;
children
=
(
children
=
(
...
@@ -1877,6 +1888,7 @@
...
@@ -1877,6 +1888,7 @@
CD82300A25D6B2AF00A05501
/* AppTabBarController.swift in Sources */
,
CD82300A25D6B2AF00A05501
/* AppTabBarController.swift in Sources */
,
CDC6126225E8DAB800188DA7
/* MoonPhaseCell.swift in Sources */
,
CDC6126225E8DAB800188DA7
/* MoonPhaseCell.swift in Sources */
,
CD37D3D6260C93B3002669D6
/* MenuCellFactory.swift in Sources */
,
CD37D3D6260C93B3002669D6
/* MenuCellFactory.swift in Sources */
,
CDAD462C26A95ED800690CB1
/* WidgetManager.swift in Sources */
,
CD8B60AD263819400055CB3F
/* NWSAlertInfoBlockTableViewCell.swift in Sources */
,
CD8B60AD263819400055CB3F
/* NWSAlertInfoBlockTableViewCell.swift in Sources */
,
87D815AC2636D61D0015A6D1
/* NWSAlertViewModel.swift in Sources */
,
87D815AC2636D61D0015A6D1
/* NWSAlertViewModel.swift in Sources */
,
CD37D3FA260DF714002669D6
/* SettingsThemeCell.swift in Sources */
,
CD37D3FA260DF714002669D6
/* SettingsThemeCell.swift in Sources */
,
...
...
1Weather/AppDelegate.swift
View file @
3117b368
...
@@ -127,6 +127,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
...
@@ -127,6 +127,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}
}
func
application
(
_
app
:
UIApplication
,
open
url
:
URL
,
options
:
[
UIApplication
.
OpenURLOptionsKey
:
Any
]
=
[:])
->
Bool
{
func
application
(
_
app
:
UIApplication
,
open
url
:
URL
,
options
:
[
UIApplication
.
OpenURLOptionsKey
:
Any
]
=
[:])
->
Bool
{
//Handle widget deep link
if
#available(iOS 14, *)
{
if
url
.
absoluteString
.
contains
(
"ow-widget"
)
{
WidgetManager
.
shared
.
handle
(
url
)
return
true
}
}
log
.
info
(
"Open URL:
\(
url
)
with options:
\(
options
)
"
)
log
.
info
(
"Open URL:
\(
url
)
with options:
\(
options
)
"
)
let
oneWeatherRouter
=
DeeplinksRouter
()
let
oneWeatherRouter
=
DeeplinksRouter
()
oneWeatherRouter
.
open
(
url
:
url
)
oneWeatherRouter
.
open
(
url
:
url
)
...
@@ -142,6 +150,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
...
@@ -142,6 +150,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func
applicationDidBecomeActive
(
_
application
:
UIApplication
)
{
func
applicationDidBecomeActive
(
_
application
:
UIApplication
)
{
LocationManager
.
shared
.
updateEverythingIfNeeded
()
LocationManager
.
shared
.
updateEverythingIfNeeded
()
if
#available(iOS 14, *)
{
WidgetManager
.
shared
.
update
()
}
}
}
func
application
(
_
application
:
UIApplication
,
didRegisterForRemoteNotificationsWithDeviceToken
deviceToken
:
Data
)
{
func
application
(
_
application
:
UIApplication
,
didRegisterForRemoteNotificationsWithDeviceToken
deviceToken
:
Data
)
{
...
...
1Weather/Info.plist
View file @
3117b368
...
@@ -29,6 +29,16 @@
...
@@ -29,6 +29,16 @@
<
string
>
oneweather
<
/string
>
<
string
>
oneweather
<
/string
>
<
/
a
rr
a
y
>
<
/
a
rr
a
y
>
<
/
d
i
c
t
>
<
/
d
i
c
t
>
<
d
i
c
t
>
<
k
e
y
>
CFBundleTypeRole
<
/k
e
y
>
<
string
>
Editor
<
/string
>
<
k
e
y
>
CFBundleURLName
<
/k
e
y
>
<
string
>
OW-Widget
<
/string
>
<
k
e
y
>
CFBundleURLSchemes
<
/k
e
y
>
<
a
rr
a
y
>
<
string
>
ow-widget
<
/string
>
<
/
a
rr
a
y
>
<
/
d
i
c
t
>
<
/
a
rr
a
y
>
<
/
a
rr
a
y
>
<
k
e
y
>
CFBundleVersion
<
/k
e
y
>
<
k
e
y
>
CFBundleVersion
<
/k
e
y
>
<
string
>
$
(
CURRENT_PROJECT_VERSION
)<
/string
>
<
string
>
$
(
CURRENT_PROJECT_VERSION
)<
/string
>
...
...
1Weather/Widget/WidgetManager.swift
0 → 100644
View file @
3117b368
//
// WidgetManager.swift
// 1Weather
//
// Created by Dmitry Stepanets on 22.07.2021.
//
import
WidgetKit
import
OneWeatherAnalytics
@available(iOS 14, *)
private
struct
WidgetOptions
:
OptionSet
{
let
rawValue
:
Int
static
let
tempuratureSmall
=
WidgetOptions
(
rawValue
:
1
<<
0
)
static
let
tempuratureMedium
=
WidgetOptions
(
rawValue
:
1
<<
1
)
static
let
tempuratureLarge
=
WidgetOptions
(
rawValue
:
1
<<
2
)
static
let
precipitationMedium
=
WidgetOptions
(
rawValue
:
1
<<
3
)
static
let
windMedium
=
WidgetOptions
(
rawValue
:
1
<<
4
)
static
let
windLarge
=
WidgetOptions
(
rawValue
:
1
<<
5
)
static
func
option
(
forKind
kind
:
String
,
family
:
WidgetFamily
)
->
Self
?
{
switch
kind
{
case
"com.onelouder.oneweather.widget.temperature"
:
switch
family
{
case
.
systemSmall
:
return
.
tempuratureSmall
case
.
systemMedium
:
return
.
tempuratureMedium
case
.
systemLarge
:
return
.
tempuratureLarge
default
:
return
nil
}
case
"com.onelouder.oneweather.widget.precipitation"
:
switch
family
{
case
.
systemMedium
:
return
.
precipitationMedium
default
:
return
nil
}
case
"com.onelouder.oneweather.widget.wind"
:
switch
family
{
case
.
systemMedium
:
return
.
windMedium
case
.
systemLarge
:
return
.
windLarge
default
:
return
nil
}
default
:
return
nil
}
}
static
func
option
(
forDeepLink
url
:
URL
)
->
Self
?
{
guard
let
widgetType
=
url
.
host
else
{
return
nil
}
switch
widgetType
{
case
"temperature-small"
:
return
.
tempuratureSmall
case
"temperature-medium"
:
return
.
tempuratureMedium
case
"temperature-large"
:
return
.
tempuratureLarge
case
"precipitation-medium"
:
return
.
precipitationMedium
case
"wind-medium"
:
return
.
windMedium
case
"wind-large"
:
return
.
windLarge
default
:
return
nil
}
}
static
func
name
(
for
option
:
WidgetOptions
)
->
String
{
switch
option
{
case
.
tempuratureSmall
:
return
"small"
case
.
tempuratureMedium
,
.
tempuratureLarge
:
return
"forecast temperature"
case
.
precipitationMedium
:
return
"forecast precipitation"
case
.
windMedium
,
.
windLarge
:
return
"forecast wind"
default
:
return
"n/a"
}
}
}
@available(iOS 14, *)
class
WidgetManager
{
static
let
shared
=
WidgetManager
()
private
init
()
{
//Load stored options
let
storedWidgetsOptions
=
UserDefaults
.
standard
.
integer
(
forKey
:
"widgetOptions"
)
self
.
widgetOptions
=
WidgetOptions
(
rawValue
:
storedWidgetsOptions
)
}
private
let
log
=
Logger
(
componentName
:
"WidgetManager"
)
private
var
widgetOptions
:
WidgetOptions
=
[]
func
update
()
{
WidgetCenter
.
shared
.
getCurrentConfigurations
{[
weak
self
]
result
in
switch
result
{
case
.
success
(
let
widgetInfo
):
self
?
.
sync
(
with
:
widgetInfo
)
case
.
failure
(
let
error
):
self
?
.
log
.
error
(
error
.
localizedDescription
)
}
}
}
func
handle
(
_
deepLink
:
URL
)
{
guard
let
option
=
WidgetOptions
.
option
(
forDeepLink
:
deepLink
)
else
{
return
}
let
name
=
WidgetOptions
.
name
(
for
:
option
)
AppAnalytics
.
shared
.
log
(
event
:
.
ANALYTICS_WIDGET_LAUNCH_FROM
,
params
:
[
.
ANALYTICS_KEY_WIDGET_NAME
:
name
])
}
private
func
sync
(
with
widgetInfo
:
[
WidgetInfo
])
{
var
currentOptions
:
WidgetOptions
=
[]
widgetInfo
.
forEach
{
if
let
option
=
WidgetOptions
.
option
(
forKind
:
$0
.
kind
,
family
:
$0
.
family
)
{
currentOptions
.
insert
(
option
)
}
}
//Add missing options
currentOptions
.
elements
()
.
forEach
{
if
!
widgetOptions
.
contains
(
$0
)
{
widgetOptions
.
insert
(
$0
)
//Analytic add
addToAnalytics
(
option
:
$0
,
isPlaced
:
true
)
}
}
//Remove from saved if needed
widgetOptions
.
elements
()
.
enumerated
()
.
forEach
{
if
!
currentOptions
.
contains
(
$1
)
{
widgetOptions
.
remove
(
$1
)
addToAnalytics
(
option
:
$1
,
isPlaced
:
false
)
}
}
//Save changes
save
(
options
:
widgetOptions
)
}
private
func
addToAnalytics
(
option
:
WidgetOptions
,
isPlaced
:
Bool
)
{
let
name
=
WidgetOptions
.
name
(
for
:
option
)
AppAnalytics
.
shared
.
log
(
event
:
isPlaced
?
.
ANALYTICS_WIDGET_PLACED
:
.
ANALYTICS_WIDGET_REMOVED
,
params
:
[
.
ANALYTICS_KEY_WIDGET_NAME
:
name
])
switch
option
{
case
.
tempuratureSmall
:
AppAnalytics
.
shared
.
log
(
event
:
isPlaced
?
.
ANALYTICS_WIDGET_TEMP_SMALL_PLACE
:
.
ANALYTICS_WIDGET_TEMP_SMALL_REMOVE
)
case
.
tempuratureMedium
,
.
tempuratureLarge
:
AppAnalytics
.
shared
.
log
(
event
:
isPlaced
?
.
ANALYTICS_WIDGET_TEMP_PLACE
:
.
ANALYTICS_WIDGET_TEMP_REMOVE
)
case
.
precipitationMedium
:
AppAnalytics
.
shared
.
log
(
event
:
isPlaced
?
.
ANALYTICS_WIDGET_PRECIP_PLACE
:
.
ANALYTICS_WIDGET_PRECIP_REMOVE
)
case
.
windMedium
,
.
windLarge
:
AppAnalytics
.
shared
.
log
(
event
:
isPlaced
?
.
ANALYTICS_WIDGET_WIND_PLACE
:
.
ANALYTICS_WIDGET_WIND_REMOVE
)
default
:
break
}
}
private
func
save
(
options
:
WidgetOptions
)
{
UserDefaults
.
standard
.
setValue
(
options
.
rawValue
,
forKey
:
"widgetOptions"
)
UserDefaults
.
standard
.
synchronize
()
}
}
private
extension
OptionSet
where
RawValue
:
FixedWidthInteger
{
func
elements
()
->
AnySequence
<
Self
>
{
var
remainingBits
=
rawValue
var
bitMask
:
RawValue
=
1
return
AnySequence
{
return
AnyIterator
{
while
remainingBits
!=
0
{
defer
{
bitMask
=
bitMask
&*
2
}
if
remainingBits
&
bitMask
!=
0
{
remainingBits
=
remainingBits
&
~
bitMask
return
Self
(
rawValue
:
bitMask
)
}
}
return
nil
}
}
}
}
OneWeatherAnalytics/OneWeatherAnalytics/AnalyticsEvent.swift
View file @
3117b368
...
@@ -94,7 +94,21 @@ public enum AnalyticsEvent: String {
...
@@ -94,7 +94,21 @@ public enum AnalyticsEvent: String {
case
ANALYTICS_WIDGET_PROMO_EXPAND
=
"WIDGET_PROMO_EXPAND"
case
ANALYTICS_WIDGET_PROMO_EXPAND
=
"WIDGET_PROMO_EXPAND"
case
ANALYTICS_WIDGET_BOTTOM_SCROLLED
=
"WIDGET_PROMO_BOTTOM_SCROLLED"
case
ANALYTICS_WIDGET_BOTTOM_SCROLLED
=
"WIDGET_PROMO_BOTTOM_SCROLLED"
case
ANALYTICS_WIDGET_PROMO_LEARN_CTA
=
"WIDGET_PROMO_LEARN_CTA"
case
ANALYTICS_WIDGET_PROMO_LEARN_CTA
=
"WIDGET_PROMO_LEARN_CTA"
case
ANALYTICS_WIDGET_LAUNCH_FROM
=
"LAUNCH_FROM_WIDGET"
case
ANALYTICS_WIDGET_PLACED
=
"WIDGET_PLACED"
case
ANALYTICS_WIDGET_REMOVED
=
"WIDGET_REMOVED"
/// When widget is placed to the home screen
case
ANALYTICS_WIDGET_TEMP_SMALL_PLACE
=
"IOS_SMALL_WIDGET_PLACED"
case
ANALYTICS_WIDGET_TEMP_PLACE
=
"IOS_TEMP_FORECAST_WIDGET_PLACED"
case
ANALYTICS_WIDGET_PRECIP_PLACE
=
"IOS_PRECIP_FORECAST_WIDGET_PLACED"
case
ANALYTICS_WIDGET_WIND_PLACE
=
"IOS_WIND_FORECAST_WIDGET_PLACED"
/// When widget has been removed from home screen
case
ANALYTICS_WIDGET_TEMP_SMALL_REMOVE
=
"IOS_SMALL_WIDGET_REMOVED"
case
ANALYTICS_WIDGET_TEMP_REMOVE
=
"IOS_TEMP_FORECAST_WIDGET_REMOVED"
case
ANALYTICS_WIDGET_PRECIP_REMOVE
=
"IOS_PRECIP_FORECAST_WIDGET_REMOVED"
case
ANALYTICS_WIDGET_WIND_REMOVE
=
"IOS_WIND_FORECAST_WIDGET_REMOVED"
/// FTUE Funnel: User has saved his first city after installing the app.
/// FTUE Funnel: User has saved his first city after installing the app.
case
ANALYTICS_USER_QUALIFIED
=
"USER_QUALIFIED"
case
ANALYTICS_USER_QUALIFIED
=
"USER_QUALIFIED"
...
...
OneWeatherAnalytics/OneWeatherAnalytics/AnalyticsParameter.swift
View file @
3117b368
...
@@ -21,4 +21,5 @@ public enum AnalyticsParameter: String {
...
@@ -21,4 +21,5 @@ public enum AnalyticsParameter: String {
case
ANALYTICS_KEY_PUSH_NOTIFICATION_SOURCE
=
"source"
case
ANALYTICS_KEY_PUSH_NOTIFICATION_SOURCE
=
"source"
case
ANALYTICS_KEY_THEME_CHANGE_NAME
=
"themeName"
case
ANALYTICS_KEY_THEME_CHANGE_NAME
=
"themeName"
case
ANALYTICS_KEY_FIST_OPEN_SOURCE
=
"Source"
case
ANALYTICS_KEY_FIST_OPEN_SOURCE
=
"Source"
case
ANALYTICS_KEY_WIDGET_NAME
=
"widget_name"
}
}
OneWeatherWidget/Widgets/PrecipitationWidget.swift
View file @
3117b368
...
@@ -20,6 +20,7 @@ struct PrecipitationWidget: Widget {
...
@@ -20,6 +20,7 @@ struct PrecipitationWidget: Widget {
provider
:
WeatherProvider
()
provider
:
WeatherProvider
()
)
{
weatherEntry
in
)
{
weatherEntry
in
MediumPrecipitationWidgetView
(
widgetViewModel
:
ForecastWidgetViewModel
(
location
:
weatherEntry
.
location
))
MediumPrecipitationWidgetView
(
widgetViewModel
:
ForecastWidgetViewModel
(
location
:
weatherEntry
.
location
))
.
widgetURL
(
URL
(
string
:
"ow-widget://precipitation-medium"
))
}
}
.
configurationDisplayName
(
"widget.precipitation.title"
.
localized
())
.
configurationDisplayName
(
"widget.precipitation.title"
.
localized
())
.
description
(
"widget.precipitation.description"
.
localized
())
.
description
(
"widget.precipitation.description"
.
localized
())
...
...
OneWeatherWidget/Widgets/TemperatureWidget.swift
View file @
3117b368
...
@@ -37,10 +37,13 @@ private struct WidgetView: View {
...
@@ -37,10 +37,13 @@ private struct WidgetView: View {
switch
widgetSize
{
switch
widgetSize
{
case
.
systemSmall
:
case
.
systemSmall
:
SmallTemperatureWidgetView
(
widgetViewModel
:
viewModel
)
SmallTemperatureWidgetView
(
widgetViewModel
:
viewModel
)
.
widgetURL
(
URL
(
string
:
"ow-widget://temperature-small"
))
case
.
systemMedium
:
case
.
systemMedium
:
MediumTemperatureWidgetView
(
widgetViewModel
:
viewModel
)
MediumTemperatureWidgetView
(
widgetViewModel
:
viewModel
)
.
widgetURL
(
URL
(
string
:
"ow-widget://temperature-medium"
))
case
.
systemLarge
:
case
.
systemLarge
:
LargeTemperatureWidgetView
(
widgetViewModel
:
viewModel
)
LargeTemperatureWidgetView
(
widgetViewModel
:
viewModel
)
.
widgetURL
(
URL
(
string
:
"ow-widget://temperature-large"
))
@unknown
default
:
@unknown
default
:
SmallTemperatureWidgetView
(
widgetViewModel
:
viewModel
)
SmallTemperatureWidgetView
(
widgetViewModel
:
viewModel
)
}
}
...
...
OneWeatherWidget/Widgets/WindWidget.swift
View file @
3117b368
...
@@ -37,8 +37,10 @@ private struct WidgetView: View {
...
@@ -37,8 +37,10 @@ private struct WidgetView: View {
switch
widgetSize
{
switch
widgetSize
{
case
.
systemMedium
:
case
.
systemMedium
:
MediumWindWidgetView
(
widgetViewModel
:
viewModel
)
MediumWindWidgetView
(
widgetViewModel
:
viewModel
)
.
widgetURL
(
URL
(
string
:
"ow-widget://wind-medium"
))
case
.
systemLarge
:
case
.
systemLarge
:
LargeWindWidgetView
(
widgetViewModel
:
viewModel
)
LargeWindWidgetView
(
widgetViewModel
:
viewModel
)
.
widgetURL
(
URL
(
string
:
"ow-widget://wind-large"
))
default
:
default
:
MediumWindWidgetView
(
widgetViewModel
:
viewModel
)
MediumWindWidgetView
(
widgetViewModel
:
viewModel
)
}
}
...
...
PG.playground/Contents.swift
View file @
3117b368
import
Foundation
import
Foundation
import
UIKit
import
UIKit
var
arr
=
[
3
,
0
,
6
,
22
,
55
,
45
,
232
,
534
,
1
,
7
,
9
,
10
]
let
maxValues
=
6
let
steps
=
(
arr
.
count
-
1
)
/
(
maxValues
-
1
)
var
result
=
[
Int
]()
for
index
in
0
..<
maxValues
{
print
(
"Fraction:
\(
index
*
steps
)
"
)
result
.
append
(
arr
[
index
*
steps
])
}
print
(
"Orig:
\(
arr
)
"
)
print
(
"Result:
\(
result
)
"
)
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