Commit 071d0b05 by Dmitriy Stepanets

Replaced shorts custom layouting to displaying image only

parent 5da64703
No preview for this file type
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
<key>OneWeatherNotificationServiceExtension.xcscheme_^#shared#^_</key> <key>OneWeatherNotificationServiceExtension.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>67</integer> <integer>64</integer>
</dict> </dict>
<key>PG (Playground) 1.xcscheme</key> <key>PG (Playground) 1.xcscheme</key>
<dict> <dict>
......
...@@ -10,17 +10,36 @@ import OneWeatherCore ...@@ -10,17 +10,36 @@ import OneWeatherCore
import InMobiShortsSource import InMobiShortsSource
import OneWeatherAnalytics import OneWeatherAnalytics
protocol ShortsManagerDelegate: AnyObject {
func shortsDidChange()
}
class ShortsManager { class ShortsManager {
//Public
static let shared = ShortsManager() static let shared = ShortsManager()
let multicastDelegate = MulticastDelegate<ShortsManagerDelegate>()
private(set) var shorts = [ShortsItem]()
//Private
private let source = InMobiShortSource() private let source = InMobiShortSource()
private let log = Logger(componentName: "ShortsManager") private let log = Logger(componentName: "ShortsManager")
private var isUpdating = false
private init() {} private init() {}
func fetchShorts(completion:@escaping (_ result: Result<[ShortsItem], Error>) -> Void) {
func refreshShorts() {
if isUpdating {
return
}
isUpdating = true
source.updateShorts {[weak self] shortItems, error in source.updateShorts {[weak self] shortItems, error in
defer {
self?.isUpdating = false
}
guard error == nil else { guard error == nil else {
self?.log.debug("Failed to update shorts \(String(describing: error?.localizedDescription))") self?.log.debug("Failed to update shorts \(String(describing: error?.localizedDescription))")
completion(.failure(error!))
return return
} }
...@@ -29,7 +48,18 @@ class ShortsManager { ...@@ -29,7 +48,18 @@ class ShortsManager {
return return
} }
completion(.success(items)) self?.shorts.removeAll()
self?.shorts.append(contentsOf: items)
self?.multicastDelegate.invoke(invocation: { delegate in
delegate.shortsDidChange()
})
}
}
func like(item: ShortsItem) {
guard let shortsToLikeIndex = (shorts.firstIndex { $0.id == item.id }) else {
return
} }
self.shorts[shortsToLikeIndex].like()
} }
} }
{
"images" : [
{
"filename" : "like_filled.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}
{
"images" : [
{
"filename" : "like_ouline.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}
...@@ -9,38 +9,6 @@ import UIKit ...@@ -9,38 +9,6 @@ import UIKit
import OneWeatherCore import OneWeatherCore
import Nuke import Nuke
private class CellGradientView: UIView {
private var gradientLayer:CAGradientLayer? {
return self.layer as? CAGradientLayer
}
init() {
super.init(frame: .zero)
prepare()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override class var layerClass: AnyClass {
return CAGradientLayer.self
}
func update(color:UIColor) {
gradientLayer?.colors = [color.withAlphaComponent(0).cgColor,
color.cgColor]
}
private func prepare() {
self.backgroundColor = .clear
guard let gradientLayer = self.gradientLayer else { return }
gradientLayer.opacity = 1
gradientLayer.locations = [0.95, 1.0]
}
}
protocol ShortsItemCellDelegate: AnyObject { protocol ShortsItemCellDelegate: AnyObject {
func averageColor(forImage image:UIImage, identifier:String) -> UIColor? func averageColor(forImage image:UIImage, identifier:String) -> UIColor?
} }
...@@ -60,10 +28,10 @@ class ShortsItemCell: UITableViewCell { ...@@ -60,10 +28,10 @@ class ShortsItemCell: UITableViewCell {
private let sourceLabel = UILabel() private let sourceLabel = UILabel()
private let titleLabel = UILabel() private let titleLabel = UILabel()
private let summaryLabel = UILabel() private let summaryLabel = UILabel()
private let ctaButton = UIButton() private var ctaButton = UIButton()
private let favoriteButton = UIButton() private var favoriteButton = UIButton()
private let shareButton = UIButton() private var shareButton = UIButton()
private let likeButton = UIButton() private var likeButton = UIButton()
private let swipeDownView = UIView() private let swipeDownView = UIView()
//Public //Public
...@@ -72,9 +40,11 @@ class ShortsItemCell: UITableViewCell { ...@@ -72,9 +40,11 @@ class ShortsItemCell: UITableViewCell {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier) super.init(style: style, reuseIdentifier: reuseIdentifier)
prepareBackground() prepareForImageOnly()
prepareTextContainer() prepareActionButtons()
prepareGradient() // prepareBackground()
// prepareTextContainer()
// prepareGradient()
} }
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
...@@ -83,13 +53,29 @@ class ShortsItemCell: UITableViewCell { ...@@ -83,13 +53,29 @@ class ShortsItemCell: UITableViewCell {
override func prepareForReuse() { override func prepareForReuse() {
super.prepareForReuse() super.prepareForReuse()
textContainer.backgroundColor = ShortsItemCell.kDefaultColor // textContainer.backgroundColor = ShortsItemCell.kDefaultColor
gradientView.update(color: ShortsItemCell.kDefaultColor) // gradientView.update(color: ShortsItemCell.kDefaultColor)
}
override func layoutSubviews() {
super.layoutSubviews()
likeButton.layer.shadowPath = UIBezierPath(roundedRect: likeButton.bounds, cornerRadius: 20).cgPath
} }
//Public //Public
func configure(shortsItem:ShortsItem) { func configure(shortsItem:ShortsItem, tableWidth:CGFloat) {
if let backgroundImage = self.bestImageForCell(images: shortsItem.images) { if let backgroundImage = shortsItem.getOverlayImage(for: tableWidth) {
Nuke.loadImage(with: backgroundImage.url, into: backgroundImageView)
}
else {
backgroundImageView.backgroundColor = UIColor.lightGray
}
UIView.performWithoutAnimation {
self.ctaButton.setTitle(shortsItem.ctaText, for: .normal)
}
/*if let backgroundImage = self.bestImageForCell(images: shortsItem.images) {
Nuke.loadImage(with: backgroundImage.url, into: backgroundImageView) {[weak self] result in Nuke.loadImage(with: backgroundImage.url, into: backgroundImageView) {[weak self] result in
switch result { switch result {
case .success(let imageResponse): case .success(let imageResponse):
...@@ -123,26 +109,10 @@ class ShortsItemCell: UITableViewCell { ...@@ -123,26 +109,10 @@ class ShortsItemCell: UITableViewCell {
summaryLabel.text = shortsItem.summaryText summaryLabel.text = shortsItem.summaryText
UIView.performWithoutAnimation { UIView.performWithoutAnimation {
self.ctaButton.setTitle(shortsItem.ctaText, for: .normal) self.ctaButton.setTitle(shortsItem.ctaText, for: .normal)
} }*/
} }
//Private //Private
private func bestImageForCell(images:[ShortsItemImage]) -> ShortsItemImage? {
guard !images.isEmpty && self.frame != .zero else {
return nil
}
var image = images.first
for itemImage in images {
if CGFloat(itemImage.width) >= self.frame.width && CGFloat(itemImage.height) >= self.frame.height {
image = itemImage
break
}
}
return image
}
@objc private func handleCtaButton() { @objc private func handleCtaButton() {
} }
...@@ -150,6 +120,14 @@ class ShortsItemCell: UITableViewCell { ...@@ -150,6 +120,14 @@ class ShortsItemCell: UITableViewCell {
//MARK:- Prepare //MARK:- Prepare
private extension ShortsItemCell { private extension ShortsItemCell {
func prepareForImageOnly() {
backgroundImageView.contentMode = .scaleAspectFit
contentView.addSubview(backgroundImageView)
backgroundImageView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
}
func prepareBackground() { func prepareBackground() {
backgroundImageView.contentMode = .scaleAspectFill backgroundImageView.contentMode = .scaleAspectFill
contentView.addSubview(backgroundImageView) contentView.addSubview(backgroundImageView)
...@@ -236,4 +214,71 @@ private extension ShortsItemCell { ...@@ -236,4 +214,71 @@ private extension ShortsItemCell {
make.bottom.equalToSuperview().inset(60) make.bottom.equalToSuperview().inset(60)
} }
} }
func prepareActionButtons() {
likeButton.setImage(UIImage(named: "like_outline"), for: .normal)
likeButton.backgroundColor = ThemeManager.currentTheme.baseBackgroundColor
likeButton.layer.cornerRadius = 20
likeButton.tintColor = ThemeManager.currentTheme.primaryTextColor
likeButton.layer.shadowColor = UIColor.black.cgColor
likeButton.layer.shadowOffset = .init(width: 0, height: 3)
likeButton.layer.shadowRadius = 5
likeButton.layer.shadowOpacity = 0.3
contentView.addSubview(likeButton)
ctaButton.addTarget(self, action: #selector(handleCtaButton), for: .touchUpInside)
ctaButton.backgroundColor = .clear
ctaButton.layer.borderColor = UIColor(hex: 0xDDDDDD).cgColor
ctaButton.layer.borderWidth = 1
ctaButton.titleLabel?.textColor = UIColor.white
ctaButton.titleLabel?.font = AppFont.SFPro.bold(size: 12)
ctaButton.layer.cornerRadius = 14
contentView.addSubview(ctaButton)
//Constraints
likeButton.snp.makeConstraints { make in
make.width.height.equalTo(40)
make.bottom.equalToSuperview().inset(28)
make.right.equalToSuperview().inset(8)
}
ctaButton.snp.makeConstraints { make in
make.width.equalTo(92)
make.height.equalTo(28)
make.left.equalToSuperview().inset(18)
make.bottom.equalToSuperview().inset(60)
}
}
}
private class CellGradientView: UIView {
private var gradientLayer:CAGradientLayer? {
return self.layer as? CAGradientLayer
}
init() {
super.init(frame: .zero)
prepare()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override class var layerClass: AnyClass {
return CAGradientLayer.self
}
func update(color:UIColor) {
gradientLayer?.colors = [color.withAlphaComponent(0).cgColor,
color.cgColor]
}
private func prepare() {
self.backgroundColor = .clear
guard let gradientLayer = self.gradientLayer else { return }
gradientLayer.opacity = 1
gradientLayer.locations = [0.95, 1.0]
}
} }
...@@ -59,6 +59,8 @@ private extension ShortsViewController { ...@@ -59,6 +59,8 @@ private extension ShortsViewController {
tableView.contentInsetAdjustmentBehavior = .never tableView.contentInsetAdjustmentBehavior = .never
tableView.dataSource = self tableView.dataSource = self
tableView.delegate = self tableView.delegate = self
tableView.separatorStyle = .none
tableView.tableFooterView = UIView()
view.addSubview(tableView) view.addSubview(tableView)
tableView.snp.makeConstraints { make in tableView.snp.makeConstraints { make in
...@@ -75,7 +77,7 @@ extension ShortsViewController: UITableViewDataSource { ...@@ -75,7 +77,7 @@ extension ShortsViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: ShortsItemCell.kIdentifier) as! ShortsItemCell let cell = tableView.dequeueReusableCell(withIdentifier: ShortsItemCell.kIdentifier) as! ShortsItemCell
cell.configure(shortsItem: viewModel.shorts[indexPath.row]) cell.configure(shortsItem: viewModel.shorts[indexPath.row], tableWidth: tableView.bounds.width)
cell.delegate = self cell.delegate = self
return cell return cell
} }
...@@ -84,6 +86,11 @@ extension ShortsViewController: UITableViewDataSource { ...@@ -84,6 +86,11 @@ extension ShortsViewController: UITableViewDataSource {
//MARK:- UITableView Delegate //MARK:- UITableView Delegate
extension ShortsViewController: UITableViewDelegate { extension ShortsViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if let image = viewModel.shorts[indexPath.row].getOverlayImage(for: tableView.frame.width) {
let aspectRatio = CGFloat(image.width) / CGFloat(image.height)
return tableView.bounds.width / aspectRatio
}
return tableView.bounds.height return tableView.bounds.height
} }
......
...@@ -14,19 +14,5 @@ class ShortsViewModel: ViewModelProtocol { ...@@ -14,19 +14,5 @@ class ShortsViewModel: ViewModelProtocol {
//Public //Public
weak var delegate:ViewModelDelegate? weak var delegate:ViewModelDelegate?
private(set) var shorts = [ShortsItem]() var shorts = [ShortsItem]()
func updateShorts() {
shortsManager.fetchShorts {[weak self] result in
guard let self = self else { return }
switch result {
case .success(let shortsItems):
self.shorts.removeAll()
self.shorts = shortsItems
self.delegate?.viewModelDidChange(model: self)
case .failure(let error):
self.delegate?.viewModel(model: self, errorHasOccured: error.localizedDescription)
}
}
}
} }
...@@ -24,7 +24,9 @@ class TodayViewModel: ViewModelProtocol { ...@@ -24,7 +24,9 @@ class TodayViewModel: ViewModelProtocol {
private let locationManager: LocationManager! = LocationManager.shared private let locationManager: LocationManager! = LocationManager.shared
private let shortsManager:ShortsManager private let shortsManager:ShortsManager
private(set) var location:Location? private(set) var location:Location?
private(set) var shorts = [ShortsItem]() var shorts: [ShortsItem] {
return ShortsManager.shared.shorts
}
public lazy var todayCellFactory:TodayCellFactory = { public lazy var todayCellFactory:TodayCellFactory = {
TodayCellFactory(viewModel: self) TodayCellFactory(viewModel: self)
...@@ -39,6 +41,7 @@ class TodayViewModel: ViewModelProtocol { ...@@ -39,6 +41,7 @@ class TodayViewModel: ViewModelProtocol {
public init(shortsManager:ShortsManager) { public init(shortsManager:ShortsManager) {
self.shortsManager = shortsManager self.shortsManager = shortsManager
self.location = LocationManager.shared.selectedLocation self.location = LocationManager.shared.selectedLocation
ShortsManager.shared.multicastDelegate.add(delegate: self)
locationManager.add(delegate: self) locationManager.add(delegate: self)
Settings.shared.delegate.add(delegate: self) Settings.shared.delegate.add(delegate: self)
NotificationCenter.default.addObserver(self, selector: #selector(handlePremiumStateChange), name: Notification.Name(rawValue: kEventInAppPurchasedCompleted), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(handlePremiumStateChange), name: Notification.Name(rawValue: kEventInAppPurchasedCompleted), object: nil)
...@@ -54,21 +57,7 @@ class TodayViewModel: ViewModelProtocol { ...@@ -54,21 +57,7 @@ class TodayViewModel: ViewModelProtocol {
public func updateWeather() { public func updateWeather() {
locationManager.updateEverythingIfNeeded() locationManager.updateEverythingIfNeeded()
shortsManager.fetchShorts {[weak self] result in ShortsManager.shared.refreshShorts()
guard let self = self else { return }
switch result {
case .success(let fetchedShorts):
self.shorts.removeAll()
self.shorts = fetchedShorts
onMain {
self.todayCellFactory.setNeedsUpdate()
self.delegate?.viewModelDidChange(model: self)
}
case .failure(let error):
self.log.debug("Shorts fetching error \(String(describing: error))")
}
}
} }
private func initializeAllAdsIfNeeded() { private func initializeAllAdsIfNeeded() {
...@@ -149,3 +138,10 @@ extension TodayViewModel: SettingsDelegate { ...@@ -149,3 +138,10 @@ extension TodayViewModel: SettingsDelegate {
delegate?.viewModelDidChange(model: self) delegate?.viewModelDidChange(model: self)
} }
} }
//MARK:- ShortsManager Delegate
extension TodayViewModel: ShortsManagerDelegate {
func shortsDidChange() {
delegate?.viewModelDidChange(model: self)
}
}
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
CD427D1F266F657900B4350A /* OneWeatherCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD427D1E266F657900B4350A /* OneWeatherCore.framework */; }; CD427D1F266F657900B4350A /* OneWeatherCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD427D1E266F657900B4350A /* OneWeatherCore.framework */; };
CD427D23266F715900B4350A /* OneWeatherAnalytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD427D22266F715900B4350A /* OneWeatherAnalytics.framework */; }; CD427D23266F715900B4350A /* OneWeatherAnalytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD427D22266F715900B4350A /* OneWeatherAnalytics.framework */; };
CDAEC2092679F70600818A2A /* GlanceOverlayImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDAEC2082679F70600818A2A /* GlanceOverlayImage.swift */; };
CDFE3F12266E407A00E72910 /* InMobiShortsSource.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDFE3F08266E407A00E72910 /* InMobiShortsSource.framework */; }; CDFE3F12266E407A00E72910 /* InMobiShortsSource.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDFE3F08266E407A00E72910 /* InMobiShortsSource.framework */; };
CDFE3F17266E407A00E72910 /* InMobiShortsSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFE3F16266E407A00E72910 /* InMobiShortsSourceTests.swift */; }; CDFE3F17266E407A00E72910 /* InMobiShortsSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDFE3F16266E407A00E72910 /* InMobiShortsSourceTests.swift */; };
CDFE3F19266E407A00E72910 /* InMobiShortsSource.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFE3F0B266E407A00E72910 /* InMobiShortsSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; CDFE3F19266E407A00E72910 /* InMobiShortsSource.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFE3F0B266E407A00E72910 /* InMobiShortsSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
...@@ -34,6 +35,7 @@ ...@@ -34,6 +35,7 @@
CD2C227E2670AC6D001ADA9A /* InMobiShortsPG.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = InMobiShortsPG.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; CD2C227E2670AC6D001ADA9A /* InMobiShortsPG.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = InMobiShortsPG.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
CD427D1E266F657900B4350A /* OneWeatherCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = OneWeatherCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; CD427D1E266F657900B4350A /* OneWeatherCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = OneWeatherCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
CD427D22266F715900B4350A /* OneWeatherAnalytics.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = OneWeatherAnalytics.framework; sourceTree = BUILT_PRODUCTS_DIR; }; CD427D22266F715900B4350A /* OneWeatherAnalytics.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = OneWeatherAnalytics.framework; sourceTree = BUILT_PRODUCTS_DIR; };
CDAEC2082679F70600818A2A /* GlanceOverlayImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlanceOverlayImage.swift; sourceTree = "<group>"; };
CDFE3F08266E407A00E72910 /* InMobiShortsSource.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = InMobiShortsSource.framework; sourceTree = BUILT_PRODUCTS_DIR; }; CDFE3F08266E407A00E72910 /* InMobiShortsSource.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = InMobiShortsSource.framework; sourceTree = BUILT_PRODUCTS_DIR; };
CDFE3F0B266E407A00E72910 /* InMobiShortsSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InMobiShortsSource.h; sourceTree = "<group>"; }; CDFE3F0B266E407A00E72910 /* InMobiShortsSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InMobiShortsSource.h; sourceTree = "<group>"; };
CDFE3F0C266E407A00E72910 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; CDFE3F0C266E407A00E72910 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
...@@ -124,6 +126,7 @@ ...@@ -124,6 +126,7 @@
CDFE3F24266E45B800E72910 /* Glance.swift */, CDFE3F24266E45B800E72910 /* Glance.swift */,
CDFE3F26266E470200E72910 /* GlanceDetails.swift */, CDFE3F26266E470200E72910 /* GlanceDetails.swift */,
CDFE3F28266E489E00E72910 /* GlanceImage.swift */, CDFE3F28266E489E00E72910 /* GlanceImage.swift */,
CDAEC2082679F70600818A2A /* GlanceOverlayImage.swift */,
CDFE3F2B266E519E00E72910 /* PeekData.swift */, CDFE3F2B266E519E00E72910 /* PeekData.swift */,
CDFE3F2D266E51B400E72910 /* Peek.swift */, CDFE3F2D266E51B400E72910 /* Peek.swift */,
); );
...@@ -243,6 +246,7 @@ ...@@ -243,6 +246,7 @@
CDFE3F23266E453500E72910 /* InMobiShortSource.swift in Sources */, CDFE3F23266E453500E72910 /* InMobiShortSource.swift in Sources */,
CDFE3F29266E489E00E72910 /* GlanceImage.swift in Sources */, CDFE3F29266E489E00E72910 /* GlanceImage.swift in Sources */,
CDFE3F25266E45B800E72910 /* Glance.swift in Sources */, CDFE3F25266E45B800E72910 /* Glance.swift in Sources */,
CDAEC2092679F70600818A2A /* GlanceOverlayImage.swift in Sources */,
CDFE3F27266E470200E72910 /* GlanceDetails.swift in Sources */, CDFE3F27266E470200E72910 /* GlanceDetails.swift in Sources */,
CDFE3F2C266E519E00E72910 /* PeekData.swift in Sources */, CDFE3F2C266E519E00E72910 /* PeekData.swift in Sources */,
); );
......
...@@ -132,6 +132,7 @@ public class InMobiShortSource: ShortSource { ...@@ -132,6 +132,7 @@ public class InMobiShortSource: ShortSource {
private func toAppModel(glanceDetails:GlanceDetails) -> ShortsItem { private func toAppModel(glanceDetails:GlanceDetails) -> ShortsItem {
ShortsItem(id: glanceDetails.id, ShortsItem(id: glanceDetails.id,
images: glanceDetails.image.supportedImages.map{ .init(width: $0.width, height: $0.height, url: $0.url) }, images: glanceDetails.image.supportedImages.map{ .init(width: $0.width, height: $0.height, url: $0.url) },
overlayImages: glanceDetails.overlayImage.supportedImages.map{ .init(width: $0.width, height: $0.height, url: $0.url) },
updatedAtInSecs: glanceDetails.updatedAtInSecs, updatedAtInSecs: glanceDetails.updatedAtInSecs,
startsAtInSecs: glanceDetails.startsAtInSecs, startsAtInSecs: glanceDetails.startsAtInSecs,
endsAtInSecs: glanceDetails.endsAtInSecs, endsAtInSecs: glanceDetails.endsAtInSecs,
......
...@@ -15,10 +15,11 @@ struct GlanceInteractionDetails: Codable { ...@@ -15,10 +15,11 @@ struct GlanceInteractionDetails: Codable {
struct GlanceDetails: Codable { struct GlanceDetails: Codable {
let id: String let id: String
let image: GlanceImage let image: GlanceImage
let overlayImage: GlanceOverlayImage
let updatedAtInSecs: TimeInterval let updatedAtInSecs: TimeInterval
let startsAtInSecs: TimeInterval let startsAtInSecs: TimeInterval
let endsAtInSecs: TimeInterval let endsAtInSecs: TimeInterval
var encodedShareURL:URL? { var encodedShareURL: URL? {
guard let urlStirng = shareUrl else { guard let urlStirng = shareUrl else {
return nil return nil
} }
......
//
// GlanceOverlayImage.swift
// InMobiShortsSource
//
// Created by Dmitry Stepanets on 16.06.2021.
//
import Foundation
struct GlanceOverlayImage: Codable {
let id:String
let supportedImages:[GlanceImageFormat]
}
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
// Created by Dmitry Stepanets on 08.06.2021. // Created by Dmitry Stepanets on 08.06.2021.
// //
import Foundation import UIKit
public struct ShortsItemImage { public struct ShortsItemImage {
public let width:Int public let width:Int
...@@ -20,9 +20,29 @@ public struct ShortsItemImage { ...@@ -20,9 +20,29 @@ public struct ShortsItemImage {
} }
public struct ShortsItem { public struct ShortsItem {
public init(id: String, images: [ShortsItemImage], updatedAtInSecs: TimeInterval, startsAtInSecs: TimeInterval, endsAtInSecs: TimeInterval, shareURL: URL?, title: String, summaryText: String, sourceName: String, heartCount: Int, shortURL: URL?, ctaText: String, ctaURL: URL?, likeCount: Int, shareCount: Int) { public let id: String
public let images: [ShortsItemImage]
public let overlayImages: [ShortsItemImage]
public let updatedAtInSecs: TimeInterval
public let startsAtInSecs: TimeInterval
public let endsAtInSecs: TimeInterval
public let shareURL: URL?
public let title: String
public let summaryText: String
public let sourceName: String
public let heartCount: Int
public let shortURL: URL?
public let ctaText: String
public let ctaURL: URL?
public let likeCount: Int
public let shareCount: Int
public var isLiked: Bool = false
public var isViewed: Bool = false
public init(id: String, images: [ShortsItemImage], overlayImages: [ShortsItemImage], updatedAtInSecs: TimeInterval, startsAtInSecs: TimeInterval, endsAtInSecs: TimeInterval, shareURL: URL?, title: String, summaryText: String, sourceName: String, heartCount: Int, shortURL: URL?, ctaText: String, ctaURL: URL?, likeCount: Int, shareCount: Int) {
self.id = id self.id = id
self.images = images self.images = images
self.overlayImages = overlayImages
self.updatedAtInSecs = updatedAtInSecs self.updatedAtInSecs = updatedAtInSecs
self.startsAtInSecs = startsAtInSecs self.startsAtInSecs = startsAtInSecs
self.endsAtInSecs = endsAtInSecs self.endsAtInSecs = endsAtInSecs
...@@ -38,19 +58,41 @@ public struct ShortsItem { ...@@ -38,19 +58,41 @@ public struct ShortsItem {
self.shareCount = shareCount self.shareCount = shareCount
} }
public let id:String public func getImage(for width:CGFloat) -> ShortsItemImage? {
public let images: [ShortsItemImage] guard !self.images.isEmpty && width > 0 else {
public let updatedAtInSecs: TimeInterval return nil
public let startsAtInSecs: TimeInterval }
public let endsAtInSecs: TimeInterval
public let shareURL: URL? var image = images.first
public let title:String for itemImage in images {
public let summaryText:String if CGFloat(itemImage.width) / UIScreen.main.scale >= width {
public let sourceName:String image = itemImage
public let heartCount:Int break
public let shortURL:URL? }
public let ctaText:String }
public let ctaURL:URL? return image
public let likeCount:Int }
public let shareCount:Int
public func getOverlayImage(for width:CGFloat) -> ShortsItemImage? {
guard !self.overlayImages.isEmpty && width > 0 else {
return nil
}
var image = overlayImages.first
for itemImage in overlayImages {
if CGFloat(itemImage.width) / UIScreen.main.scale >= width {
image = itemImage
break
}
}
return image
}
public mutating func like() {
isLiked = true
}
public mutating func markAsViewed() {
isViewed = true
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment