added tileContainer view/model

Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
Matt Bruce 2024-04-15 15:14:56 -05:00
parent 122f5b6c97
commit 6e5abcc912
4 changed files with 244 additions and 0 deletions

View File

@ -578,6 +578,8 @@
EA41F4AC2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */; };
EA5124FD243601600051A3A4 /* BGImageHeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */; };
EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */; };
EA6642912BCDA97300D81DC4 /* TileContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6642902BCDA97300D81DC4 /* TileContainer.swift */; };
EA6642932BCDA97D00D81DC4 /* TileContainerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6642922BCDA97D00D81DC4 /* TileContainerModel.swift */; };
EA6E8B952B504A43000139B4 /* ButtonGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6E8B942B504A43000139B4 /* ButtonGroup.swift */; };
EA6E8B972B504A4D000139B4 /* ButtonGroupModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6E8B962B504A4D000139B4 /* ButtonGroupModel.swift */; };
EA7D81602B2B6E6800D29F9E /* Icon.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7D815F2B2B6E6800D29F9E /* Icon.swift */; };
@ -1184,6 +1186,8 @@
EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicRuleFormFieldEffectModel.swift; sourceTree = "<group>"; };
EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButton.swift; sourceTree = "<group>"; };
EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButtonModel.swift; sourceTree = "<group>"; };
EA6642902BCDA97300D81DC4 /* TileContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TileContainer.swift; sourceTree = "<group>"; };
EA6642922BCDA97D00D81DC4 /* TileContainerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TileContainerModel.swift; sourceTree = "<group>"; };
EA6E8B942B504A43000139B4 /* ButtonGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroup.swift; sourceTree = "<group>"; };
EA6E8B962B504A4D000139B4 /* ButtonGroupModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroupModel.swift; sourceTree = "<group>"; };
EA7D815F2B2B6E6800D29F9E /* Icon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Icon.swift; sourceTree = "<group>"; };
@ -2274,6 +2278,8 @@
EA1758472BC97ED800A5C0D9 /* BadgeIndicator.swift */,
EA17584B2BC9894800A5C0D9 /* ButtonIconModel.swift */,
EA17584D2BC9895A00A5C0D9 /* ButtonIcon.swift */,
EA6642922BCDA97D00D81DC4 /* TileContainerModel.swift */,
EA6642902BCDA97300D81DC4 /* TileContainer.swift */,
EA985C3F2970939A00F2FF2E /* TileletModel.swift */,
EA985C3D2970938F00F2FF2E /* Tilelet.swift */,
EA7D81612B2B6E7F00D29F9E /* IconModel.swift */,
@ -3063,6 +3069,7 @@
0AE14F64238315D2005417F8 /* TextField.swift in Sources */,
0A51F3E22475CB73002E08B6 /* LoadingSpinnerModel.swift in Sources */,
D2169303251E53D9002A6324 /* SectionListTemplateModel.swift in Sources */,
EA6642932BCDA97D00D81DC4 /* TileContainerModel.swift in Sources */,
AF7E509929E477C1009DC2AD /* AlertController.swift in Sources */,
0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */,
BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */,
@ -3189,6 +3196,7 @@
D29C559625C099630082E7D6 /* VideoDataManager.swift in Sources */,
8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */,
D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */,
EA6642912BCDA97300D81DC4 /* TileContainer.swift in Sources */,
012A88C2238D7BCA00FE3DA1 /* CarouselItemModel.swift in Sources */,
27F6B08C26052AFF008529AA /* ParentMoleculeModelProtocol.swift in Sources */,
EA985C402970939A00F2FF2E /* TileletModel.swift in Sources */,

View File

@ -0,0 +1,89 @@
//
// TileContainer.swift
// MVMCoreUI
//
// Created by Matt Bruce on 4/15/24.
// Copyright © 2024 Verizon Wireless. All rights reserved.
//
import Foundation
import VDS
import Combine
open class TileContainer: VDS.TileContainer, VDSMoleculeViewProtocol{
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public var model: MoleculeModelProtocol?
public var viewModel: TileContainerModel!
public var delegateObject: MVMCoreUIDelegateObject?
public var additionalData: [AnyHashable: Any]?
public var molecule: MoleculeViewProtocol?
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
public convenience required init() {
self.init(frame: .zero)
}
//--------------------------------------------------
// MARK: - Public
//--------------------------------------------------
public func viewModelDidUpdate() {
if molecule != nil {
molecule?.set(with: viewModel.molecule, delegateObject, additionalData)
} else if let moleculeView = ModelRegistry.createMolecule(viewModel.molecule, delegateObject: delegateObject, additionalData: additionalData) {
addContentView(moleculeView)
}
padding = viewModel.padding
color = viewModel.color
backgroundEffect = viewModel.backgroundEffect
aspectRatio = viewModel.aspectRatio
width = viewModel.width
height = viewModel.height
showBorder = viewModel.showBorder
showDropShadows = viewModel.showDropShadwows
//setup action
if let action = viewModel.action {
//add the subscriber
onClick = { [weak self] control in
guard let self, let viewModel = self.viewModel else { return }
MVMCoreUIActionHandler.performActionUnstructured(with: action,
sourceModel: viewModel,
additionalData: self.additionalData,
delegateObject: self.delegateObject)
}
}
}
//--------------------------------------------------
// MARK: - MVMCoreViewProtocol
//--------------------------------------------------
open func updateView(_ size: CGFloat) {}
//--------------------------------------------------
// MARK: - MoleculeViewProtocol
//--------------------------------------------------
//since this is a class func, we can't reference it directly
public static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
100
}
//--------------------------------------------------
// MARK: - Overrides
//--------------------------------------------------
open override func layoutSubviews() {
super.layoutSubviews()
// Accounts for any collection size changes
DispatchQueue.main.async { [weak self] in
guard let self else { return }
self.delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self)
}
}
}

