mirror of
https://github.com/divkit/divkit.git
synced 2026-06-06 20:07:59 +00:00
f1563c9890
Initial commit Add notification for divkit Allow overwrite for migration [migration] browser/bitbucket/personal/booster/divkit Note: mandatory check (NEED_CHECK) was skipped DivKit files moved dIVKIT-0: Fix ts builder build update div-gallery visibility screenshots update div-gallery visibility screens a.yaml cleanup updated codegen scripts change gallery alignment change internal types in expressions removed copyrights remove permissions TemplatesSupportTests refactoring Ничего не поменялось. Отрефакторил и почистил тесты. Split package.json send all public removed yandex-team links URL added type as ArgumentType added camera permission description safe area insets for errors count view `EdgeInsets` for debug view with errors count. Needed for fullscreen divs. Naming corresponds to mapping `EdgeInsets` to div-variables. Will be used here: https://nda.ya.ru/t/Lhr5Lxgb5KN6nX fixed compiler warnings fix DivKitComponents variables setup, add update func fix DivKitComponents variables setup, add update func authors clean up Удалил коллег из инфраструктуры, тестирования и мессенджера. Половину людей я вообще тут не знаю. Список какой-то косячный, в нём, например, @booster и @askvortsov нет. Предлагаю заново вручную составить и записать туда тех, кто точно дивкитом занимался, а не просто мимо проходил. Fix DivKit pods compilability Fix DivKit pods compilability use only english in demo app translate divKit demo app russian text Scroll when keyboard opened Scroll when keyboard opened Fix gallery scroll in a11y Это копия пр-а, который я делал в репо алискита: https://bitbucket.browser.yandex-team.ru/projects/ML/repos/mobile-alice-library-android/pull-requests/18808/overview authors clean up2 SwiftGenerator flake8 errors fix & ya.make edit swift generation tests swift references swift generator implementation init swift generator code refactoring 1) rename to modeling 2) rename kind to PropertyType 3) delete apply_pluralization_rules 4) description default value is empty string 5) remove entity_type_field_alias, typename_alias, client_optional, profileEntities, ignore_properties, generate_plain_constructor 6) remove client prefix Add XcodeBuild in ignore Add XcodeBuild in ignore introduce new global variable api introduce new global variable api Revert commit bdcbc0081395ebe44ed7fe24bf5f4b25569c6df0 LayoutKitSnapshotTests Fix sandboxRelease dependencies. support zero value for width and height remove unused css variables "CONTRIBUTING.md" README draft updated gitignore/arcignore introduce color type in expressions introduce color type in expressions added xcconfig files fixed swift formatting fail tests if updating references Чтобы уж точно не забыть вернуть False. Layout changes Fix expression parsing don't change clickable state in a11y don't change clickable state in a11y Update items checks Parse description references to translations add licence file link fixed expression properties generation add ability to track requests to global variables Добавляем в GlobalVariableController возможность подписаться на запросы к глобальным переменным. Нужно дляОткрыт Накопительная палитра , а так же в целом полезная функциональность, через которую можно делать ленивый прогрев глобальных переменных Changelog Minor fixes bump divkit version up to 3.0.0 fixed snapshot tests depdendencies Иногда не запускалась сборка SnapshotTestsHostApp перед стартом тестов. used new api-generator deserialization refactoring removed gitignore samples text fixes fixed samples text remove theme button remove theme button demo activity redesign demo activity redesign habr sample app change deleted images in screenshot tests change deleted images in screenshot tests new ic_launcher new ic_launcher more readme Binding variable for div input Biding variable for div input Implement documentation generator Rename max_lines to max_visible_lines Rename max_lines to max_visible_lines add habr and medium fix div-functions doc Fix link in description Text selecting for demo app enabled Text selecting for demo app enabled KotlinGenerator kotlin code generation kotlin generation tests kotlin generation references add gradle wrapper to kotlin json builder add gradle wrapper to kotlin json builder DemoApp redesign fixed codegen scripts debugView safeAreaInsets DebugView safe area insets TypeScript Generator ya.make changes TypeScript generator TypeScript tests TypeScript test references fix enumeration aliases debugInfoParams fix compile Fix black box flicker in video-custom Fixed stub image showing by moving it away from PlayerView. Increased stub loading speed by adding VideoViewModel warmup. Fixed redundant redraws by combining stub visibility and bitmap data. PlayerView background was set to transparent. DivExpression fix DivExpression fix Implement translations Save & share bind globalVariableController to divContext bind variableController to divContext used new TypeScript generator Подключил генератор на питоне. Изменения в сгенерированных файлах связаны в основном с переводом описаний на английский язык. moved LivePreview Перенёс LivePreview из отдельного модуля в DivKitDemoApp. Добавил сканер кодов в UrlInputView. Удалил часть дублирующегося кода. remove sms and phone_state permission fix links interception fix links interception Fix link in documentation remove site from "config.stable.json" Support highlight_color and keyboardType in div input Support highlight_color in div input Action animation fix for iOS
407 lines
16 KiB
Swift
407 lines
16 KiB
Swift
@testable import LayoutKit
|
|
|
|
import XCTest
|
|
|
|
import BaseUI
|
|
import CommonCore
|
|
|
|
final class GalleryViewLayoutTests: XCTestCase {
|
|
func test_ProducesEqualToModelBlocksCountNumberOfFrames() {
|
|
let model = Blocks.horizontalCenterModel
|
|
|
|
let layout = GalleryViewLayout(model: model)
|
|
|
|
XCTAssertEqual(layout.blockFrames.count, model.items.count)
|
|
}
|
|
|
|
func test_WhenHasHorizontalDirection_ProducesSummaryWidthAndBlockMaximumHeightContentSizePlusCrossInsets(
|
|
) {
|
|
let layout = GalleryViewLayout(model: Blocks.horizontalCenterModel)
|
|
|
|
XCTAssertEqual(layout.contentSize.width, Blocks.contentAxialSize)
|
|
XCTAssertEqual(layout.contentSize.height, Blocks.contentCrossMaxSize + Blocks.fixedInsets.sum)
|
|
}
|
|
|
|
func test_WhenDoesNotHaveBounds_AndHorizontalDirection_AppliesResizableBlockHeightToOtherBlocksMaximumHeight(
|
|
) {
|
|
let model = Blocks.horizontalCenterModel
|
|
|
|
let layout = GalleryViewLayout(model: model)
|
|
|
|
if let index = model.items.firstIndex(where: { $0.content.isVerticallyResizable }) {
|
|
XCTAssertEqual(layout.blockFrames[index].height, Blocks.contentCrossMaxSize)
|
|
} else {
|
|
XCTFail()
|
|
}
|
|
}
|
|
|
|
func test_WhenHasBounds_AndHorizontalDirection_AppliesResizableBlockHeightToInsetedBoundsHeight() {
|
|
let model = Blocks.horizontalCenterModel
|
|
|
|
let layout = GalleryViewLayout(model: model, boundsSize: boundsSize)
|
|
|
|
let height = boundsSize.height - Blocks.fixedInsets.sum
|
|
if let index = model.items.firstIndex(where: { $0.content.isVerticallyResizable }) {
|
|
XCTAssertEqual(layout.blockFrames[index].height, height)
|
|
} else {
|
|
XCTFail()
|
|
}
|
|
}
|
|
|
|
func test_WhenHasVerticalDirection_ProducesSummaryHeightAndBlockMaximumWidthContentSizePlusCrossInsets(
|
|
) {
|
|
let layout = GalleryViewLayout(model: Blocks.verticalCenterModel)
|
|
|
|
XCTAssertEqual(layout.contentSize.width, Blocks.contentCrossMaxSize + Blocks.fixedInsets.sum)
|
|
XCTAssertEqual(layout.contentSize.height, Blocks.contentAxialSize)
|
|
}
|
|
|
|
func test_WhenDoesNotHaveBounds_AndVerticalDirection_AppliesResizableBlockWidthToOtherBlocksMaximumWidth(
|
|
) {
|
|
let model = Blocks.verticalCenterModel
|
|
|
|
let layout = GalleryViewLayout(model: model)
|
|
|
|
if let index = model.items.firstIndex(where: { $0.content.isHorizontallyResizable }) {
|
|
XCTAssertEqual(layout.blockFrames[index].width, Blocks.contentCrossMaxSize)
|
|
} else {
|
|
XCTFail()
|
|
}
|
|
}
|
|
|
|
func test_WhenHasBounds_AndVerticalDirection_AppliesResizableBlockWidthToInsetedBoundsWidth() {
|
|
let model = Blocks.verticalCenterModel
|
|
|
|
let layout = GalleryViewLayout(model: model, boundsSize: boundsSize)
|
|
|
|
if let index = model.items.firstIndex(where: { $0.content.isHorizontallyResizable }) {
|
|
XCTAssertEqual(layout.blockFrames[index].width, boundsSize.width - Blocks.fixedInsets.sum)
|
|
} else {
|
|
XCTFail()
|
|
}
|
|
}
|
|
|
|
func test_WhenHasResizableAxialInsets_AndHorizontalDirection_CalculatesContentSizeFittingProvidedSize(
|
|
) {
|
|
let model = Blocks.horizontalResizableModel
|
|
|
|
let layout = GalleryViewLayout(model: model, boundsSize: boundsSize)
|
|
|
|
let expectedSize = Blocks.contentAxialSizeWithoutSideGaps + boundsSize.width - Blocks
|
|
.resizableInsets.maxViewportSize
|
|
XCTAssertEqual(layout.contentSize.width, expectedSize)
|
|
}
|
|
|
|
func test_WhenHasResizableAxialInsets_AndVerticalDirection_CalculatesContentSizeFittingProvidedSize(
|
|
) {
|
|
let model = Blocks.verticalResizableModel
|
|
|
|
let layout = GalleryViewLayout(model: model, boundsSize: boundsSize)
|
|
|
|
let expectedSize = Blocks.contentAxialSizeWithoutSideGaps + boundsSize.height - Blocks
|
|
.resizableInsets.maxViewportSize
|
|
XCTAssertEqual(layout.contentSize.height, expectedSize)
|
|
}
|
|
|
|
func test_WhenHasResizableAxialInsets_AndHorizontalDirection_ProducesSideGapsFittingProvidedSize(
|
|
) {
|
|
let model = Blocks.horizontalResizableModel
|
|
|
|
let layout = GalleryViewLayout(model: model, boundsSize: boundsSize)
|
|
|
|
let expectedInsetValue = (boundsSize.width - Blocks.resizableInsets.maxViewportSize) / 2
|
|
XCTAssertEqual(layout.blockFrames.first?.minX, expectedInsetValue)
|
|
XCTAssertEqual(layout.blockFrames.last?.maxX, layout.contentSize.width - expectedInsetValue)
|
|
}
|
|
|
|
func test_WhenHasResizableAxialInsets_AndVerticalDirection_ProducesSideGapsFittingProvidedSize() {
|
|
let model = Blocks.verticalResizableModel
|
|
|
|
let layout = GalleryViewLayout(model: model, boundsSize: boundsSize)
|
|
|
|
let expectedInsetValue = (boundsSize.height - Blocks.resizableInsets.maxViewportSize) / 2
|
|
XCTAssertEqual(layout.blockFrames.first?.minY, expectedInsetValue)
|
|
XCTAssertEqual(layout.blockFrames.last?.maxY, layout.contentSize.height - expectedInsetValue)
|
|
}
|
|
|
|
func test_WhenHasResizableCrossInsets_AndVerticalDirection_ProducesSideGapsFittingProvidedSize() {
|
|
let model = Blocks.makeModel(
|
|
direction: .vertical,
|
|
metrics: .resizableCross,
|
|
crossAlignment: .leading
|
|
)
|
|
|
|
let layout = GalleryViewLayout(model: model, boundsSize: boundsSize)
|
|
|
|
let expectedInsetValue = (boundsSize.width - Blocks.resizableInsets.maxViewportSize) / 2
|
|
XCTAssertEqual(layout.blockFrames.first?.minX, expectedInsetValue)
|
|
XCTAssertEqual(layout.blockFrames.first?.maxX, layout.contentSize.width - expectedInsetValue)
|
|
}
|
|
|
|
func test_WhenHasResizableCrossInsets_AndHorizontalDirection_ProducesSideGapsFittingProvidedSize(
|
|
) {
|
|
let model = Blocks.makeModel(
|
|
direction: .horizontal,
|
|
metrics: .resizableCross,
|
|
crossAlignment: .leading
|
|
)
|
|
|
|
let layout = GalleryViewLayout(model: model, boundsSize: boundsSize)
|
|
|
|
let expectedInsetValue = (boundsSize.height - Blocks.resizableInsets.maxViewportSize) / 2
|
|
XCTAssertEqual(layout.blockFrames.first?.minY, expectedInsetValue)
|
|
XCTAssertEqual(layout.blockFrames.first?.maxY, layout.contentSize.height - expectedInsetValue)
|
|
}
|
|
|
|
func test_WhenHasHorizontalDirection_StartsLeftEdgeAtFirstGapAndFinishesRightEdgeBeforeLastGap() {
|
|
let layout = GalleryViewLayout(model: Blocks.horizontalCenterModel)
|
|
|
|
XCTAssertEqual(layout.blockFrames.first?.minX, Blocks.gapSize)
|
|
XCTAssertEqual(layout.blockFrames.last?.maxX, Blocks.gapSize + Blocks.framesAxialSize)
|
|
}
|
|
|
|
func test_WhenHasHorizontalDirection_AndCenterVerticalAlignment_LayoutFramesAroundInsetedVerticalCenter(
|
|
) {
|
|
let layout = GalleryViewLayout(model: Blocks.horizontalCenterModel, boundsSize: boundsSize)
|
|
|
|
let center = floor(
|
|
Blocks.fixedInsets
|
|
.leading + (boundsSize.height - Blocks.fixedInsets.sum) / 2
|
|
)
|
|
XCTAssert(layout.blockFrames.allSatisfy { $0.midY.isApproximatelyEqualTo(center) })
|
|
}
|
|
|
|
func test_WhenHasHorizontalDirection_AndLeadingVerticalAlignment_LayoutFramesAboveCrossInsets() {
|
|
let layout = GalleryViewLayout(model: Blocks.horizontalTrailingModel, boundsSize: boundsSize)
|
|
|
|
let trailing = boundsSize.height - Blocks.fixedInsets.trailing
|
|
XCTAssert(layout.blockFrames.allSatisfy { $0.maxY.isApproximatelyEqualTo(trailing) })
|
|
}
|
|
|
|
func test_WhenHasHorizontalDirection_AndTrailingVerticalAlignment_LayoutFramesBelowCrossInsets() {
|
|
let layout = GalleryViewLayout(model: Blocks.horizontalLeadingModel, boundsSize: boundsSize)
|
|
|
|
XCTAssert(
|
|
layout.blockFrames
|
|
.allSatisfy { $0.minY.isApproximatelyEqualTo(Blocks.fixedInsets.leading) }
|
|
)
|
|
}
|
|
|
|
func test_WhenHasVerticalDirection_AndCenterHorizontalAlignment_LayoutFramesAroundInsetedHorizontalCenter(
|
|
) {
|
|
let layout = GalleryViewLayout(model: Blocks.verticalCenterModel, boundsSize: boundsSize)
|
|
|
|
let center = floor(Blocks.fixedInsets.leading + (boundsSize.width - Blocks.fixedInsets.sum) / 2)
|
|
XCTAssert(layout.blockFrames.allSatisfy { $0.midX.isApproximatelyEqualTo(center) })
|
|
}
|
|
|
|
func test_WhenHasVerticalDirection_AndLeadingHorizontalAlignment_LayoutFramesAtLeadingOfCrossInset(
|
|
) {
|
|
let layout = GalleryViewLayout(model: Blocks.verticalLeadingModel, boundsSize: boundsSize)
|
|
|
|
XCTAssert(
|
|
layout.blockFrames
|
|
.allSatisfy { $0.minX.isApproximatelyEqualTo(Blocks.fixedInsets.leading) }
|
|
)
|
|
}
|
|
|
|
func test_WhenHasVerticalDirection_AndTrailingHorizontalAlignment_LayoutFramesAtTrailingOfCrossInset(
|
|
) {
|
|
let layout = GalleryViewLayout(model: Blocks.verticalTrailingModel, boundsSize: boundsSize)
|
|
|
|
let trailing = boundsSize.width - Blocks.fixedInsets.trailing
|
|
XCTAssert(layout.blockFrames.allSatisfy { $0.maxX.isApproximatelyEqualTo(trailing) })
|
|
}
|
|
|
|
func test_WhenHasVerticalDirection_StartsHeightAtFirstGapAndFinishesBeforeLastGap() {
|
|
let layout = GalleryViewLayout(model: Blocks.verticalCenterModel)
|
|
|
|
XCTAssertEqual(layout.blockFrames.first?.minY, Blocks.gapSize)
|
|
XCTAssertEqual(layout.blockFrames.last?.maxY, Blocks.gapSize + Blocks.framesAxialSize)
|
|
}
|
|
|
|
func test_WhenHasPagingModel_ReturnsLastIndexForLastPageOrigin() {
|
|
let layout = GalleryViewLayout(model: Blocks.fixedPagingModel)
|
|
let index = layout.blockFrames.count - 1
|
|
let offset = layout.blockPages[index].origin
|
|
|
|
let pageIndex = layout.pageIndex(forContentOffset: offset)
|
|
|
|
XCTAssertEqual(pageIndex, CGFloat(index), accuracy: accuracy)
|
|
}
|
|
|
|
func test_WhenHasPagingModel_ReturnsZeroIndexForOffsetOutOfRange() {
|
|
let layout = GalleryViewLayout(model: Blocks.fixedPagingModel)
|
|
|
|
XCTAssertEqual(layout.pageIndex(forContentOffset: -1), 0, accuracy: accuracy)
|
|
XCTAssertEqual(layout.pageIndex(forContentOffset: .infinity), 0, accuracy: accuracy)
|
|
}
|
|
|
|
func test_WhenHasFixedPagingModel_ReturnsInitialOffsetForReverseConversion() {
|
|
let layout = GalleryViewLayout(model: Blocks.fixedPagingModel, boundsSize: boundsSize)
|
|
let page = layout.blockPages[2]
|
|
let offset = page.origin + page.size / 2
|
|
let pageIndex = layout.pageIndex(forContentOffset: offset)
|
|
let foundOffset = layout.contentOffset(pageIndex: pageIndex)
|
|
|
|
XCTAssertEqual(offset, foundOffset, accuracy: accuracy)
|
|
}
|
|
|
|
func test_WhenHasAutoPagingModel_ReturnsInitialOffsetForReverseConversion() {
|
|
let layout = GalleryViewLayout(model: Blocks.autoPagingModel, boundsSize: boundsSize)
|
|
let page = layout.blockPages[2]
|
|
let offset = page.origin + page.size / 2
|
|
let pageIndex = layout.pageIndex(forContentOffset: offset)
|
|
let foundOffset = layout.contentOffset(pageIndex: pageIndex)
|
|
|
|
XCTAssertEqual(offset, foundOffset, accuracy: accuracy)
|
|
}
|
|
|
|
func test_WhenHasAutoPagingModel_ReturnsMaxOffsetForLastPage() {
|
|
let layout = GalleryViewLayout(model: Blocks.autoPagingModel, boundsSize: boundsSize)
|
|
let offset = layout.contentOffset(
|
|
pageIndex: CGFloat(layout.blockPages.count - 1)
|
|
)
|
|
let maxOffset = layout.contentSize.width - boundsSize.width
|
|
|
|
XCTAssertEqual(maxOffset, offset, accuracy: accuracy)
|
|
}
|
|
|
|
func test_WhenHasPagingModel_DetectsContainingGreaterOrEqualMinimumAndLowerMaximumWithAccuracy() {
|
|
let layout = GalleryViewLayout(model: Blocks.fixedPagingModel)
|
|
|
|
if let page = layout.blockPages.first {
|
|
let below = page.origin - .leastNonzeroMagnitude
|
|
let middle = page.origin + page.size / 2
|
|
let upper = page.origin + page.size - .leastNonzeroMagnitude
|
|
|
|
XCTAssertTrue(page.contains(below))
|
|
XCTAssertTrue(page.contains(middle))
|
|
XCTAssertFalse(page.contains(upper))
|
|
} else {
|
|
XCTFail()
|
|
}
|
|
}
|
|
|
|
func test_WhenHasPagingModel_ContainsContinuousPages() {
|
|
let layout = GalleryViewLayout(model: Blocks.fixedPagingModel)
|
|
|
|
let totalSpace = (1..<layout.blockPages.count).reduce(CGFloat(0)) { result, index in
|
|
let page = layout.blockPages[index - 1]
|
|
let nextPage = layout.blockPages[index]
|
|
return result + nextPage.origin - (page.origin + page.size)
|
|
}
|
|
XCTAssertEqual(totalSpace, 0, accuracy: accuracy)
|
|
}
|
|
}
|
|
|
|
private enum Blocks {
|
|
private static let horizontallyResizable: Block = SeparatorBlock(direction: .horizontal)
|
|
|
|
private static let verticallyResizable: Block = SeparatorBlock(direction: .vertical)
|
|
|
|
private static let small: Block = try! ContainerBlock(
|
|
layoutDirection: .horizontal,
|
|
widthTrait: .fixed(smallSize),
|
|
heightTrait: .fixed(smallSize),
|
|
children: [verticallyResizable]
|
|
)
|
|
|
|
private static let big: Block = try! ContainerBlock(
|
|
layoutDirection: .horizontal,
|
|
widthTrait: .fixed(bigSize),
|
|
heightTrait: .fixed(bigSize),
|
|
children: [verticallyResizable]
|
|
)
|
|
|
|
static func makeModel(
|
|
direction: GalleryViewModel.Direction = .horizontal,
|
|
metrics: GalleryViewMetrics = .fixed,
|
|
crossAlignment: Alignment = .center,
|
|
scrollMode: GalleryViewModel.ScrollMode = .default
|
|
) -> GalleryViewModel {
|
|
let resizableBlock = direction.isHorizontal ? verticallyResizable : horizontallyResizable
|
|
|
|
let blocks = [Block](repeating: big, times: try! UInt(value: bigCount)) +
|
|
[Block](repeating: small, times: try! UInt(value: smallCount)) +
|
|
[Block](repeating: resizableBlock, times: try! UInt(value: resizableCount))
|
|
|
|
return GalleryViewModel(
|
|
blocks: blocks,
|
|
metrics: metrics,
|
|
scrollMode: scrollMode,
|
|
path: UIElementPath("model"),
|
|
direction: direction,
|
|
crossAlignment: crossAlignment
|
|
)
|
|
}
|
|
|
|
static let smallCount = 2
|
|
static let bigCount = 2
|
|
static let resizableCount = 2
|
|
static let totalCount = bigCount + smallCount + resizableCount
|
|
static let blocksCount = smallCount + bigCount + resizableCount
|
|
static let smallSize = CGFloat(64)
|
|
static let bigSize = CGFloat(128)
|
|
static let resizableSize = CGFloat(1)
|
|
static let gapSize = CGFloat(1)
|
|
static let bigAxialSize = bigSize * CGFloat(bigCount)
|
|
static let smallAxialSize = smallSize * CGFloat(smallCount)
|
|
static let resizableAxialSize = resizableSize * CGFloat(resizableCount)
|
|
static let gapAxialSize = gapSize * CGFloat(blocksCount + 1)
|
|
static let framesAxialSize = bigAxialSize + smallAxialSize + resizableAxialSize + gapSize *
|
|
CGFloat(max(blocksCount - 1, 0))
|
|
static let contentAxialSize = bigAxialSize + smallAxialSize + resizableAxialSize + gapAxialSize
|
|
static let contentAxialSizeWithoutSideGaps = contentAxialSize - 2 * gapSize
|
|
static let contentCrossMaxSize = max(bigSize, smallSize)
|
|
static let horizontalCenterModel = makeModel()
|
|
static let horizontalLeadingModel = makeModel(crossAlignment: .leading)
|
|
static let horizontalTrailingModel = makeModel(crossAlignment: .trailing)
|
|
static let verticalCenterModel = makeModel(direction: .vertical)
|
|
static let verticalLeadingModel = makeModel(
|
|
direction: .vertical,
|
|
crossAlignment: .leading
|
|
)
|
|
static let verticalTrailingModel = makeModel(
|
|
direction: .vertical,
|
|
crossAlignment: .trailing
|
|
)
|
|
static let fixedPagingModel = makeModel(scrollMode: .fixedPaging(pageSize: boundsSize.width))
|
|
static let autoPagingModel = makeModel(scrollMode: .autoPaging)
|
|
static let fixedInsets = SideInsets(leading: 4, trailing: 10)
|
|
static let resizableInsets = InsetMode.Resizable(minValue: 10, maxViewportSize: 14)
|
|
static let horizontalResizableModel = makeModel(metrics: .resizableAxial)
|
|
static let verticalResizableModel = makeModel(
|
|
direction: .vertical,
|
|
metrics: .resizableAxial
|
|
)
|
|
}
|
|
|
|
private let boundsSize = CGSize(width: 64, height: 64)
|
|
private let accuracy: CGFloat = 1e-4
|
|
|
|
extension GalleryViewMetrics {
|
|
fileprivate static let spacings = [CGFloat](
|
|
repeating: Blocks.gapSize,
|
|
times: try! UInt(value: Blocks.totalCount - 1)
|
|
)
|
|
|
|
fileprivate static let resizableAxial = GalleryViewMetrics(
|
|
axialInsetMode: .resizable(params: Blocks.resizableInsets),
|
|
crossInsetMode: .fixed(values: Blocks.fixedInsets),
|
|
spacings: spacings
|
|
)
|
|
|
|
fileprivate static let fixed = GalleryViewMetrics(
|
|
axialInsetMode: .fixed(values: SideInsets(leading: Blocks.gapSize, trailing: Blocks.gapSize)),
|
|
crossInsetMode: .fixed(values: Blocks.fixedInsets),
|
|
spacings: spacings
|
|
)
|
|
|
|
fileprivate static let resizableCross = GalleryViewMetrics(
|
|
axialInsetMode: .fixed(values: Blocks.fixedInsets),
|
|
crossInsetMode: .resizable(params: Blocks.resizableInsets),
|
|
spacings: spacings
|
|
)
|
|
}
|