added cardId to statesById in DivBlockStateStorage

This commit is contained in:
chris-benua
2023-07-19 20:04:57 +03:00
parent 742d797ffd
commit 92f040bb66
7 changed files with 114 additions and 78 deletions
@@ -102,17 +102,18 @@ public final class DivActionURLHandler {
value: value
)
case let .setCurrentItem(id, index):
setCurrentItem(id: id, index: index)
setCurrentItem(id: id, cardId: cardId, index: index)
updateCard(.state(cardId))
case let .setNextItem(id, overflow):
setNextItem(id: id, overflow: overflow)
setNextItem(id: id, cardId: cardId, overflow: overflow)
updateCard(.state(cardId))
case let .setPreviousItem(id, overflow):
setPreviousItem(id: id, overflow: overflow)
setPreviousItem(id: id, cardId: cardId, overflow: overflow)
updateCard(.state(cardId))
case let .video(id: id, action: action):
blockStateStorage.setState(
id: id,
cardId: cardId,
state: VideoBlockViewState(state: action == .play ? .playing : .paused)
)
updateCard(.state(cardId))
@@ -137,29 +138,31 @@ public final class DivActionURLHandler {
}
}
private func setCurrentItem(id: String, index: Int) {
switch blockStateStorage.getStateUntyped(id) {
private func setCurrentItem(id: String, cardId: DivCardID, index: Int) {
switch blockStateStorage.getStateUntyped(id, cardId: cardId) {
case let galleryState as GalleryViewState:
setGalleryCurrentItem(
id: id,
cardId: cardId,
index: index,
itemsCount: galleryState.itemsCount
)
case let pagerState as PagerViewState:
setPagerCurrentItem(
id: id,
cardId: cardId,
index: index,
numberOfPages: pagerState.numberOfPages
)
case let tabsState as TabViewState:
setTabsCurrentItem(id: id, index: index, countOfPages: tabsState.countOfPages)
setTabsCurrentItem(id: id, cardId: cardId, index: index, countOfPages: tabsState.countOfPages)
default:
return
}
}
private func setNextItem(id: String, overflow: OverflowMode) {
switch blockStateStorage.getStateUntyped(id) {
private func setNextItem(id: String, cardId: DivCardID, overflow: OverflowMode) {
switch blockStateStorage.getStateUntyped(id, cardId: cardId) {
case let galleryState as GalleryViewState:
let index = getNextIndex(
current: galleryState.currentItemIndex,
@@ -168,6 +171,7 @@ public final class DivActionURLHandler {
)
setGalleryCurrentItem(
id: id,
cardId: cardId,
index: index,
itemsCount: galleryState.itemsCount
)
@@ -179,6 +183,7 @@ public final class DivActionURLHandler {
)
setPagerCurrentItem(
id: id,
cardId: cardId,
index: nextIndex,
numberOfPages: pagerState.numberOfPages
)
@@ -190,6 +195,7 @@ public final class DivActionURLHandler {
)
setTabsCurrentItem(
id: id,
cardId: cardId,
index: nextIndex,
countOfPages: tabsState.countOfPages
)
@@ -211,8 +217,8 @@ public final class DivActionURLHandler {
}
}
private func setPreviousItem(id: String, overflow: OverflowMode) {
switch blockStateStorage.getStateUntyped(id) {
private func setPreviousItem(id: String, cardId: DivCardID, overflow: OverflowMode) {
switch blockStateStorage.getStateUntyped(id, cardId: cardId) {
case let galleryState as GalleryViewState:
let index = getPreviousIndex(
current: galleryState.currentItemIndex,
@@ -221,6 +227,7 @@ public final class DivActionURLHandler {
)
setGalleryCurrentItem(
id: id,
cardId: cardId,
index: index,
itemsCount: galleryState.itemsCount
)
@@ -232,6 +239,7 @@ public final class DivActionURLHandler {
)
setPagerCurrentItem(
id: id,
cardId: cardId,
index: prevIndex,
numberOfPages: pagerState.numberOfPages
)
@@ -243,6 +251,7 @@ public final class DivActionURLHandler {
)
setTabsCurrentItem(
id: id,
cardId: cardId,
index: prevIndex,
countOfPages: tabsState.countOfPages
)
@@ -266,11 +275,13 @@ public final class DivActionURLHandler {
private func setGalleryCurrentItem(
id: String,
cardId: DivCardID,
index: Int,
itemsCount: Int
) {
blockStateStorage.setState(
id: id,
cardId: cardId,
state: GalleryViewState(
contentPageIndex: CGFloat(max(0, index)),
itemsCount: itemsCount
@@ -278,7 +289,7 @@ public final class DivActionURLHandler {
)
}
private func setPagerCurrentItem(id: String, index: Int, numberOfPages: Int) {
private func setPagerCurrentItem(id: String, cardId: DivCardID, index: Int, numberOfPages: Int) {
let clampedIndex = clamp(index, min: 0, max: numberOfPages - 1)
guard clampedIndex == index else {
return
@@ -286,6 +297,7 @@ public final class DivActionURLHandler {
blockStateStorage.setState(
id: id,
cardId: cardId,
state: PagerViewState(
numberOfPages: numberOfPages,
currentPage: clampedIndex
@@ -293,9 +305,10 @@ public final class DivActionURLHandler {
)
}
private func setTabsCurrentItem(id: String, index: Int, countOfPages: Int) {
private func setTabsCurrentItem(id: String, cardId: DivCardID, index: Int, countOfPages: Int) {
blockStateStorage.setState(
id: id,
cardId: cardId,
state: TabViewState(
selectedPageIndex: CGFloat(max(0, index)),
countOfPages: countOfPages
+26 -9
View File
@@ -1,10 +1,11 @@
import Foundation
import LayoutKit
import BaseTinyPublic
public final class DivBlockStateStorage {
public private(set) var states: BlocksState
private var statesById: [String: ElementState] = [:]
private var statesById: [IdAndCardId: ElementState] = [:]
public init(states: BlocksState = [:]) {
self.states = states
@@ -16,25 +17,26 @@ public final class DivBlockStateStorage {
}
public func getStateUntyped(_ path: UIElementPath) -> ElementState? {
statesById[path.leaf] ?? states[path]
statesById[IdAndCardId(path: path)] ?? states[path]
}
@inlinable
public func getState<T: ElementState>(_ id: String) -> T? {
getStateUntyped(id) as? T
public func getState<T: ElementState>(_ id: String, cardId: DivCardID) -> T? {
getStateUntyped(id, cardId: cardId) as? T
}
public func getStateUntyped(_ id: String) -> ElementState? {
statesById[id] ?? states.first { $0.key.leaf == id }?.value
public func getStateUntyped(_ id: String, cardId: DivCardID) -> ElementState? {
let idKey = IdAndCardId(id: id, cardId: cardId)
return statesById[idKey] ?? states.first { IdAndCardId(path: $0.key) == idKey }?.value
}
public func setState(path: UIElementPath, state: ElementState) {
statesById[path.leaf] = nil
statesById[IdAndCardId(path: path)] = nil
states[path] = state
}
public func setState(id: String, state: ElementState) {
statesById[id] = state
public func setState(id: String, cardId: DivCardID, state: ElementState) {
statesById[IdAndCardId(id: id, cardId: cardId)] = state
}
public func reset() {
@@ -52,3 +54,18 @@ extension DivBlockStateStorage: ElementStateObserver {
getStateUntyped(path)
}
}
private struct IdAndCardId: Hashable {
let id: String
let cardId: DivCardID
init(id: String, cardId: DivCardID) {
self.id = id
self.cardId = cardId
}
init(path: UIElementPath) {
id = path.leaf
cardId = DivCardID(rawValue: path.root)
}
}
+14 -14
View File
@@ -12,20 +12,6 @@ public typealias DivStatePath = Tagged<DivStatePathTag, UIElementPath>
public enum DivBlockPathTag {}
public typealias DivBlockPath = Tagged<DivBlockPathTag, UIElementPath>
extension UIElementPath {
public static func parseDivPath(_ string: String) -> Self? {
let split = string.split(separator: "/")
guard
let first = split.first,
Int(first) != nil
else {
return nil
}
return UIElementPath(String(first)) + split.dropFirst().map(String.init)
}
}
extension Tagged where Tag == DivStatePathTag, RawValue == UIElementPath {
public static func makeDivStatePath(from string: String) -> Self? {
guard let path = UIElementPath.parseDivPath(string) else {
@@ -91,3 +77,17 @@ extension Tagged where Tag == DivBlockPathTag, RawValue == UIElementPath {
return DivStatePath(rawValue: parent)
}
}
extension UIElementPath {
fileprivate static func parseDivPath(_ string: String) -> Self? {
let split = string.split(separator: "/")
guard
let first = split.first,
Int(first) != nil
else {
return nil
}
return UIElementPath(String(first)) + split.dropFirst().map(String.init)
}
}
@@ -65,7 +65,9 @@ extension DivIndicator: DivBlockModeling {
pagerId: $0
)
}
let state = context.blockStateStorage.states.pagerViewState(for: pagerPath) ?? .default
let state: PagerViewState = pagerPath.flatMap {
context.blockStateStorage.getState($0.pagerId, cardId: context.cardId)
} ?? .default
let spaceBetweenCenters = CGFloat(spaceBetweenCenters.resolveValue(expressionResolver) ?? 0)
let configuration = PageIndicatorConfiguration(
@@ -14,7 +14,7 @@ final class DivBlockStateStorageTests: XCTestCase {
}
func test_GetState_ByPath_NotExists() {
XCTAssertNil(storage.getStateUntyped(path("0/id")))
XCTAssertNil(storage.getStateUntyped(divStatePath("0/id")))
}
func test_GetState_ById_NotExists() {
@@ -22,47 +22,47 @@ final class DivBlockStateStorageTests: XCTestCase {
}
func test_SetState_WithPath_GetState_ByPath() {
storage.setState(path: path("0/id"), state: state1)
XCTAssertEqual(storage.getState(path("0/id")), state1)
storage.setState(path: divStatePath("0/id"), state: state1)
XCTAssertEqual(storage.getState(divStatePath("0/id")), state1)
}
func test_SetState_WithPath_GetState_ById() {
storage.setState(path: path("0/id"), state: state1)
XCTAssertEqual(storage.getState("id"), state1)
storage.setState(path: path(cardId: "card_id", path: "0/id"), state: state1)
XCTAssertEqual(storage.getState("id", cardId: "card_id"), state1)
}
func test_SetState_WithId_GetState_ByPath() {
storage.setState(id: "id", state: state1)
XCTAssertEqual(storage.getState(path("0/div_state/state1/id")), state1)
func test_SetState_WithIdAndCardId_GetState_ByPath() {
storage.setState(id: "id", cardId: "card_id", state: state1)
XCTAssertEqual(storage.getState(path(cardId: "card_id", path: "0/div_state/state1/id")), state1)
}
func test_SetState_WithId_GetState_ById() {
storage.setState(id: "id", state: state1)
XCTAssertEqual(storage.getState("id"), state1)
func test_SetState_WithIdAndCardId_GetState_ByIdAndCardId() {
storage.setState(id: "id", cardId: "card_id", state: state1)
XCTAssertEqual(storage.getState("id", cardId: "card_id"), state1)
}
func test_SetState_WithPath_OverridesWithId() {
storage.setState(id: "id", state: state1)
storage.setState(path: path("0/id"), state: state2)
XCTAssertEqual(storage.getState(path("0/id")), state2)
storage.setState(id: "id", cardId: "card_id", state: state1)
storage.setState(path: path(cardId: "card_id", path: "0/id"), state: state2)
XCTAssertEqual(storage.getState(path(cardId: "card_id", path: "0/id")), state2)
}
func test_SetState_WithId_OverridesWithPath() {
storage.setState(path: path("0/id"), state: state1)
storage.setState(id: "id", state: state2)
XCTAssertEqual(storage.getState(path("0/id")), state2)
storage.setState(path: path(cardId: "card_id", path: "0/id"), state: state1)
storage.setState(id: "id", cardId: "card_id", state: state2)
XCTAssertEqual(storage.getState(path(cardId: "card_id", path: "0/id")), state2)
}
func test_Reset_ResetsPaths() {
storage.setState(path: path("0/id"), state: state1)
storage.setState(path: divStatePath("0/id"), state: state1)
storage.reset()
XCTAssertNil(storage.getStateUntyped(path("0/id")))
XCTAssertNil(storage.getStateUntyped(divStatePath("0/id")))
}
func test_Reset_ResetsIds() {
storage.setState(id: "id", state: state1)
storage.setState(id: "id", cardId: "card_id", state: state1)
storage.reset()
XCTAssertNil(storage.getStateUntyped("id"))
XCTAssertNil(storage.getStateUntyped("id", cardId: "card_id"))
}
}
@@ -73,6 +73,10 @@ private struct State: ElementState, Equatable {
public let name: String
}
private func path(_ path: String) -> UIElementPath {
UIElementPath.parseDivPath(path)!
private func path(cardId: String, path: String) -> UIElementPath {
UIElementPath(cardId) + path.split(separator: "/").map(String.init)
}
private func divStatePath(_ path: String) -> UIElementPath {
DivStatePath.makeDivStatePath(from: path)!.rawValue
}
@@ -3,29 +3,12 @@ import Foundation
import CommonCorePublic
import LayoutKitInterface
extension BlocksState {
public func pagerViewState(for pagerPath: PagerPath?) -> PagerViewState? {
pagerPath.flatMap { pagerPath in
first(where: { pagerPath.matches($0.key) })?.value as? PagerViewState
}
}
}
public struct PagerPath: Equatable {
let cardId: String
let pagerId: String
public let cardId: String
public let pagerId: String
public init(cardId: String, pagerId: String) {
self.cardId = cardId
self.pagerId = pagerId
}
}
extension PagerPath {
fileprivate func matches(_ path: UIElementPath) -> Bool {
if path.root != cardId {
return false
}
return path.leaf == pagerId
}
}
@@ -146,3 +146,20 @@ extension Array where Element == GalleryViewModel.Item {
}
}
}
extension BlocksState {
public func pagerViewState(for pagerPath: PagerPath?) -> PagerViewState? {
pagerPath.flatMap { pagerPath in
first(where: { pagerPath.matches($0.key) })?.value as? PagerViewState
}
}
}
extension PagerPath {
fileprivate func matches(_ path: UIElementPath) -> Bool {
if path.root != cardId {
return false
}
return path.leaf == pagerId
}
}