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
c73871a6
Commit
c73871a6
authored
Aug 04, 2021
by
Dmitriy Stepanets
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
IOS-147: Added new average color calculating logic grabbed from android Palette
parent
d0837650
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
97 additions
and
49 deletions
+97
-49
1Weather.xcworkspace/xcuserdata/dstepanets.xcuserdatad/xcschemes/xcschememanagement.plist
+30
-30
1Weather/Extensions/UIImage+AverageColor.swift
+10
-10
1Weather/Network/ShortsManager.swift
+28
-0
1Weather/UI/View controllers/Today/Shorts/ShortsCollectionViewCell.swift
+29
-9
No files found.
1Weather.xcworkspace/xcuserdata/dstepanets.xcuserdatad/xcschemes/xcschememanagement.plist
View file @
c73871a6
...
...
@@ -23,56 +23,56 @@
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
4
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
3
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
OneWeatherCorePlayground
(
Playground
)
1.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
6
7
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
6
4
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
OneWeatherCorePlayground
(
Playground
)
10.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
2
1
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
2
3
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
OneWeatherCorePlayground
(
Playground
)
11.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
2
2
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
2
4
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
OneWeatherCorePlayground
(
Playground
)
12.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
2
3
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
2
5
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
OneWeatherCorePlayground
(
Playground
)
13.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
30
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
93
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
OneWeatherCorePlayground
(
Playground
)
14.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
31
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
94
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
OneWeatherCorePlayground
(
Playground
)
15.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
32
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
95
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
OneWeatherCorePlayground
(
Playground
)
16.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -100,63 +100,63 @@
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
6
8
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
6
5
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
OneWeatherCorePlayground
(
Playground
)
3.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
6
9
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
6
6
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
OneWeatherCorePlayground
(
Playground
)
4.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
65
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
11
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
OneWeatherCorePlayground
(
Playground
)
5.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
66
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
12
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
OneWeatherCorePlayground
(
Playground
)
6.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
67
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
13
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
OneWeatherCorePlayground
(
Playground
)
7.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
1
8
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
1
7
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
OneWeatherCorePlayground
(
Playground
)
8.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
1
9
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
1
8
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
OneWeatherCorePlayground
(
Playground
)
9.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
20
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
19
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
OneWeatherCorePlayground
(
Playground
)
.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
2
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
4
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
PG
(
Playground
)
1.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -170,42 +170,42 @@
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
2
4
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
2
6
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
PG
(
Playground
)
11.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
2
5
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
2
7
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
PG
(
Playground
)
12.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
2
6
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
2
8
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
PG
(
Playground
)
13.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
27
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
89
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
PG
(
Playground
)
14.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
28
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
90
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
PG
(
Playground
)
15.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
29
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
91
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
PG
(
Playground
)
16.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -247,49 +247,49 @@
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
70
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
14
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
PG
(
Playground
)
5.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
71
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
15
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
PG
(
Playground
)
6.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
72
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
16
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
PG
(
Playground
)
7.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
15
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
20
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
PG
(
Playground
)
8.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
16
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
21
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
PG
(
Playground
)
9.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
17
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
22
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
PG
(
Playground
)
.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
3
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
2
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
/
d
i
c
t
>
<
/
d
i
c
t
>
...
...
1Weather/Extensions/UIImage+AverageColor.swift
View file @
c73871a6
...
...
@@ -6,19 +6,19 @@
//
import
UIKit
import
Palette
extension
UIImage
{
var
averageColor
:
UIColor
?
{
guard
let
inputImage
=
CIImage
(
image
:
self
)
else
{
return
nil
}
let
extentVector
=
CIVector
(
x
:
inputImage
.
extent
.
origin
.
x
,
y
:
inputImage
.
extent
.
origin
.
y
,
z
:
inputImage
.
extent
.
size
.
width
,
w
:
inputImage
.
extent
.
size
.
height
)
guard
let
filter
=
CIFilter
(
name
:
"CIAreaAverage"
,
parameters
:
[
kCIInputImageKey
:
inputImage
,
kCIInputExtentKey
:
extentVector
])
else
{
return
nil
}
guard
let
outputImage
=
filter
.
outputImage
else
{
return
nil
}
var
bitmap
=
[
UInt8
](
repeating
:
0
,
count
:
4
)
let
context
=
CIContext
(
options
:
[
.
workingColorSpace
:
kCFNull
!
])
context
.
render
(
outputImage
,
toBitmap
:
&
bitmap
,
rowBytes
:
4
,
bounds
:
CGRect
(
x
:
0
,
y
:
0
,
width
:
1
,
height
:
1
),
format
:
.
RGBA8
,
colorSpace
:
nil
)
let
palette
=
self
.
createPalette
()
var
vibrantSwatch
=
palette
.
mutedSwatch
if
nil
==
vibrantSwatch
{
vibrantSwatch
=
palette
.
darkMutedSwatch
}
if
nil
==
vibrantSwatch
{
vibrantSwatch
=
palette
.
lightMutedSwatch
}
return
UIColor
(
red
:
CGFloat
(
bitmap
[
0
])
/
255
,
green
:
CGFloat
(
bitmap
[
1
])
/
255
,
blue
:
CGFloat
(
bitmap
[
2
])
/
255
,
alpha
:
CGFloat
(
bitmap
[
3
])
/
255
)
return
vibrantSwatch
?
.
color
}
}
1Weather/Network/ShortsManager.swift
View file @
c73871a6
...
...
@@ -9,6 +9,7 @@ import UIKit
import
OneWeatherCore
import
InMobiShortsSource
import
OneWeatherAnalytics
import
Nuke
protocol
ShortsManagerDelegate
:
AnyObject
{
func
shortsDidChange
()
...
...
@@ -24,6 +25,8 @@ class ShortsManager {
}
//Private
private
let
avgColorQueue
=
OperationQueue
()
private
let
colorCache
=
NSCache
<
NSString
,
UIColor
>
()
private
let
source
=
InMobiShortSource
()
private
let
log
=
Logger
(
componentName
:
"ShortsManager"
)
private
var
isUpdating
=
false
...
...
@@ -84,4 +87,29 @@ class ShortsManager {
self
.
shorts
[
sourceIndex
]
.
markAsViewed
()
}
func
backgroundColor
(
for
short
:
ShortsItem
,
shortImage
:
UIImage
,
completion
:
@escaping(_ color: UIColor?,_ shortId: String)
->
Void
)
{
if
let
cachedColor
=
colorCache
.
object
(
forKey
:
short
.
id
as
NSString
)
{
completion
(
cachedColor
,
short
.
id
)
return
}
avgColorQueue
.
addOperation
{
guard
let
color
=
shortImage
.
averageColor
else
{
completion
(
nil
,
short
.
id
)
return
}
self
.
colorCache
.
setObject
(
color
,
forKey
:
short
.
id
as
NSString
)
completion
(
color
,
short
.
id
)
}
// shortImage.averageColor { avgColor in
// guard let color = avgColor else {
// completion(nil)
// return
// }
// self.colorCache.setObject(color, forKey: short.id as NSString)
// completion(color)
// }
}
}
1Weather/UI/View controllers/Today/Shorts/ShortsCollectionViewCell.swift
View file @
c73871a6
...
...
@@ -18,6 +18,7 @@ class ShortsCollectionViewCell: UICollectionViewCell {
private
let
imageView
=
UIImageView
()
private
let
footerView
=
UIView
()
private
let
footerLabel
=
UILabel
()
private
var
currentShortId
:
String
?
//Public
weak
var
delegate
:
ShortsCollectionCellDelegate
?
...
...
@@ -31,30 +32,48 @@ class ShortsCollectionViewCell: UICollectionViewCell {
}
func
configure
(
shortsItem
:
ShortsItem
)
{
self
.
currentShortId
=
shortsItem
.
id
footerLabel
.
text
=
shortsItem
.
title
if
let
image
=
self
.
bestImageForCellSize
(
images
:
shortsItem
.
images
)
{
let
resizeOptions
=
ImageProcessors
.
Resize
(
size
:
self
.
bounds
.
size
,
crop
:
true
)
let
cornerRadius
=
ImageProcessors
.
RoundedCorners
(
radius
:
12
)
let
imageRequest
=
ImageRequest
(
url
:
image
.
url
,
processors
:
[
resizeOptions
,
cornerRadius
])
Nuke
.
loadImage
(
with
:
imageRequest
,
into
:
imageView
)
{[
weak
self
]
result
in
ImagePipeline
.
shared
.
loadImage
(
with
:
imageRequest
)
{
result
in
switch
result
{
case
.
success
(
let
imageR
esponse
):
onMain
{
self
?
.
imageView
.
image
=
imageResponse
.
image
case
.
success
(
let
r
esponse
):
ShortsManager
.
shared
.
backgroundColor
(
for
:
shortsItem
,
shortImage
:
response
.
image
)
{[
weak
self
]
avgColor
,
shortId
in
guard
self
?
.
currentShortId
==
shortId
else
{
return
}
if
let
cachedColor
=
self
?
.
delegate
?
.
averageColor
(
forImage
:
imageResponse
.
image
,
identifier
:
image
.
url
.
absoluteString
)
{
self
?
.
footerView
.
backgroundColor
=
cachedColor
onMain
{
if
let
color
=
avgColor
{
self
?
.
imageView
.
image
=
response
.
image
self
?
.
footerView
.
backgroundColor
=
color
}
else
{
self
?
.
footerView
.
backgroundColor
=
ThemeManager
.
currentTheme
.
containerBackgroundColor
}
}
default
:
break
}
}
// Nuke.loadImage(with: imageRequest, into: imageView) {[weak self] result in
// switch result {
// case .success(let imageResponse):
// ShortsManager.shared.backgroundColor(for: shortsItem, shortImage: imageResponse.image) { avgColor, shortId in
// guard self?.currentShortId == shortId else { return }
//
// onMain {
// if let color = avgColor {
// self?.footerView.backgroundColor = color
// }
// }
// }
// default:
// break
// }
// }
}
else
{
imageView
.
image
=
nil
...
...
@@ -68,6 +87,7 @@ class ShortsCollectionViewCell: UICollectionViewCell {
override
func
prepareForReuse
()
{
super
.
prepareForReuse
()
self
.
imageView
.
image
=
nil
self
.
footerView
.
backgroundColor
=
.
clear
}
...
...
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