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
5c505122
Commit
5c505122
authored
Jun 18, 2021
by
Dmitriy Stepanets
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Finished Shorts UI & UX
parent
0c145ad0
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
149 additions
and
44 deletions
+149
-44
1Weather.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/xcschememanagement.plist
+1
-1
1Weather/Coordinators/AppCoordinator.swift
+12
-0
1Weather/Coordinators/ShortsCoordinator.swift
+8
-3
1Weather/Network/ShortsManager.swift
+9
-13
1Weather/UI/View controllers/Shorts/ShortsViewController.swift
+31
-9
1Weather/UI/View controllers/Today/Cells/TodayCellFactory.swift
+9
-1
1Weather/UI/View controllers/Today/Cells/TodayShortsCell.swift
+17
-2
1Weather/UI/View controllers/Today/Shorts/ShortsView.swift
+15
-3
1Weather/ViewModels/ShortsViewModel.swift
+4
-2
1Weather/ViewModels/TodayViewModel.swift
+4
-0
PG.playground/Contents.swift
+39
-10
No files found.
1Weather.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/xcschememanagement.plist
View file @
5c505122
...
...
@@ -12,7 +12,7 @@
<
k
e
y
>
OneWeatherNotificationServiceExtension.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
6
3
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
6
0
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
PG
(
Playground
)
1.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
1Weather/Coordinators/AppCoordinator.swift
View file @
5c505122
...
...
@@ -78,6 +78,18 @@ class AppCoordinator: Coordinator {
tabBarController
.
selectedIndex
=
AppTabBarController
.
AppTab
.
radar
.
rawValue
}
public
func
openShorts
(
atIndex
index
:
Int
)
{
guard
ShortsManager
.
shared
.
shortsAvailable
,
let
shortsCoordinator
=
(
childCoordinators
.
first
{
$0
is
ShortsCoordinator
}
as?
ShortsCoordinator
)
else
{
return
}
shortsCoordinator
.
setIndexToScroll
(
shortIndex
:
index
)
tabBarController
.
selectedIndex
=
AppTabBarController
.
AppTab
.
shorts
.
rawValue
}
public
func
openNotifications
()
{
let
notificationsCoordinator
=
NotificationsCoordinator
(
parentViewController
:
tabBarController
)
notificationsCoordinator
.
parentCoordinator
=
self
...
...
1Weather/Coordinators/ShortsCoordinator.swift
View file @
5c505122
...
...
@@ -9,7 +9,10 @@ import UIKit
class
ShortsCoordinator
:
Coordinator
{
//Private
private
var
tabBarController
:
UITabBarController
private
var
tabBarController
:
UITabBarController
private
lazy
var
shortsViewController
:
ShortsViewController
=
{
return
ShortsViewController
(
coordinator
:
self
)
}()
//Public
var
childCoordinators
=
[
Coordinator
]()
...
...
@@ -21,15 +24,17 @@ class ShortsCoordinator: Coordinator {
}
func
start
()
{
let
shortsViewController
=
ShortsViewController
(
coordinator
:
self
)
tabBarController
.
add
(
viewController
:
shortsViewController
)
}
func
start
(
withIndex
index
:
Int
)
{
let
shortsViewController
=
ShortsViewController
(
coordinator
:
self
)
tabBarController
.
add
(
viewController
:
shortsViewController
,
atIndex
:
index
)
}
func
setIndexToScroll
(
shortIndex
index
:
Int
)
{
shortsViewController
.
set
(
indexToScroll
:
index
)
}
func
viewControllerDidEnd
(
controller
:
UIViewController
)
{
parentCoordinator
?
.
childDidFinish
(
child
:
self
)
}
...
...
1Weather/Network/ShortsManager.swift
View file @
5c505122
...
...
@@ -5,7 +5,7 @@
// Created by Dmitry Stepanets on 08.06.2021.
//
import
Foundation
import
UIKit
import
OneWeatherCore
import
InMobiShortsSource
import
OneWeatherAnalytics
...
...
@@ -20,7 +20,7 @@ class ShortsManager {
let
multicastDelegate
=
MulticastDelegate
<
ShortsManagerDelegate
>
()
private(set)
var
shorts
=
[
ShortsItem
]()
var
shortsAvailable
:
Bool
{
return
LocationManager
.
shared
.
selectedLocation
?
.
countryCode
==
"US"
return
LocationManager
.
shared
.
selectedLocation
?
.
countryCode
==
"US"
&&
UIDevice
.
current
.
userInterfaceIdiom
==
.
phone
}
//Private
...
...
@@ -60,16 +60,7 @@ class ShortsManager {
}
func
reordering
()
{
var
reorderingArray
=
self
.
shorts
var
itemsToReorder
=
[
ShortsItem
]()
self
.
shorts
.
enumerated
()
.
forEach
{
if
$1
.
isViewed
{
itemsToReorder
.
append
(
reorderingArray
.
remove
(
at
:
$0
))
}
}
reorderingArray
.
append
(
contentsOf
:
itemsToReorder
)
self
.
shorts
=
reorderingArray
shorts
=
shorts
.
filter
{
!
$0
.
isViewed
}
+
shorts
.
filter
{
$0
.
isViewed
}
self
.
multicastDelegate
.
invoke
{
delegate
in
delegate
.
shortsDidChange
()
...
...
@@ -84,9 +75,14 @@ class ShortsManager {
}
func
markAsViewed
(
item
:
ShortsItem
)
{
guard
let
sourceIndex
=
(
self
.
shorts
.
firstIndex
{
$0
.
id
==
item
.
id
})
else
{
guard
!
item
.
isViewed
,
let
sourceIndex
=
(
self
.
shorts
.
firstIndex
{
$0
.
id
==
item
.
id
})
else
{
return
}
print
(
"[ShortsManager] Mark short as viewed at index:
\(
sourceIndex
)
"
)
self
.
shorts
[
sourceIndex
]
.
markAsViewed
()
}
}
1Weather/UI/View controllers/Shorts/ShortsViewController.swift
View file @
5c505122
...
...
@@ -22,7 +22,7 @@ class ShortsViewController: UIViewController {
private
let
tableView
=
UITableView
()
private
var
averageColorCache
=
[
AnyHashable
:
UIColor
]()
private
var
lastOffset
:
CGFloat
=
0
private
var
visibleRow
=
0
private
var
itemIndexToScroll
:
Int
?
deinit
{
print
(
"[ShortsViewController] deinit"
)
...
...
@@ -45,9 +45,31 @@ class ShortsViewController: UIViewController {
prepareTableView
()
}
override
func
viewWillAppear
(
_
animated
:
Bool
)
{
super
.
viewWillAppear
(
animated
)
if
let
indexToScroll
=
itemIndexToScroll
{
tableView
.
scrollToRow
(
at
:
[
0
,
indexToScroll
],
at
:
.
top
,
animated
:
false
)
lastOffset
=
tableView
.
contentOffset
.
y
itemIndexToScroll
=
nil
viewModel
.
markAsViewed
(
atIndex
:
indexToScroll
)
}
else
{
lastOffset
=
0
tableView
.
scrollToRow
(
at
:
[
0
,
0
],
at
:
.
top
,
animated
:
false
)
}
}
override
func
viewDidAppear
(
_
animated
:
Bool
)
{
super
.
viewDidAppear
(
animated
)
if
lastOffset
==
0
{
viewModel
.
markAsViewed
(
atIndex
:
0
)
}
}
override
func
viewWillDisappear
(
_
animated
:
Bool
)
{
super
.
viewWillDisappear
(
animated
)
print
(
"[ShortsViewController] Will disappear"
)
ShortsManager
.
shared
.
reordering
(
)
}
private
func
scrollTo
(
newOffset
:
CGPoint
,
velocity
:
CGPoint
)
{
...
...
@@ -56,11 +78,12 @@ class ShortsViewController: UIViewController {
animation
?
.
duration
=
0.4
animation
?
.
toValue
=
newOffset
animation
?
.
fromValue
=
tableView
.
contentOffset
print
(
"[ShortsViewController] diff:
\(
abs
(
tableView
.
contentOffset
.
y
)
/
newOffset
.
y
)
"
)
tableView
.
pop_add
(
animation
,
forKey
:
kAnimationKey
)
}
func
set
(
indexToScroll
:
Int
)
{
itemIndexToScroll
=
indexToScroll
}
}
//MARK:- Prepare
...
...
@@ -105,10 +128,6 @@ extension ShortsViewController: UITableViewDelegate {
return
tableView
.
bounds
.
height
}
func
tableView
(
_
tableView
:
UITableView
,
didEndDisplaying
cell
:
UITableViewCell
,
forRowAt
indexPath
:
IndexPath
)
{
viewModel
.
markAsViewed
(
item
:
viewModel
.
shorts
[
indexPath
.
row
])
}
func
scrollViewWillEndDragging
(
_
scrollView
:
UIScrollView
,
withVelocity
velocity
:
CGPoint
,
targetContentOffset
:
UnsafeMutablePointer
<
CGPoint
>
)
{
//Get direction
let
direction
:
ScrollDirection
...
...
@@ -144,6 +163,7 @@ extension ShortsViewController: UITableViewDelegate {
//Check for the last row
if
nextRowIndexPath
.
row
==
rowsCount
-
1
{
viewModel
.
markAsViewed
(
atIndex
:
nextRowIndexPath
.
row
)
let
offset
=
tableView
.
contentSize
.
height
-
tableView
.
frame
.
height
self
.
scrollTo
(
newOffset
:
.
init
(
x
:
tableView
.
contentOffset
.
x
,
y
:
offset
),
velocity
:
velocity
)
return
...
...
@@ -151,6 +171,7 @@ extension ShortsViewController: UITableViewDelegate {
case
.
toTop
:
if
topRowIndexPath
.
row
==
0
{
self
.
scrollTo
(
newOffset
:
.
zero
,
velocity
:
velocity
)
viewModel
.
markAsViewed
(
atIndex
:
0
)
return
}
...
...
@@ -158,6 +179,7 @@ extension ShortsViewController: UITableViewDelegate {
}
let
nextRowRect
=
tableView
.
rectForRow
(
at
:
nextRowIndexPath
)
viewModel
.
markAsViewed
(
atIndex
:
nextRowIndexPath
.
row
)
self
.
scrollTo
(
newOffset
:
nextRowRect
.
origin
,
velocity
:
velocity
)
}
...
...
1Weather/UI/View controllers/Today/Cells/TodayCellFactory.swift
View file @
5c505122
...
...
@@ -125,7 +125,8 @@ class TodayCellFactory: CellFactoryProtocol {
return
cell
case
.
shorts
:
let
cell
=
dequeueReusableCell
(
type
:
TodayShortsCell
.
self
,
tableView
:
tableView
,
indexPath
:
indexPath
)
cell
.
configure
(
shorts
:
todayViewModel
.
shorts
)
cell
.
delegate
=
self
cell
.
reload
()
return
cell
case
.
conditions
:
let
cell
=
dequeueReusableCell
(
type
:
TodayConditionsCell
.
self
,
tableView
:
tableView
,
indexPath
:
indexPath
)
...
...
@@ -224,3 +225,10 @@ class TodayCellFactory: CellFactoryProtocol {
todaySection
.
hiddenRows
=
rowsToHide
}
}
//MARK:- TodayShortsCell Delegate
extension
TodayCellFactory
:
TodayShortsCellDelegate
{
func
didSelectShort
(
atIndex
index
:
Int
)
{
todayViewModel
.
openShorts
(
atIndex
:
index
)
}
}
1Weather/UI/View controllers/Today/Cells/TodayShortsCell.swift
View file @
5c505122
...
...
@@ -8,11 +8,18 @@
import
UIKit
import
OneWeatherCore
protocol
TodayShortsCellDelegate
:
AnyObject
{
func
didSelectShort
(
atIndex
index
:
Int
)
}
class
TodayShortsCell
:
UITableViewCell
{
//Private
private
let
headingLabel
=
UILabel
()
private
let
shortsView
=
ShortsView
()
//Public
weak
var
delegate
:
TodayShortsCellDelegate
?
override
init
(
style
:
UITableViewCell
.
CellStyle
,
reuseIdentifier
:
String
?)
{
super
.
init
(
style
:
style
,
reuseIdentifier
:
reuseIdentifier
)
...
...
@@ -30,8 +37,8 @@ class TodayShortsCell: UITableViewCell {
updateUI
()
}
func
configure
(
shorts
:[
ShortsItem
]
)
{
self
.
shortsView
.
configure
(
shorts
:
shorts
)
func
reload
(
)
{
self
.
shortsView
.
reload
(
)
}
private
func
updateUI
()
{
...
...
@@ -60,6 +67,7 @@ private extension TodayShortsCell {
}
func
prepareShortsView
()
{
shortsView
.
delegate
=
self
contentView
.
addSubview
(
shortsView
)
shortsView
.
snp
.
makeConstraints
{
make
in
...
...
@@ -69,3 +77,10 @@ private extension TodayShortsCell {
}
}
}
//MARK:- ShortsView Delegate
extension
TodayShortsCell
:
ShortsViewDelegate
{
func
didSelectShort
(
at
index
:
Int
)
{
delegate
?
.
didSelectShort
(
atIndex
:
index
)
}
}
1Weather/UI/View controllers/Today/Shorts/ShortsView.swift
View file @
5c505122
...
...
@@ -8,13 +8,22 @@
import
UIKit
import
OneWeatherCore
protocol
ShortsViewDelegate
:
AnyObject
{
func
didSelectShort
(
at
index
:
Int
)
}
class
ShortsView
:
UIView
{
//Private
private
let
headingLabel
=
UILabel
()
private
let
collectionView
=
UICollectionView
(
frame
:
.
zero
,
collectionViewLayout
:
ShortsCollectionViewLayout
())
private
var
shorts
=
[
ShortsItem
]()
private
var
shorts
:
[
ShortsItem
]
{
return
ShortsManager
.
shared
.
shorts
}
private
var
averageColorCache
=
[
AnyHashable
:
UIColor
]()
//Public
weak
var
delegate
:
ShortsViewDelegate
?
init
()
{
super
.
init
(
frame
:
.
zero
)
...
...
@@ -25,8 +34,7 @@ class ShortsView: UIView {
fatalError
(
"init(coder:) has not been implemented"
)
}
func
configure
(
shorts
:[
ShortsItem
])
{
self
.
shorts
=
shorts
func
reload
()
{
onMain
{
self
.
collectionView
.
reloadData
()
}
...
...
@@ -78,6 +86,10 @@ extension ShortsView: UICollectionViewDelegate {
(
cell
as?
ShortsCollectionViewCell
)?
.
stopZoomAnimation
()
}
}
func
collectionView
(
_
collectionView
:
UICollectionView
,
didSelectItemAt
indexPath
:
IndexPath
)
{
delegate
?
.
didSelectShort
(
at
:
indexPath
.
row
)
}
}
//MARK:- ShortsCollectionCell Delegate
...
...
1Weather/ViewModels/ShortsViewModel.swift
View file @
5c505122
...
...
@@ -39,8 +39,10 @@ class ShortsViewModel: ViewModelProtocol {
}
}
func
markAsViewed
(
item
:
ShortsItem
)
{
shortsManager
.
markAsViewed
(
item
:
item
)
func
markAsViewed
(
atIndex
index
:
Int
)
{
guard
index
<
shorts
.
count
else
{
return
}
print
(
"[ShortsViewModel mark as viewed
\(
shorts
[
index
]
.
title
)
]"
)
shortsManager
.
markAsViewed
(
item
:
shorts
[
index
])
}
}
...
...
1Weather/ViewModels/TodayViewModel.swift
View file @
5c505122
...
...
@@ -112,6 +112,10 @@ class TodayViewModel: ViewModelProtocol {
}
}
public
func
openShorts
(
atIndex
index
:
Int
)
{
AppCoordinator
.
instance
.
openShorts
(
atIndex
:
index
)
}
private
func
onboardingFlowCompleted
()
{
self
.
initializeAllAdsIfNeeded
()
PushNotificationsManager
.
shared
.
registerForRemoteNotifications
()
...
...
PG.playground/Contents.swift
View file @
5c505122
import
Foundation
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
])
extension
Array
{
mutating
func
move
(
from
oldIndex
:
Index
,
to
newIndex
:
Index
)
{
// Don't work for free and use swap when indices are next to each other - this
// won't rebuild array and will be super efficient.
if
oldIndex
==
newIndex
{
return
}
if
abs
(
newIndex
-
oldIndex
)
==
1
{
return
self
.
swapAt
(
oldIndex
,
newIndex
)
}
self
.
insert
(
self
.
remove
(
at
:
oldIndex
),
at
:
newIndex
)
}
}
print
(
"Orig:
\(
arr
)
"
)
print
(
"Result:
\(
result
)
"
)
struct
Element
{
let
isViewed
:
Bool
let
value
:
String
}
var
arr
:[
Element
]
=
[
.
init
(
isViewed
:
true
,
value
:
"a"
),
.
init
(
isViewed
:
true
,
value
:
"b"
),
.
init
(
isViewed
:
true
,
value
:
"c"
),
.
init
(
isViewed
:
false
,
value
:
"d"
),
.
init
(
isViewed
:
false
,
value
:
"e"
),
.
init
(
isViewed
:
false
,
value
:
"f"
),
.
init
(
isViewed
:
false
,
value
:
"g"
),
.
init
(
isViewed
:
false
,
value
:
"h"
),
.
init
(
isViewed
:
false
,
value
:
"i"
)]
var
indexesToReorder
=
[
Int
]()
for
(
index
,
element
)
in
arr
.
enumerated
()
{
if
element
.
isViewed
{
indexesToReorder
.
append
(
index
)
}
}
arr
=
arr
.
filter
{
!
$0
.
isViewed
}
+
arr
.
filter
{
$0
.
isViewed
}
//for index in indexesToReorder {
// arr.move(from: index, to: arr.count - 1)
//}
print
(
arr
.
map
{
$0
.
value
})
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