View File

@ -0,0 +1,99 @@
//
// TileContainerModel.swift
// MVMCoreUI
//
// Created by Matt Bruce on 4/15/24.
// Copyright © 2024 Verizon Wireless. All rights reserved.
//
import Foundation
import VDS
open class TileContainerModel: TileContainerBaseModel, MoleculeModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "tileContainer"
public var id: String = UUID().uuidString
public var backgroundColor: Color?
public var padding: TileContainer.Padding = .padding4X
public var aspectRatio: TileContainer.AspectRatio = .ratio1x1
public var color: TileContainer.BackgroundColor = .secondary
public var backgroundEffect: TileContainer.BackgroundEffect = .none
public var molecule: MoleculeModelProtocol
private enum CodingKeys: String, CodingKey {
case id
case moleculeName
case molecule
case padding
case aspectRatio
case color
case backgroundEffect
}
required public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
molecule = try container.decodeModel(codingKey: .molecule)
padding = try container.decodeIfPresent(TileContainer.Padding.self, forKey: .padding) ?? .padding4X
color = try container.decodeIfPresent(TileContainer.BackgroundColor.self, forKey: .color) ?? .secondary
backgroundEffect = try container.decodeIfPresent(TileContainer.BackgroundEffect.self, forKey: .backgroundEffect) ?? .none
aspectRatio = try container.decodeIfPresent(TileContainer.AspectRatio.self, forKey: .aspectRatio) ?? .none
try super.init(from: decoder)
}
public override func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(padding, forKey: .padding)
try container.encodeIfPresent(color, forKey: .color)
try container.encodeIfPresent(backgroundEffect, forKey: .backgroundEffect)
try container.encodeIfPresent(aspectRatio, forKey: .aspectRatio)
try super.encode(to: encoder)
}
}
open class TileContainerBaseModel: Codable {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public var backgroundImage: String?
public var action: ActionModelProtocol?
public var imageFallbackColor: Surface = .light
public var width: CGFloat?
public var height: CGFloat?
public var showBorder: Bool = false
public var showDropShadwows: Bool = false
private enum CodingKeys: String, CodingKey {
case backgroundImage
case action
case padding
case imageFallbackColor
case width
case height
case showBorder
case showDropShadows
}
required public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
backgroundImage = try container.decodeIfPresent(String.self, forKey: .backgroundImage)
width = try container.decodeIfPresent(CGFloat.self, forKey: .width)
height = try container.decodeIfPresent(CGFloat.self, forKey: .height)
action = try container.decodeModelIfPresent(codingKey: .action)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(backgroundImage, forKey: .backgroundImage)
try container.encodeIfPresent(width, forKey: .width)
try container.encodeIfPresent(height, forKey: .height)
try container.encodeModelIfPresent(action, forKey: .action)
}
}

View File

@ -100,6 +100,54 @@ extension VDS.TileContainerBase.BackgroundColor: Codable {
}
}
extension VDS.TileContainerBase.BackgroundEffect: Codable {
enum Error: Swift.Error {
case valueNotFound(type: String)
}
enum CodingKeys: String, CodingKey {
case type
case firstColor
case secondColor
}
enum BackgroundEffectType: String, Codable {
case transparency
case none
case gradient
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let type = try container.decode(BackgroundEffectType.self, forKey: .type)
switch type {
case .transparency:
self = .transparency
case .none:
self = .none
case .gradient:
let firstColor = try container.decode(String.self, forKey: .firstColor)
let secondColor = try container.decode(String.self, forKey: .secondColor)
self = .gradient(firstColor, secondColor)
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
switch self {
case .transparency:
try container.encode(BackgroundEffectType.transparency.rawValue, forKey: .type)
case .none:
try container.encode(BackgroundEffectType.none.rawValue, forKey: .type)
case .gradient(let firstColor, let secondColor):
try container.encode(BackgroundEffectType.gradient.rawValue, forKey: .type)
try container.encode(firstColor, forKey: .firstColor)
try container.encode(secondColor, forKey: .secondColor)
@unknown default: break
}
}
}
extension VDS.TileContainer.Padding: Codable {
enum PaddingError: Error {
case valueNotFound(type: String)