Use low-level divkit layout implementation
a10e00d445772539a30404f68a1143c3591602bc
@@ -10175,6 +10175,7 @@
|
||||
"client/flutter/divkit/lib/src/core/widgets/image/div_image_widget.dart":"divkit/public/client/flutter/divkit/lib/src/core/widgets/image/div_image_widget.dart",
|
||||
"client/flutter/divkit/lib/src/core/widgets/input/div_input_model.dart":"divkit/public/client/flutter/divkit/lib/src/core/widgets/input/div_input_model.dart",
|
||||
"client/flutter/divkit/lib/src/core/widgets/input/div_input_widget.dart":"divkit/public/client/flutter/divkit/lib/src/core/widgets/input/div_input_widget.dart",
|
||||
"client/flutter/divkit/lib/src/core/widgets/layout/div_layout.dart":"divkit/public/client/flutter/divkit/lib/src/core/widgets/layout/div_layout.dart",
|
||||
"client/flutter/divkit/lib/src/core/widgets/pager/div_pager_model.dart":"divkit/public/client/flutter/divkit/lib/src/core/widgets/pager/div_pager_model.dart",
|
||||
"client/flutter/divkit/lib/src/core/widgets/pager/div_pager_widget.dart":"divkit/public/client/flutter/divkit/lib/src/core/widgets/pager/div_pager_widget.dart",
|
||||
"client/flutter/divkit/lib/src/core/widgets/root/div_root_model.dart":"divkit/public/client/flutter/divkit/lib/src/core/widgets/root/div_root_model.dart",
|
||||
@@ -10337,6 +10338,7 @@
|
||||
"client/flutter/divkit/lib/src/schema/url_value.dart":"divkit/public/client/flutter/divkit/lib/src/schema/url_value.dart",
|
||||
"client/flutter/divkit/lib/src/schema/url_variable.dart":"divkit/public/client/flutter/divkit/lib/src/schema/url_variable.dart",
|
||||
"client/flutter/divkit/lib/src/utils/clockwork.dart":"divkit/public/client/flutter/divkit/lib/src/utils/clockwork.dart",
|
||||
"client/flutter/divkit/lib/src/utils/configuration.dart":"divkit/public/client/flutter/divkit/lib/src/utils/configuration.dart",
|
||||
"client/flutter/divkit/lib/src/utils/content_alignment_converters.dart":"divkit/public/client/flutter/divkit/lib/src/utils/content_alignment_converters.dart",
|
||||
"client/flutter/divkit/lib/src/utils/converters.dart":"divkit/public/client/flutter/divkit/lib/src/utils/converters.dart",
|
||||
"client/flutter/divkit/lib/src/utils/div_focus_node.dart":"divkit/public/client/flutter/divkit/lib/src/utils/div_focus_node.dart",
|
||||
@@ -10344,7 +10346,6 @@
|
||||
"client/flutter/divkit/lib/src/utils/duration_helper.dart":"divkit/public/client/flutter/divkit/lib/src/utils/duration_helper.dart",
|
||||
"client/flutter/divkit/lib/src/utils/parsing_utils.dart":"divkit/public/client/flutter/divkit/lib/src/utils/parsing_utils.dart",
|
||||
"client/flutter/divkit/lib/src/utils/provider.dart":"divkit/public/client/flutter/divkit/lib/src/utils/provider.dart",
|
||||
"client/flutter/divkit/lib/src/utils/size_converters.dart":"divkit/public/client/flutter/divkit/lib/src/utils/size_converters.dart",
|
||||
"client/flutter/divkit/lib/src/utils/tap_builder.dart":"divkit/public/client/flutter/divkit/lib/src/utils/tap_builder.dart",
|
||||
"client/flutter/divkit/lib/src/utils/trace.dart":"divkit/public/client/flutter/divkit/lib/src/utils/trace.dart",
|
||||
"client/flutter/divkit/pubspec.yaml":"divkit/public/client/flutter/divkit/pubspec.yaml",
|
||||
|
||||
@@ -292,6 +292,11 @@ class DartGenerator(Generator):
|
||||
result += f' _index = {i};'
|
||||
result += EMPTY
|
||||
|
||||
# Checker declaration
|
||||
for (i, n) in enumerate(sorted(entity_enumeration.entity_names)):
|
||||
result += f' bool get is{utils.capitalize_camel_case(n)} => _index == {i};'
|
||||
result += EMPTY
|
||||
|
||||
# Preload declaration
|
||||
result += ' Future<void> preload(Map<String, dynamic> context) => value.preload(context);'
|
||||
|
||||
@@ -356,6 +361,12 @@ class DartGenerator(Generator):
|
||||
result += EMPTY
|
||||
result += f' const {full_name}(this.value);'
|
||||
|
||||
# Checker declaration
|
||||
for i in range(cases_len):
|
||||
variant = allowed_name(utils.lower_camel_case(string_enumeration.cases[i][0]))
|
||||
result += f' bool get is{utils.capitalize_camel_case(variant)} => this == {variant};'
|
||||
result += EMPTY
|
||||
|
||||
result += EMPTY
|
||||
result += ' T map<T>({'
|
||||
for i in range(cases_len):
|
||||
|
||||
@@ -293,6 +293,44 @@ class Entity extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 18;
|
||||
|
||||
bool get isEntityWithArray => _index == 0;
|
||||
|
||||
bool get isEntityWithArrayOfEnums => _index == 1;
|
||||
|
||||
bool get isEntityWithArrayOfExpressions => _index == 2;
|
||||
|
||||
bool get isEntityWithArrayOfNestedItems => _index == 3;
|
||||
|
||||
bool get isEntityWithArrayWithTransform => _index == 4;
|
||||
|
||||
bool get isEntityWithComplexProperty => _index == 5;
|
||||
|
||||
bool get isEntityWithComplexPropertyWithDefaultValue => _index == 6;
|
||||
|
||||
bool get isEntityWithEntityProperty => _index == 7;
|
||||
|
||||
bool get isEntityWithOptionalComplexProperty => _index == 8;
|
||||
|
||||
bool get isEntityWithOptionalProperty => _index == 9;
|
||||
|
||||
bool get isEntityWithOptionalStringEnumProperty => _index == 10;
|
||||
|
||||
bool get isEntityWithPropertyWithDefaultValue => _index == 11;
|
||||
|
||||
bool get isEntityWithRawArray => _index == 12;
|
||||
|
||||
bool get isEntityWithRequiredProperty => _index == 13;
|
||||
|
||||
bool get isEntityWithSimpleProperties => _index == 14;
|
||||
|
||||
bool get isEntityWithStringArrayProperty => _index == 15;
|
||||
|
||||
bool get isEntityWithStringEnumProperty => _index == 16;
|
||||
|
||||
bool get isEntityWithStringEnumPropertyWithDefaultValue => _index == 17;
|
||||
|
||||
bool get isEntityWithoutProperties => _index == 18;
|
||||
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
static Entity? fromJson(Map<String, dynamic>? json,) {
|
||||
|
||||
@@ -66,6 +66,10 @@ enum EntityWithArrayOfEnumsItem implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const EntityWithArrayOfEnumsItem(this.value);
|
||||
bool get isFirst => this == first;
|
||||
|
||||
bool get isSecond => this == second;
|
||||
|
||||
|
||||
T map<T>({
|
||||
required T Function() first,
|
||||
|
||||
@@ -66,6 +66,10 @@ enum EntityWithOptionalStringEnumPropertyProperty implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const EntityWithOptionalStringEnumPropertyProperty(this.value);
|
||||
bool get isFirst => this == first;
|
||||
|
||||
bool get isSecond => this == second;
|
||||
|
||||
|
||||
T map<T>({
|
||||
required T Function() first,
|
||||
|
||||
@@ -66,6 +66,10 @@ enum EntityWithStringEnumPropertyProperty implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const EntityWithStringEnumPropertyProperty(this.value);
|
||||
bool get isFirst => this == first;
|
||||
|
||||
bool get isSecond => this == second;
|
||||
|
||||
|
||||
T map<T>({
|
||||
required T Function() first,
|
||||
|
||||
@@ -67,6 +67,12 @@ enum EntityWithStringEnumPropertyWithDefaultValueValue implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const EntityWithStringEnumPropertyWithDefaultValueValue(this.value);
|
||||
bool get isFirst => this == first;
|
||||
|
||||
bool get isSecond => this == second;
|
||||
|
||||
bool get isThird => this == third;
|
||||
|
||||
|
||||
T map<T>({
|
||||
required T Function() first,
|
||||
|
||||
@@ -55,6 +55,10 @@ class EnumWithDefaultType extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 1;
|
||||
|
||||
bool get isWithDefault => _index == 0;
|
||||
|
||||
bool get isWithoutDefault => _index == 1;
|
||||
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
static EnumWithDefaultType? fromJson(Map<String, dynamic>? json,) {
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
## 0.3.1-rc.1
|
||||
## 0.4.0-rc.1
|
||||
|
||||
* Use low-level divkit layout implementation: DivLayout
|
||||
* Optimize pre-calculation of states when switching
|
||||
* Fix sticky switching of states
|
||||
* Fix inner objects in templates breaks rendering
|
||||
* Add support div-text features: font_family, letter_spacing font_weight_value, text_shadow
|
||||
* Add scenario list to testing page
|
||||
* Add handling url in playground editor
|
||||
* Added feature logging management
|
||||
|
||||
|
||||
## Migration 0.3 → 0.4
|
||||
|
||||
* No changes in the public API!
|
||||
* Due to the change in the layout system, we cannot guarantee full compliance with the rendering
|
||||
of the previous version, now we use a lower-level, rather than a composition of standard components.
|
||||
|
||||
## 0.3.0
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ linter:
|
||||
rules:
|
||||
- always_declare_return_types
|
||||
- always_use_package_imports
|
||||
- prefer_expression_function_bodies
|
||||
- require_trailing_commas
|
||||
- prefer_const_constructors
|
||||
- directives_ordering
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:divkit/divkit.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import 'src/app.dart';
|
||||
@@ -11,5 +11,9 @@ void main() {
|
||||
..keepLog = kDebugMode
|
||||
..onLog = print;
|
||||
|
||||
debugPrintDivKitViewLifecycle = true;
|
||||
debugPrintDivExpressionResolve = true;
|
||||
debugPrintDivPerformLayout = true;
|
||||
|
||||
runApp(const ProviderScope(child: PlaygroundApp()));
|
||||
}
|
||||
|
||||
@@ -74,10 +74,12 @@ class _ShowPageState extends ConsumerState<ShowPage> {
|
||||
future: load(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
return DivKitView(
|
||||
key: ObjectKey(reloadN),
|
||||
data: snapshot.requireData,
|
||||
customHandler: PlaygroundAppCustomHandler(),
|
||||
return SingleChildScrollView(
|
||||
child: DivKitView(
|
||||
key: ObjectKey(reloadN),
|
||||
data: snapshot.requireData,
|
||||
customHandler: PlaygroundAppCustomHandler(),
|
||||
),
|
||||
);
|
||||
}
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
|
||||
@@ -1,16 +1,23 @@
|
||||
PODS:
|
||||
- FlutterMacOS (1.0.0)
|
||||
- FMDB (2.7.10):
|
||||
- FMDB/standard (= 2.7.10)
|
||||
- FMDB/standard (2.7.10)
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- sqflite (0.0.3):
|
||||
- Flutter
|
||||
- sqflite (0.0.2):
|
||||
- FlutterMacOS
|
||||
- FMDB (>= 2.7.5)
|
||||
|
||||
DEPENDENCIES:
|
||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/darwin`)
|
||||
- sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- FMDB
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
FlutterMacOS:
|
||||
@@ -18,12 +25,13 @@ EXTERNAL SOURCES:
|
||||
path_provider_foundation:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
|
||||
sqflite:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sqflite/darwin
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
||||
FMDB: eae540775bf7d0c87a5af926ae37af69effe5a19
|
||||
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
|
||||
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
|
||||
sqflite: d0307f984e859ce2bd39b230d672a448ea3f47b4
|
||||
|
||||
PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7
|
||||
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: archive
|
||||
sha256: "80e5141fafcb3361653ce308776cfd7d45e6e9fbb429e14eec571382c0c5fecb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.3.2"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -21,10 +13,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0
|
||||
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.10.0"
|
||||
version: "2.11.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -61,10 +53,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c
|
||||
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
version: "1.3.0"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -77,10 +69,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0
|
||||
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.17.0"
|
||||
version: "1.18.0"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -110,7 +102,7 @@ packages:
|
||||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.3.1-rc.1"
|
||||
version: "0.4.0-rc.1"
|
||||
equatable:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -139,10 +131,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
|
||||
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.4"
|
||||
version: "7.0.0"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@@ -224,14 +216,30 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
js:
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7"
|
||||
name: leak_tracker
|
||||
sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.5"
|
||||
version: "10.0.0"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_flutter_testing
|
||||
sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
leak_tracker_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_testing
|
||||
sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -252,26 +260,26 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72"
|
||||
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.13"
|
||||
version: "0.12.16+1"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
|
||||
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.0"
|
||||
version: "0.8.0"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42"
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.8.0"
|
||||
version: "1.11.0"
|
||||
octo_image:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -284,10 +292,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b
|
||||
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.8.2"
|
||||
version: "1.9.0"
|
||||
path_parsing:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -356,10 +364,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76"
|
||||
sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
version: "3.1.4"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -372,10 +380,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: process
|
||||
sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09"
|
||||
sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.2.4"
|
||||
version: "5.0.2"
|
||||
riverpod:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -401,10 +409,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
|
||||
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
version: "1.10.0"
|
||||
sprintf:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -433,10 +441,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
|
||||
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.11.1"
|
||||
state_notifier:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -449,10 +457,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
|
||||
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.1.2"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -489,10 +497,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206
|
||||
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.4.16"
|
||||
version: "0.6.1"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -553,18 +561,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: e7fb6c2282f7631712b69c19d1bff82f3767eea33a2321c14fa59ad67ea391c7
|
||||
sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.4.0"
|
||||
version: "13.0.0"
|
||||
webdriver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webdriver
|
||||
sha256: ef67178f0cc7e32c1494645b11639dd1335f1d18814aa8435113a92e9ef9d841
|
||||
sha256: "003d7da9519e1e5f329422b36c4dcdf18d7d2978d1ba099ea4e45ba490ed845e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
version: "3.0.3"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -590,5 +598,5 @@ packages:
|
||||
source: hosted
|
||||
version: "6.2.2"
|
||||
sdks:
|
||||
dart: ">=2.19.0 <3.0.0"
|
||||
dart: ">=3.2.0-0 <4.0.0"
|
||||
flutter: ">=3.7.0"
|
||||
|
||||
@@ -19,4 +19,3 @@ export 'src/core/widgets/widgets.dart';
|
||||
export 'src/schema/schema.dart';
|
||||
export 'src/utils/converters.dart';
|
||||
export 'src/utils/parsing_utils.dart';
|
||||
export 'src/utils/size_converters.dart';
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:ui';
|
||||
|
||||
import 'package:divkit/divkit.dart';
|
||||
import 'package:divkit/src/core/widgets/root/div_root_widget.dart';
|
||||
import 'package:divkit/src/utils/configuration.dart';
|
||||
import 'package:divkit/src/utils/div_scaling_model.dart';
|
||||
import 'package:divkit/src/utils/provider.dart';
|
||||
import 'package:divkit/src/utils/trace.dart';
|
||||
@@ -95,9 +96,14 @@ class DivKitView extends StatelessWidget {
|
||||
Widget build(BuildContext context) => Directionality(
|
||||
textDirection: textDirection ?? Directionality.of(context),
|
||||
child: provide(
|
||||
DivScalingModel(textScale: textScale, viewScale: viewScale),
|
||||
DivScalingModel(
|
||||
textScale: textScale,
|
||||
viewScale: viewScale,
|
||||
),
|
||||
child: provide(
|
||||
ShowUnsupportedDivs(showUnsupportedDivs),
|
||||
DivConfiguration(
|
||||
showUnsupportedDivs: showUnsupportedDivs,
|
||||
),
|
||||
child: provide(
|
||||
cacheManager,
|
||||
child: FocusScope(
|
||||
@@ -139,9 +145,6 @@ class _DivKitViewState extends State<_DivKitView> {
|
||||
|
||||
DivContext get divContext => divRootContext!;
|
||||
|
||||
Widget get loader =>
|
||||
widget.loadingBuilder?.call(context) ?? const SizedBox.shrink();
|
||||
|
||||
void updateContext() {
|
||||
if (widget.data.preloaded) {
|
||||
divRootContext = DivRootContext.initSync(
|
||||
@@ -193,6 +196,9 @@ class _DivKitViewState extends State<_DivKitView> {
|
||||
}
|
||||
}
|
||||
|
||||
Widget get loader =>
|
||||
widget.loadingBuilder?.call(context) ?? const SizedBox.shrink();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => divRootContext != null
|
||||
? DivKitProvider(
|
||||
|
||||
@@ -4,6 +4,15 @@ import 'package:divkit/src/core/protocol/div_logger.dart';
|
||||
import 'package:divkit/src/core/protocol/div_variable.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
/// Print logs with information about expression calculations.
|
||||
bool debugPrintDivExpressionResolve = false;
|
||||
|
||||
void _log(String message) {
|
||||
if (debugPrintDivExpressionResolve) {
|
||||
loggerUse(const DefaultDivLoggerContext('onResolve')).debug(message);
|
||||
}
|
||||
}
|
||||
|
||||
final exprResolver = DefaultDivExpressionResolver();
|
||||
|
||||
abstract class DivExpressionResolver {
|
||||
@@ -43,7 +52,7 @@ class DefaultDivExpressionResolver implements DivExpressionResolver {
|
||||
result = expr.parse!(result);
|
||||
}
|
||||
|
||||
logger.debug(
|
||||
_log(
|
||||
"Expr ${expr.source} with args ${context.current}"
|
||||
"and result $result [${result.runtimeType}]",
|
||||
);
|
||||
|
||||
@@ -9,6 +9,15 @@ import 'package:divkit/src/core/variable/variable_manager.dart';
|
||||
import 'package:divkit/src/utils/div_focus_node.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
/// Print logs with information about DivKitView lifecycle.
|
||||
bool debugPrintDivKitViewLifecycle = false;
|
||||
|
||||
void _log(DivLoggerContext? loggerContext, String message) {
|
||||
if (debugPrintDivKitViewLifecycle) {
|
||||
loggerUse(loggerContext).debug(message);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class DivContext {
|
||||
const DivContext();
|
||||
|
||||
@@ -47,7 +56,7 @@ abstract class DivContext {
|
||||
}
|
||||
|
||||
class DivRootContext extends DivContext {
|
||||
BuildContext? _buildContext;
|
||||
final BuildContext? _buildContext;
|
||||
|
||||
@override
|
||||
BuildContext get buildContext => _buildContext!;
|
||||
@@ -140,7 +149,7 @@ class DivRootContext extends DivContext {
|
||||
final divContext = DivRootContext(context);
|
||||
final loggerContext = DefaultDivLoggerContext(source.logId);
|
||||
|
||||
loggerUse(loggerContext).debug('Init [Async] ${divContext.hashCode}');
|
||||
_log(loggerContext, 'Async init #${divContext.hashCode}');
|
||||
|
||||
// Main initialization
|
||||
divContext
|
||||
@@ -171,7 +180,7 @@ class DivRootContext extends DivContext {
|
||||
.toList(growable: false),
|
||||
);
|
||||
|
||||
loggerUse(loggerContext).debug('Prepared ${divContext.hashCode}');
|
||||
_log(loggerContext, 'Prepared #${divContext.hashCode}');
|
||||
return divContext;
|
||||
}
|
||||
|
||||
@@ -194,8 +203,9 @@ class DivRootContext extends DivContext {
|
||||
final divContext = DivRootContext(context);
|
||||
final loggerContext = DefaultDivLoggerContext(source.logId);
|
||||
|
||||
loggerUse(loggerContext).debug('Init [Sync] ${divContext.hashCode}');
|
||||
loggerUse(loggerContext).debug('Instant rendering is enabled!');
|
||||
_log(loggerContext, 'Sync init #${divContext.hashCode}');
|
||||
_log(loggerContext,
|
||||
'Instant rendering is enabled! #${divContext.hashCode}');
|
||||
|
||||
// Main initialization
|
||||
divContext
|
||||
@@ -226,7 +236,7 @@ class DivRootContext extends DivContext {
|
||||
.toList(growable: false),
|
||||
);
|
||||
|
||||
loggerUse(loggerContext).debug('Prepared ${divContext.hashCode}');
|
||||
_log(loggerContext, 'Prepared #${divContext.hashCode}');
|
||||
return divContext;
|
||||
}
|
||||
|
||||
@@ -242,7 +252,7 @@ class DivRootContext extends DivContext {
|
||||
}
|
||||
|
||||
Future<void> dispose() async {
|
||||
loggerUse(_loggerContext).debug("Dispose $hashCode");
|
||||
_log(_loggerContext, "Dispose #$hashCode");
|
||||
|
||||
_stateManager?.dispose();
|
||||
_visibilityActionManager?.dispose();
|
||||
|
||||
@@ -6,9 +6,11 @@ import 'package:flutter/widgets.dart';
|
||||
|
||||
class DivBaseModel with EquatableMixin {
|
||||
final double opacity;
|
||||
final bool isGone;
|
||||
final DivAlignment alignment;
|
||||
final PassDivSize width;
|
||||
final PassDivSize height;
|
||||
final DivSizeValue width;
|
||||
final DivSizeValue height;
|
||||
final double? aspect;
|
||||
final EdgeInsetsGeometry? padding;
|
||||
final EdgeInsetsGeometry? margin;
|
||||
final DivDecoration? decoration;
|
||||
@@ -23,18 +25,21 @@ class DivBaseModel with EquatableMixin {
|
||||
required this.alignment,
|
||||
required this.focusDecoration,
|
||||
required this.divVisibility,
|
||||
required this.isGone,
|
||||
this.opacity = 1.0,
|
||||
this.visibilityActions = const [],
|
||||
this.padding,
|
||||
this.margin,
|
||||
this.aspect,
|
||||
this.decoration,
|
||||
this.divId,
|
||||
});
|
||||
|
||||
static DivBaseModel? value(
|
||||
BuildContext context,
|
||||
DivBase data,
|
||||
) {
|
||||
DivBase data, [
|
||||
Expression<double>? aspect,
|
||||
]) {
|
||||
final divScalingModel = read<DivScalingModel>(context);
|
||||
final viewScale = divScalingModel?.viewScale ?? 1;
|
||||
|
||||
@@ -56,17 +61,16 @@ class DivBaseModel with EquatableMixin {
|
||||
}
|
||||
|
||||
return DivBaseModel(
|
||||
isGone: data.visibility.requireValue.isGone,
|
||||
opacity: data.valueOpacity().clamp(0.0, 1.0),
|
||||
alignment: PassDivAlignment(
|
||||
data.alignmentVertical,
|
||||
data.alignmentHorizontal,
|
||||
).valueAlignment(),
|
||||
width: data.valueWidth(
|
||||
extension: margin.horizontal,
|
||||
viewScale: viewScale,
|
||||
),
|
||||
height: data.valueHeight(
|
||||
extension: margin.vertical,
|
||||
viewScale: viewScale,
|
||||
),
|
||||
visibilityActions: visibilityActionsList,
|
||||
@@ -74,6 +78,7 @@ class DivBaseModel with EquatableMixin {
|
||||
viewScale: viewScale,
|
||||
),
|
||||
margin: margin,
|
||||
aspect: aspect?.requireValue,
|
||||
decoration: data.valueBoxDecoration(
|
||||
viewScale: viewScale,
|
||||
),
|
||||
@@ -95,8 +100,9 @@ class DivBaseModel with EquatableMixin {
|
||||
|
||||
static Stream<DivBaseModel> from(
|
||||
BuildContext context,
|
||||
DivBase data,
|
||||
) {
|
||||
DivBase data, [
|
||||
Expression<double>? aspect,
|
||||
]) {
|
||||
final variables = watch<DivContext>(context)!.variableManager;
|
||||
final divScalingModel = watch<DivScalingModel>(context);
|
||||
final viewScale = divScalingModel?.viewScale ?? 1;
|
||||
@@ -125,6 +131,7 @@ class DivBaseModel with EquatableMixin {
|
||||
}
|
||||
|
||||
return DivBaseModel(
|
||||
isGone: (await data.visibility.resolveValue(context: context)).isGone,
|
||||
opacity: (await data.resolveOpacity(
|
||||
context: context,
|
||||
))
|
||||
@@ -137,12 +144,10 @@ class DivBaseModel with EquatableMixin {
|
||||
),
|
||||
width: await data.resolveWidth(
|
||||
context: context,
|
||||
extension: margin.horizontal,
|
||||
viewScale: viewScale,
|
||||
),
|
||||
height: await data.resolveHeight(
|
||||
context: context,
|
||||
extension: margin.vertical,
|
||||
viewScale: viewScale,
|
||||
),
|
||||
visibilityActions: visibilityActionsList,
|
||||
@@ -151,6 +156,9 @@ class DivBaseModel with EquatableMixin {
|
||||
viewScale: viewScale,
|
||||
),
|
||||
margin: margin,
|
||||
aspect: await aspect?.resolveValue(
|
||||
context: context,
|
||||
),
|
||||
decoration: await data.resolveBoxDecoration(
|
||||
context: context,
|
||||
viewScale: viewScale,
|
||||
@@ -174,6 +182,7 @@ class DivBaseModel with EquatableMixin {
|
||||
alignment,
|
||||
width,
|
||||
height,
|
||||
aspect,
|
||||
padding,
|
||||
margin,
|
||||
decoration,
|
||||
@@ -335,78 +344,50 @@ extension PassDivBase on DivBase {
|
||||
Future<double> resolveOpacity({
|
||||
required DivVariableContext context,
|
||||
}) async {
|
||||
final opacity = (await visibility.resolveValue(context: context)).asOpacity;
|
||||
if (opacity != 1) {
|
||||
final visibility = (await this.visibility.resolveValue(context: context));
|
||||
if (!visibility.isVisible) {
|
||||
return 0;
|
||||
}
|
||||
return await alpha.resolveValue(context: context);
|
||||
}
|
||||
|
||||
double valueOpacity() {
|
||||
final opacity = visibility.value!.asOpacity;
|
||||
if (opacity != 1) {
|
||||
final visibility = this.visibility.requireValue;
|
||||
if (!visibility.isVisible) {
|
||||
return 0;
|
||||
}
|
||||
return alpha.value!;
|
||||
return alpha.requireValue;
|
||||
}
|
||||
|
||||
Future<PassDivSize> resolveWidth({
|
||||
Future<DivSizeValue> resolveWidth({
|
||||
required DivVariableContext context,
|
||||
required double viewScale,
|
||||
double extension = 0,
|
||||
}) async {
|
||||
if ((await visibility.resolveValue(context: context)).isGone) {
|
||||
return const FixedDivSize(0);
|
||||
} else {
|
||||
return await width.resolve(
|
||||
}) async =>
|
||||
await width.resolve(
|
||||
context: context,
|
||||
extension: extension,
|
||||
viewScale: viewScale,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
PassDivSize valueWidth({
|
||||
DivSizeValue valueWidth({
|
||||
required double viewScale,
|
||||
double extension = 0,
|
||||
}) {
|
||||
if (visibility.value!.isGone) {
|
||||
return const FixedDivSize(0);
|
||||
} else {
|
||||
return width.passValue(
|
||||
extension: extension,
|
||||
}) =>
|
||||
width.passValue(
|
||||
viewScale: viewScale,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<PassDivSize> resolveHeight({
|
||||
Future<DivSizeValue> resolveHeight({
|
||||
required DivVariableContext context,
|
||||
required double viewScale,
|
||||
double extension = 0,
|
||||
}) async {
|
||||
if ((await visibility.resolveValue(context: context)).isGone) {
|
||||
return const FixedDivSize(0);
|
||||
} else {
|
||||
return await height.resolve(
|
||||
}) async =>
|
||||
await height.resolve(
|
||||
context: context,
|
||||
extension: extension,
|
||||
viewScale: viewScale,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
PassDivSize valueHeight({
|
||||
DivSizeValue valueHeight({
|
||||
required double viewScale,
|
||||
double extension = 0,
|
||||
}) {
|
||||
if (visibility.value!.isGone) {
|
||||
return const FixedDivSize(0);
|
||||
} else {
|
||||
return height.passValue(
|
||||
extension: extension,
|
||||
}) =>
|
||||
height.passValue(
|
||||
viewScale: viewScale,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import 'package:divkit/divkit.dart';
|
||||
import 'package:divkit/src/core/widgets/base/div_base_model.dart';
|
||||
import 'package:divkit/src/core/widgets/div_visibility_emitter.dart';
|
||||
import 'package:divkit/src/utils/content_alignment_converters.dart';
|
||||
import 'package:divkit/src/utils/div_focus_node.dart';
|
||||
import 'package:divkit/src/utils/provider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class DivBaseWidget extends StatefulWidget {
|
||||
@@ -11,6 +9,8 @@ class DivBaseWidget extends StatefulWidget {
|
||||
|
||||
final DivTapActionData? tapActionData;
|
||||
|
||||
final Expression<double>? aspect;
|
||||
|
||||
final Widget child;
|
||||
|
||||
const DivBaseWidget({
|
||||
@@ -18,6 +18,7 @@ class DivBaseWidget extends StatefulWidget {
|
||||
super.key,
|
||||
required this.child,
|
||||
this.tapActionData,
|
||||
this.aspect,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -34,14 +35,14 @@ class _DivBaseWidgetState extends State<DivBaseWidget> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
value = DivBaseModel.value(context, widget.data);
|
||||
value = DivBaseModel.value(context, widget.data, widget.aspect);
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
|
||||
stream ??= DivBaseModel.from(context, widget.data);
|
||||
stream ??= DivBaseModel.from(context, widget.data, widget.aspect);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -49,8 +50,8 @@ class _DivBaseWidgetState extends State<DivBaseWidget> {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
|
||||
if (widget.data != oldWidget.data) {
|
||||
value = DivBaseModel.value(context, widget.data);
|
||||
stream = DivBaseModel.from(context, widget.data);
|
||||
value = DivBaseModel.value(context, widget.data, widget.aspect);
|
||||
stream = DivBaseModel.from(context, widget.data, widget.aspect);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,15 +63,17 @@ class _DivBaseWidgetState extends State<DivBaseWidget> {
|
||||
if (snapshot.hasData) {
|
||||
final model = snapshot.requireData;
|
||||
final focusNode = FocusScope.of(context).getById(model.divId);
|
||||
final parent = watch<DivParentData>(context);
|
||||
final contentAlignment = watch<ContentAlignment>(context);
|
||||
|
||||
return DivSizeWrapper(
|
||||
parent: parent,
|
||||
contentAlignment: contentAlignment,
|
||||
if (model.isGone) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return DivLayout(
|
||||
height: model.height,
|
||||
width: model.width,
|
||||
alignment: model.alignment,
|
||||
margin: model.margin,
|
||||
aspect: model.aspect,
|
||||
alignment: model.alignment.asAlignment,
|
||||
child: DivVisibilityEmitter(
|
||||
visibilityActions: model.visibilityActions,
|
||||
divVisibility: model.divVisibility,
|
||||
@@ -85,23 +88,17 @@ class _DivBaseWidgetState extends State<DivBaseWidget> {
|
||||
builder: (_, __) => _DecoratedBox(
|
||||
key: key,
|
||||
padding: model.padding,
|
||||
margin: model.margin,
|
||||
decoration: focusNode.hasFocus
|
||||
? model.focusDecoration
|
||||
: model.decoration,
|
||||
child: RepaintBoundary(
|
||||
child: widget.child,
|
||||
),
|
||||
child: widget.child,
|
||||
),
|
||||
)
|
||||
: _DecoratedBox(
|
||||
key: key,
|
||||
padding: model.padding,
|
||||
margin: model.margin,
|
||||
decoration: model.decoration,
|
||||
child: RepaintBoundary(
|
||||
child: widget.child,
|
||||
),
|
||||
child: widget.child,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -121,15 +118,98 @@ class _DivBaseWidgetState extends State<DivBaseWidget> {
|
||||
}
|
||||
}
|
||||
|
||||
extension PassDivSizeImpl on DivSize {
|
||||
Future<DivSizeValue> resolve({
|
||||
required DivVariableContext context,
|
||||
required double viewScale,
|
||||
}) async =>
|
||||
map(
|
||||
divFixedSize: (fixed) async => DivFixed(
|
||||
await fixed.resolveDimension(
|
||||
context: context,
|
||||
viewScale: viewScale,
|
||||
),
|
||||
),
|
||||
divMatchParentSize: (flex) async => DivMatchParent(
|
||||
(await flex.weight?.resolveValue(context: context))?.toInt(),
|
||||
),
|
||||
divWrapContentSize: (wrapped) async {
|
||||
final constrained = await wrapped.constrained?.resolveValue(
|
||||
context: context,
|
||||
) ??
|
||||
false;
|
||||
|
||||
if (!constrained) {
|
||||
return DivWrapContent(
|
||||
min: await wrapped.minSize?.resolveDimension(
|
||||
context: context,
|
||||
viewScale: viewScale,
|
||||
),
|
||||
max: await wrapped.maxSize?.resolveDimension(
|
||||
context: context,
|
||||
viewScale: viewScale,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return DivConstrained(
|
||||
min: await wrapped.minSize?.resolveDimension(
|
||||
context: context,
|
||||
viewScale: viewScale,
|
||||
),
|
||||
max: await wrapped.maxSize?.resolveDimension(
|
||||
context: context,
|
||||
viewScale: viewScale,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
DivSizeValue passValue({
|
||||
required double viewScale,
|
||||
}) =>
|
||||
map(
|
||||
divFixedSize: (fixed) => DivFixed(
|
||||
fixed.valueDimension(
|
||||
viewScale: viewScale,
|
||||
),
|
||||
),
|
||||
divMatchParentSize: (flex) => DivMatchParent(
|
||||
flex.weight?.requireValue.toInt(),
|
||||
),
|
||||
divWrapContentSize: (wrapped) {
|
||||
final constrained = wrapped.constrained?.requireValue ?? false;
|
||||
|
||||
if (!constrained) {
|
||||
return DivWrapContent(
|
||||
min: wrapped.minSize?.valueDimension(
|
||||
viewScale: viewScale,
|
||||
),
|
||||
max: wrapped.maxSize?.valueDimension(
|
||||
viewScale: viewScale,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return DivConstrained(
|
||||
min: wrapped.minSize?.valueDimension(
|
||||
viewScale: viewScale,
|
||||
),
|
||||
max: wrapped.maxSize?.valueDimension(
|
||||
viewScale: viewScale,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
class _DecoratedBox extends StatelessWidget {
|
||||
final DivDecoration? decoration;
|
||||
final Widget child;
|
||||
final EdgeInsetsGeometry? padding;
|
||||
final EdgeInsetsGeometry? margin;
|
||||
|
||||
const _DecoratedBox({
|
||||
required this.child,
|
||||
this.margin,
|
||||
this.padding,
|
||||
this.decoration,
|
||||
super.key,
|
||||
@@ -138,36 +218,33 @@ class _DecoratedBox extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final backgroundWidgets = decoration?.backgroundWidgets ?? <Widget>[];
|
||||
return Container(
|
||||
margin: margin,
|
||||
child: CustomPaint(
|
||||
painter: _OuterShadowPainter(
|
||||
outerShadow: decoration?.outerShadow,
|
||||
borderRadiusCustom: decoration?.customBorderRadius,
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: decoration?.customBorderRadius.toBorderRadius() ??
|
||||
BorderRadius.zero,
|
||||
child: Stack(
|
||||
fit: StackFit.passthrough,
|
||||
children: [
|
||||
...backgroundWidgets
|
||||
.map(
|
||||
(widget) => Positioned.fill(
|
||||
child: widget,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: decoration?.customBorderRadius.toBorderRadius(),
|
||||
border: decoration?.boxDecoration.border,
|
||||
),
|
||||
padding: padding,
|
||||
child: child,
|
||||
return CustomPaint(
|
||||
painter: _OuterShadowPainter(
|
||||
outerShadow: decoration?.outerShadow,
|
||||
borderRadiusCustom: decoration?.customBorderRadius,
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: decoration?.customBorderRadius.toBorderRadius() ??
|
||||
BorderRadius.zero,
|
||||
child: Stack(
|
||||
fit: StackFit.passthrough,
|
||||
children: [
|
||||
...backgroundWidgets
|
||||
.map(
|
||||
(widget) => Positioned.fill(
|
||||
child: widget,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: decoration?.customBorderRadius.toBorderRadius(),
|
||||
border: decoration?.boxDecoration.border,
|
||||
),
|
||||
],
|
||||
),
|
||||
padding: padding,
|
||||
child: child,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -7,12 +7,10 @@ import 'package:flutter/widgets.dart';
|
||||
class DivContainerModel with EquatableMixin {
|
||||
final List<Widget> children;
|
||||
final ContentAlignment contentAlignment;
|
||||
final double? aspectRatio;
|
||||
|
||||
const DivContainerModel({
|
||||
required this.contentAlignment,
|
||||
this.children = const [],
|
||||
this.aspectRatio,
|
||||
});
|
||||
|
||||
static DivContainerModel? value(
|
||||
@@ -29,7 +27,6 @@ class DivContainerModel with EquatableMixin {
|
||||
|
||||
return DivContainerModel(
|
||||
contentAlignment: contentAlignment,
|
||||
aspectRatio: data.aspect?.ratio.requireValue,
|
||||
children: data.items
|
||||
?.map(
|
||||
(e) => DivWidget(e),
|
||||
@@ -65,9 +62,6 @@ class DivContainerModel with EquatableMixin {
|
||||
|
||||
return DivContainerModel(
|
||||
contentAlignment: contentAlignment,
|
||||
aspectRatio: await data.aspect?.ratio.resolveValue(
|
||||
context: context,
|
||||
),
|
||||
children: data.items
|
||||
?.map(
|
||||
(e) => DivWidget(e),
|
||||
@@ -82,6 +76,5 @@ class DivContainerModel with EquatableMixin {
|
||||
List<Object?> get props => [
|
||||
children,
|
||||
contentAlignment,
|
||||
aspectRatio,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ class _DivContainerWidgetState extends State<DivContainerWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) => DivBaseWidget(
|
||||
data: widget.data,
|
||||
aspect: widget.data.aspect?.ratio,
|
||||
tapActionData: DivTapActionData(
|
||||
action: widget.data.action,
|
||||
actions: widget.data.actions,
|
||||
@@ -57,46 +58,38 @@ class _DivContainerWidgetState extends State<DivContainerWidget> {
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
final model = snapshot.requireData;
|
||||
final mainWidget = provide(
|
||||
model.contentAlignment,
|
||||
child: model.contentAlignment.map(
|
||||
flex: (data) => provide(
|
||||
DivParentData.flex,
|
||||
child: Flex(
|
||||
direction: data.direction,
|
||||
mainAxisAlignment: data.mainAxisAlignment,
|
||||
crossAxisAlignment: data.crossAxisAlignment,
|
||||
children: model.children,
|
||||
),
|
||||
final mainWidget = model.contentAlignment.map(
|
||||
flex: (data) => provide(
|
||||
data.direction == Axis.vertical
|
||||
? DivParentData.column
|
||||
: DivParentData.row,
|
||||
child: Flex(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
direction: data.direction,
|
||||
mainAxisAlignment: data.mainAxisAlignment,
|
||||
crossAxisAlignment: data.crossAxisAlignment,
|
||||
children: model.children,
|
||||
),
|
||||
wrap: (data) => provide(
|
||||
DivParentData.wrap,
|
||||
child: Wrap(
|
||||
direction: data.direction,
|
||||
alignment: data.wrapAlignment,
|
||||
runAlignment: data.runAlignment,
|
||||
children: model.children,
|
||||
),
|
||||
),
|
||||
wrap: (data) => provide(
|
||||
DivParentData.wrap,
|
||||
child: Wrap(
|
||||
direction: data.direction,
|
||||
alignment: data.wrapAlignment,
|
||||
runAlignment: data.runAlignment,
|
||||
children: model.children,
|
||||
),
|
||||
stack: (data) => provide(
|
||||
DivParentData.stack,
|
||||
child: Stack(
|
||||
alignment: data.contentAlignment ??
|
||||
AlignmentDirectional.topStart,
|
||||
children: model.children,
|
||||
),
|
||||
),
|
||||
stack: (data) => provide(
|
||||
DivParentData.stack,
|
||||
child: Stack(
|
||||
alignment:
|
||||
data.contentAlignment ?? AlignmentDirectional.topStart,
|
||||
children: model.children,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final aspect = model.aspectRatio;
|
||||
if (aspect != null) {
|
||||
return AspectRatio(
|
||||
aspectRatio: aspect,
|
||||
child: mainWidget,
|
||||
);
|
||||
}
|
||||
|
||||
return mainWidget;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
import 'package:divkit/divkit.dart';
|
||||
import 'package:divkit/src/utils/configuration.dart';
|
||||
|
||||
import 'package:divkit/src/utils/provider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Configuration model.
|
||||
class ShowUnsupportedDivs {
|
||||
final bool enabled;
|
||||
|
||||
const ShowUnsupportedDivs(this.enabled);
|
||||
}
|
||||
|
||||
class DivErrorWidget extends StatelessWidget {
|
||||
static const errorColor = Color(0xFFFF0000);
|
||||
|
||||
@@ -24,7 +18,7 @@ class DivErrorWidget extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) =>
|
||||
watch<ShowUnsupportedDivs>(context)?.enabled ?? false
|
||||
watch<DivConfiguration>(context)?.showUnsupportedDivs ?? false
|
||||
? DivBaseWidget(
|
||||
data: data,
|
||||
child: Placeholder(
|
||||
|
||||
@@ -22,6 +22,7 @@ class DivVisibilityEmitter extends StatelessWidget {
|
||||
final isVisible = divVisibility == DivVisibility.visible;
|
||||
return Visibility(
|
||||
visible: isVisible,
|
||||
replacement: IgnorePointer(child: child),
|
||||
child: IgnorePointer(
|
||||
ignoring: !isVisible,
|
||||
child: _DivVisibilityActionEmitter(
|
||||
@@ -98,9 +99,7 @@ class _DivVisibilityActionEmitterState
|
||||
}
|
||||
|
||||
return VisibilityDetector(
|
||||
key: ValueKey(
|
||||
widget.id,
|
||||
),
|
||||
key: ValueKey(widget.id),
|
||||
child: widget.child,
|
||||
onVisibilityChanged: (VisibilityInfo info) {
|
||||
divContext.visibilityActionManager.updateActionsStateIfNeed(
|
||||
|
||||
@@ -72,19 +72,15 @@ class _DivGalleryWidgetState extends State<DivGalleryWidget> {
|
||||
|
||||
return SingleChildScrollView(
|
||||
scrollDirection: model.orientation,
|
||||
child: isHorizontal
|
||||
? provide(
|
||||
DivParentData.flex,
|
||||
child: Row(
|
||||
children: childrenWithSpacing,
|
||||
),
|
||||
)
|
||||
: provide(
|
||||
DivParentData.flex,
|
||||
child: Column(
|
||||
children: childrenWithSpacing,
|
||||
),
|
||||
),
|
||||
child: provide(
|
||||
isHorizontal ? DivParentData.row : DivParentData.column,
|
||||
child: Flex(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
direction: isHorizontal ? Axis.horizontal : Axis.vertical,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: childrenWithSpacing,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ class DivImageModel with EquatableMixin {
|
||||
final Color? color;
|
||||
final BlendMode? colorBlendMode;
|
||||
final AlignmentGeometry contentAlignment;
|
||||
final double? aspectRatio;
|
||||
final double? blurRadius;
|
||||
final bool rtlMirror;
|
||||
|
||||
@@ -21,7 +20,6 @@ class DivImageModel with EquatableMixin {
|
||||
required this.rtlMirror,
|
||||
this.color,
|
||||
this.colorBlendMode,
|
||||
this.aspectRatio,
|
||||
this.blurRadius,
|
||||
});
|
||||
|
||||
@@ -50,7 +48,6 @@ class DivImageModel with EquatableMixin {
|
||||
color: data.tintColor?.value!,
|
||||
colorBlendMode: data.tintMode.value!.asBlendMode,
|
||||
contentAlignment: alignment,
|
||||
aspectRatio: data.aspect?.ratio.requireValue,
|
||||
blurRadius: filters.blurRadius == null
|
||||
? null
|
||||
: (filters.blurRadius ?? 0) * viewScale,
|
||||
@@ -107,9 +104,6 @@ class DivImageModel with EquatableMixin {
|
||||
context: context,
|
||||
) ??
|
||||
Alignment.center,
|
||||
aspectRatio: await data.aspect?.ratio.resolveValue(
|
||||
context: context,
|
||||
),
|
||||
blurRadius: filters.blurRadius == null
|
||||
? null
|
||||
: (filters.blurRadius ?? 0) * viewScale,
|
||||
@@ -125,7 +119,6 @@ class DivImageModel with EquatableMixin {
|
||||
color,
|
||||
colorBlendMode,
|
||||
contentAlignment,
|
||||
aspectRatio,
|
||||
blurRadius,
|
||||
rtlMirror,
|
||||
];
|
||||
|
||||
@@ -54,6 +54,7 @@ class _DivImageWidgetState extends State<DivImageWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) => DivBaseWidget(
|
||||
data: widget.data,
|
||||
aspect: widget.data.aspect?.ratio,
|
||||
tapActionData: DivTapActionData(
|
||||
action: widget.data.action,
|
||||
actions: widget.data.actions,
|
||||
@@ -120,8 +121,6 @@ class _DivImageWidgetState extends State<DivImageWidget> {
|
||||
}
|
||||
}
|
||||
|
||||
final aspect = model.aspectRatio;
|
||||
|
||||
final Widget blurredImage;
|
||||
final blurRadius = model.blurRadius;
|
||||
if (blurRadius != null) {
|
||||
@@ -147,13 +146,6 @@ class _DivImageWidgetState extends State<DivImageWidget> {
|
||||
mirroredImage = blurredImage;
|
||||
}
|
||||
|
||||
if (aspect != null) {
|
||||
return AspectRatio(
|
||||
aspectRatio: aspect,
|
||||
child: mirroredImage,
|
||||
);
|
||||
}
|
||||
|
||||
return mirroredImage;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,523 @@
|
||||
import 'package:divkit/src/core/protocol/div_logger.dart';
|
||||
import 'package:divkit/src/utils/provider.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
/// Print logs with information about constraints and div sizes.
|
||||
bool debugPrintDivPerformLayout = false;
|
||||
|
||||
void _log(String message) {
|
||||
if (debugPrintDivPerformLayout) {
|
||||
loggerUse(const DefaultDivLoggerContext('onLayout')).debug(message);
|
||||
}
|
||||
}
|
||||
|
||||
/// Layout size parameters.
|
||||
class DivLayoutParam {
|
||||
final DivSizeValue width;
|
||||
final DivSizeValue height;
|
||||
|
||||
const DivLayoutParam({
|
||||
this.width = const DivMatchParent(),
|
||||
this.height = const DivWrapContent(),
|
||||
});
|
||||
|
||||
DivLayoutParam copyWith({
|
||||
DivSizeValue? width,
|
||||
DivSizeValue? height,
|
||||
}) =>
|
||||
DivLayoutParam(
|
||||
width: width ?? this.width,
|
||||
height: height ?? this.height,
|
||||
);
|
||||
|
||||
@override
|
||||
String toString() => 'DivLayoutParam($width, $height)';
|
||||
}
|
||||
|
||||
/// The type of the parent container.
|
||||
enum DivParentData {
|
||||
none,
|
||||
wrap,
|
||||
column,
|
||||
row,
|
||||
stack,
|
||||
pager;
|
||||
|
||||
bool get isWrap => this == DivParentData.wrap;
|
||||
|
||||
bool get isColumn => this == DivParentData.column;
|
||||
|
||||
bool get isRow => this == DivParentData.row;
|
||||
|
||||
bool get isStack => this == DivParentData.stack;
|
||||
|
||||
bool get isPager => this == DivParentData.pager;
|
||||
}
|
||||
|
||||
/// Generalization of divkit sizes.
|
||||
abstract class DivSizeValue {
|
||||
const DivSizeValue();
|
||||
|
||||
T map<T>({
|
||||
required Function(double value) fixed,
|
||||
required Function(double? min, double? max) wrapContent,
|
||||
required Function(int weight) matchParent,
|
||||
required Function(double? min, double? max) constrained,
|
||||
});
|
||||
|
||||
bool get isFixed => false;
|
||||
|
||||
bool get isWrapContent => false;
|
||||
|
||||
bool get isMatchParent => false;
|
||||
|
||||
bool get isConstrained => false;
|
||||
}
|
||||
|
||||
/// Force setting the size.
|
||||
class DivFixed extends DivSizeValue {
|
||||
final double value;
|
||||
|
||||
const DivFixed(this.value);
|
||||
|
||||
@override
|
||||
T map<T>({
|
||||
required Function(double value) fixed,
|
||||
required Function(double? min, double? max) wrapContent,
|
||||
required Function(int weight) matchParent,
|
||||
required Function(double? min, double? max) constrained,
|
||||
}) =>
|
||||
fixed(value);
|
||||
|
||||
@override
|
||||
bool get isFixed => true;
|
||||
|
||||
@override
|
||||
String toString() => 'fixed($value)';
|
||||
}
|
||||
|
||||
/// Allow the child to be the size it wants and
|
||||
/// specify the constants within which expects it.
|
||||
/// Unlike [DivConstrained] allows overflows!
|
||||
class DivWrapContent extends DivSizeValue {
|
||||
final double? min;
|
||||
final double? max;
|
||||
|
||||
const DivWrapContent({
|
||||
this.min,
|
||||
this.max,
|
||||
});
|
||||
|
||||
@override
|
||||
T map<T>({
|
||||
required Function(double value) fixed,
|
||||
required Function(double? min, double? max) wrapContent,
|
||||
required Function(int weight) matchParent,
|
||||
required Function(double? min, double? max) constrained,
|
||||
}) =>
|
||||
wrapContent(min, max);
|
||||
|
||||
@override
|
||||
bool get isWrapContent => true;
|
||||
|
||||
@override
|
||||
String toString() => 'wrapContent';
|
||||
}
|
||||
|
||||
/// Force the maximum size of the parent for the child,
|
||||
/// but we can still specify the weight in [Flex].
|
||||
class DivMatchParent extends DivSizeValue {
|
||||
final int? weight;
|
||||
|
||||
const DivMatchParent([this.weight = 1]);
|
||||
|
||||
@override
|
||||
T map<T>({
|
||||
required Function(double value) fixed,
|
||||
required Function(double? min, double? max) wrapContent,
|
||||
required Function(int weight) matchParent,
|
||||
required Function(double? min, double? max) constrained,
|
||||
}) =>
|
||||
matchParent(weight ?? 1);
|
||||
|
||||
@override
|
||||
bool get isMatchParent => true;
|
||||
|
||||
@override
|
||||
String toString() => 'matchParent(${weight ?? 1})';
|
||||
}
|
||||
|
||||
/// Like that [DivWrapContent], but doesn't allow overflowing at all.
|
||||
class DivConstrained extends DivSizeValue {
|
||||
final double? min;
|
||||
final double? max;
|
||||
|
||||
const DivConstrained({
|
||||
this.min,
|
||||
this.max,
|
||||
});
|
||||
|
||||
@override
|
||||
T map<T>({
|
||||
required Function(double value) fixed,
|
||||
required Function(double? min, double? max) wrapContent,
|
||||
required Function(int weight) matchParent,
|
||||
required Function(double? min, double? max) constrained,
|
||||
}) =>
|
||||
constrained(min, max);
|
||||
|
||||
@override
|
||||
bool get isConstrained => true;
|
||||
|
||||
@override
|
||||
String toString() => 'constrained($min, $max))';
|
||||
}
|
||||
|
||||
/// A unit of a divkit layout system that tries to integrate into an existing one in Flutter.
|
||||
///
|
||||
/// All the necessary data about the parent and child are collected here
|
||||
/// and it can forcibly change the standard [performLayout].
|
||||
///
|
||||
/// Note: to debug the divkit layout system, enable logging [debugPrintDivPerformLayout].
|
||||
class DivLayout extends StatelessWidget {
|
||||
final DivSizeValue width;
|
||||
final DivSizeValue height;
|
||||
final double? aspect;
|
||||
final EdgeInsetsGeometry? margin;
|
||||
final AlignmentGeometry? alignment;
|
||||
|
||||
final Widget child;
|
||||
|
||||
const DivLayout({
|
||||
super.key,
|
||||
required this.child,
|
||||
this.width = const DivMatchParent(),
|
||||
this.height = const DivWrapContent(),
|
||||
this.alignment,
|
||||
this.margin,
|
||||
this.aspect,
|
||||
});
|
||||
|
||||
DivLayoutParam modifySize(DivParentData? parent, DivLayoutParam? parentSize) {
|
||||
final parentWidth = parentSize?.width;
|
||||
final parentHeight = parentSize?.height;
|
||||
|
||||
var res = DivLayoutParam(
|
||||
width: width,
|
||||
height: height,
|
||||
);
|
||||
|
||||
// When the wrapContent/constrained is specified for the parent, then we force it on children.
|
||||
if (width.isMatchParent && (parentHeight?.isWrapContent ?? false) ||
|
||||
(parentHeight?.isConstrained ?? false)) {
|
||||
res = res.copyWith(
|
||||
width: parentWidth,
|
||||
);
|
||||
}
|
||||
|
||||
// When the wrapContent/constrained is specified for the parent, then we force it on children.
|
||||
if (height.isMatchParent && (parentHeight?.isWrapContent ?? false) ||
|
||||
(parentHeight?.isConstrained ?? false)) {
|
||||
res = res.copyWith(
|
||||
height: parentHeight,
|
||||
);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final parent = watch<DivParentData>(context);
|
||||
final parentSize = watch<DivLayoutParam>(context);
|
||||
final modified = modifySize(parent, parentSize);
|
||||
final biggerParent = (parentSize?.height.isMatchParent ?? false) ||
|
||||
(parentSize?.width.isMatchParent ?? false);
|
||||
|
||||
Widget it = Padding(
|
||||
padding: margin ?? EdgeInsets.zero,
|
||||
child: DivSizeLayout(
|
||||
width: modified.width,
|
||||
height: modified.height,
|
||||
aspect: aspect,
|
||||
child: provide(
|
||||
modified,
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
if (parent == DivParentData.stack && alignment != null && biggerParent) {
|
||||
return Positioned.fill(
|
||||
child: Align(
|
||||
widthFactor: 1,
|
||||
heightFactor: 1,
|
||||
alignment: alignment!,
|
||||
child: it,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (alignment != null) {
|
||||
it = Align(
|
||||
alignment: alignment!,
|
||||
child: it,
|
||||
);
|
||||
}
|
||||
|
||||
if (parent == DivParentData.column && modified.height is DivMatchParent) {
|
||||
final weight = (modified.height as DivMatchParent).weight ?? 1;
|
||||
return Flexible(flex: weight, child: it);
|
||||
} else if (parent == DivParentData.row &&
|
||||
modified.width is DivMatchParent) {
|
||||
final weight = (modified.width as DivMatchParent).weight ?? 1;
|
||||
return Flexible(flex: weight, child: it);
|
||||
}
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties.add(
|
||||
DiagnosticsProperty<AlignmentGeometry?>(
|
||||
'alignment',
|
||||
alignment,
|
||||
defaultValue: null,
|
||||
),
|
||||
);
|
||||
properties.add(
|
||||
DiagnosticsProperty<DivSizeValue>(
|
||||
'width',
|
||||
width,
|
||||
defaultValue: const DivMatchParent(),
|
||||
),
|
||||
);
|
||||
properties.add(
|
||||
DiagnosticsProperty<DivSizeValue>(
|
||||
'height',
|
||||
height,
|
||||
defaultValue: const DivWrapContent(),
|
||||
),
|
||||
);
|
||||
properties.add(
|
||||
DiagnosticsProperty<double?>(
|
||||
'aspect',
|
||||
aspect,
|
||||
defaultValue: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class DivSizeLayout extends SingleChildRenderObjectWidget {
|
||||
final DivSizeValue width;
|
||||
final DivSizeValue height;
|
||||
final double? aspect;
|
||||
|
||||
const DivSizeLayout({
|
||||
super.key,
|
||||
required Widget child,
|
||||
this.width = const DivWrapContent(),
|
||||
this.height = const DivWrapContent(),
|
||||
this.aspect,
|
||||
}) : super(child: child);
|
||||
|
||||
@override
|
||||
RenderObject createRenderObject(BuildContext context) => DivSizeLayoutRender(
|
||||
width,
|
||||
height,
|
||||
aspect,
|
||||
);
|
||||
|
||||
@override
|
||||
void updateRenderObject(
|
||||
BuildContext context,
|
||||
covariant DivSizeLayoutRender renderObject,
|
||||
) =>
|
||||
renderObject
|
||||
..width = width
|
||||
..height = height
|
||||
..aspect = aspect;
|
||||
}
|
||||
|
||||
class DivSizeLayoutRender extends RenderBox
|
||||
with RenderObjectWithChildMixin<RenderBox> {
|
||||
DivSizeValue _width;
|
||||
|
||||
set width(DivSizeValue value) {
|
||||
if (value != _width) {
|
||||
_width = value;
|
||||
markNeedsLayout();
|
||||
}
|
||||
}
|
||||
|
||||
DivSizeValue _height;
|
||||
|
||||
set height(DivSizeValue value) {
|
||||
if (value != _height) {
|
||||
_height = value;
|
||||
markNeedsLayout();
|
||||
}
|
||||
}
|
||||
|
||||
double? _aspect;
|
||||
|
||||
set aspect(double? value) {
|
||||
if (value != _aspect) {
|
||||
_aspect = value;
|
||||
markNeedsLayout();
|
||||
}
|
||||
}
|
||||
|
||||
DivSizeLayoutRender(
|
||||
DivSizeValue width,
|
||||
DivSizeValue height,
|
||||
double? aspect,
|
||||
) : _width = width,
|
||||
_height = height,
|
||||
_aspect = aspect;
|
||||
|
||||
@override
|
||||
bool hitTestSelf(Offset position) => true;
|
||||
|
||||
@override
|
||||
bool hitTestChildren(
|
||||
BoxHitTestResult result, {
|
||||
required Offset position,
|
||||
}) {
|
||||
if (child != null) {
|
||||
return child!.hitTest(
|
||||
result,
|
||||
position: position,
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
if (child == null) {
|
||||
size = constraints.smallest;
|
||||
return;
|
||||
}
|
||||
|
||||
_log("[begin #$hashCode]");
|
||||
|
||||
var it = constraints;
|
||||
_width.map(
|
||||
fixed: (value) {
|
||||
_log("width.fixed($value)");
|
||||
it = it.copyWith(
|
||||
minWidth: value,
|
||||
maxWidth: value,
|
||||
);
|
||||
},
|
||||
wrapContent: (min, max) {
|
||||
_log("width.wrapContent($min, $max)");
|
||||
it = it.copyWith(minWidth: min ?? 0, maxWidth: max);
|
||||
},
|
||||
matchParent: (weight) {
|
||||
_log("width.matchParent($weight)");
|
||||
it = it.copyWith(
|
||||
minWidth: constraints.hasBoundedWidth ? constraints.maxWidth : 0.0,
|
||||
maxWidth: constraints.maxWidth,
|
||||
);
|
||||
},
|
||||
constrained: (min, max) {
|
||||
_log("width.constrained($min, $max)");
|
||||
it = it.copyWith(
|
||||
minWidth: constraints.constrainWidth(min ?? constraints.minWidth),
|
||||
maxWidth: constraints.constrainWidth(max ?? constraints.maxWidth),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
if (_aspect == null) {
|
||||
_height.map(
|
||||
fixed: (value) {
|
||||
_log("height.fixed($value)");
|
||||
it = it.copyWith(
|
||||
minHeight: value,
|
||||
maxHeight: value,
|
||||
);
|
||||
},
|
||||
wrapContent: (min, max) {
|
||||
_log("height.wrapContent($min, $max)");
|
||||
it = it.copyWith(minHeight: min ?? 0, maxHeight: max);
|
||||
},
|
||||
matchParent: (weight) {
|
||||
_log("height.matchParent($weight)");
|
||||
it = it.copyWith(
|
||||
minHeight:
|
||||
constraints.hasBoundedHeight ? constraints.maxHeight : 0.0,
|
||||
maxHeight: constraints.maxHeight,
|
||||
);
|
||||
},
|
||||
constrained: (min, max) {
|
||||
_log("height.constrained($min, $max)");
|
||||
it = it.copyWith(
|
||||
minHeight:
|
||||
constraints.constrainHeight(min ?? constraints.minHeight),
|
||||
maxHeight:
|
||||
constraints.constrainHeight(max ?? constraints.maxHeight),
|
||||
);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
// This layout passage is needed in order to calculate the width.
|
||||
child!.layout(it, parentUsesSize: true);
|
||||
final value = child!.size.width / _aspect!;
|
||||
_log("Aspect size: $value");
|
||||
it = it.copyWith(
|
||||
minHeight: value,
|
||||
maxHeight: value,
|
||||
);
|
||||
}
|
||||
|
||||
_log(
|
||||
"[constraints]\n"
|
||||
"in: $constraints\n"
|
||||
"out: $it",
|
||||
);
|
||||
|
||||
child!.layout(it, parentUsesSize: true);
|
||||
|
||||
final childWidth = child!.size.width;
|
||||
final calcWidth = _width is DivMatchParent
|
||||
? constraints.hasBoundedWidth
|
||||
? constraints.maxWidth
|
||||
: childWidth
|
||||
: _width is DivWrapContent
|
||||
? childWidth
|
||||
: constraints.constrainWidth(childWidth);
|
||||
|
||||
final childHeight = child!.size.height;
|
||||
final calcHeight = _height is DivMatchParent
|
||||
? constraints.hasBoundedHeight
|
||||
? constraints.maxHeight
|
||||
: childHeight
|
||||
: _height is DivWrapContent
|
||||
? childHeight
|
||||
: constraints.constrainHeight(childHeight);
|
||||
|
||||
_log(
|
||||
"[size]\n"
|
||||
"in: ${child!.size}\n"
|
||||
"out: ${constraints.constrain(Size(calcWidth, calcHeight))}",
|
||||
);
|
||||
|
||||
size = constraints.constrain(Size(calcWidth, calcHeight));
|
||||
|
||||
_log("[end #$hashCode]");
|
||||
}
|
||||
|
||||
@override
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
if (child != null) {
|
||||
context.paintChild(child!, offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,8 +43,7 @@ class DivPagerModel with EquatableMixin {
|
||||
PageController controller,
|
||||
ValueGetter<int> currentPage,
|
||||
) {
|
||||
final variables =
|
||||
DivKitProvider.watch<DivContext>(context)!.variableManager;
|
||||
final variables = watch<DivContext>(context)!.variableManager;
|
||||
final id = data.id;
|
||||
if (id != null && variables.context.current[id] != currentPage()) {
|
||||
variables.putVariable(id, currentPage());
|
||||
|
||||
@@ -25,12 +25,12 @@ class _DivPagerWidgetState extends State<DivPagerWidget> {
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
value = DivPagerModel.value(context, widget.data);
|
||||
currentPage = widget.data.defaultItem.value ?? 0;
|
||||
controller = PageController(
|
||||
initialPage: currentPage,
|
||||
);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -70,11 +70,14 @@ class _DivPagerWidgetState extends State<DivPagerWidget> {
|
||||
if (snapshot.hasData) {
|
||||
final model = snapshot.requireData;
|
||||
|
||||
return PageView(
|
||||
scrollDirection: model.orientation,
|
||||
controller: controller,
|
||||
onPageChanged: (value) => onPageChanged(value),
|
||||
children: model.children,
|
||||
return provide(
|
||||
DivParentData.pager,
|
||||
child: PageView(
|
||||
scrollDirection: model.orientation,
|
||||
controller: controller,
|
||||
onPageChanged: (value) => onPageChanged(value),
|
||||
children: model.children,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -87,7 +90,7 @@ class _DivPagerWidgetState extends State<DivPagerWidget> {
|
||||
currentPage = value;
|
||||
final id = widget.data.id;
|
||||
if (id != null) {
|
||||
final divContext = DivKitProvider.watch<DivContext>(context)!;
|
||||
final divContext = watch<DivContext>(context)!;
|
||||
divContext.variableManager.updateVariable(id, currentPage);
|
||||
}
|
||||
}
|
||||
@@ -95,6 +98,7 @@ class _DivPagerWidgetState extends State<DivPagerWidget> {
|
||||
@override
|
||||
void dispose() {
|
||||
controller.dispose();
|
||||
value = null;
|
||||
stream = null;
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -32,13 +32,16 @@ class DivRootModel with EquatableMixin {
|
||||
final variables = watch<DivContext>(context)!.variableManager;
|
||||
final state = watch<DivContext>(context)!.stateManager;
|
||||
return state.watch<DivRootModel>((states) async {
|
||||
// To avoid errors in the first frame due to outdated variable
|
||||
// context data, needs to preload all the variables used in div.
|
||||
await data.preload(variables.context.current);
|
||||
return DivRootModel(
|
||||
final model = DivRootModel(
|
||||
stateId: states['root']!,
|
||||
states: data.states,
|
||||
);
|
||||
|
||||
// To avoid errors in the first frame due to outdated variable
|
||||
// context data, needs to preload all the variables used in state.
|
||||
await model.state.preload(variables.context.current);
|
||||
|
||||
return model;
|
||||
}).distinct();
|
||||
}
|
||||
|
||||
|
||||
@@ -78,10 +78,7 @@ class DivStateModel with EquatableMixin {
|
||||
|
||||
final state = watch<DivContext>(context)!.stateManager;
|
||||
return state.watch<DivStateModel>((states) async {
|
||||
// To avoid errors in the first frame due to outdated variable
|
||||
// context data, needs to preload all the variables used in div.
|
||||
await data.preload(variables.context.current);
|
||||
return DivStateModel(
|
||||
final model = DivStateModel(
|
||||
divId: divId,
|
||||
stateId: states[divId],
|
||||
defaultStateId: await data.defaultStateId?.resolveValue(
|
||||
@@ -89,6 +86,12 @@ class DivStateModel with EquatableMixin {
|
||||
),
|
||||
states: data.states,
|
||||
);
|
||||
|
||||
// To avoid errors in the first frame due to outdated variable
|
||||
// context data, needs to preload all the variables used in state.
|
||||
await model.state?.preload(variables.context.current);
|
||||
|
||||
return model;
|
||||
}).distinct();
|
||||
}
|
||||
|
||||
|
||||
@@ -54,11 +54,13 @@ class _DivStateWidgetState extends State<DivStateWidget> {
|
||||
if (snapshot.hasData) {
|
||||
final model = snapshot.requireData;
|
||||
return provide(
|
||||
DivStateId(model.divId),
|
||||
child: DivWidget(
|
||||
// The unique identifier of the state subtree
|
||||
key: ValueKey(model.path),
|
||||
model.state?.div,
|
||||
DivParentData.none,
|
||||
child: provide(
|
||||
DivStateId(model.divId),
|
||||
child: DivWidget(
|
||||
// The unique identifier of the state subtree
|
||||
key: ValueKey(model.path), model.state?.div,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ export 'div_widget.dart';
|
||||
export 'gallery/div_gallery_widget.dart';
|
||||
export 'image/div_image_widget.dart';
|
||||
export 'input/div_input_widget.dart';
|
||||
export 'layout/div_layout.dart';
|
||||
export 'pager/div_pager_widget.dart';
|
||||
export 'state/div_state_widget.dart';
|
||||
export 'text/div_text_widget.dart';
|
||||
|
||||
@@ -332,6 +332,38 @@ class Div extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 15;
|
||||
|
||||
bool get isDivContainer => _index == 0;
|
||||
|
||||
bool get isDivCustom => _index == 1;
|
||||
|
||||
bool get isDivGallery => _index == 2;
|
||||
|
||||
bool get isDivGifImage => _index == 3;
|
||||
|
||||
bool get isDivGrid => _index == 4;
|
||||
|
||||
bool get isDivImage => _index == 5;
|
||||
|
||||
bool get isDivIndicator => _index == 6;
|
||||
|
||||
bool get isDivInput => _index == 7;
|
||||
|
||||
bool get isDivPager => _index == 8;
|
||||
|
||||
bool get isDivSelect => _index == 9;
|
||||
|
||||
bool get isDivSeparator => _index == 10;
|
||||
|
||||
bool get isDivSlider => _index == 11;
|
||||
|
||||
bool get isDivState => _index == 12;
|
||||
|
||||
bool get isDivTabs => _index == 13;
|
||||
|
||||
bool get isDivText => _index == 14;
|
||||
|
||||
bool get isDivVideo => _index == 15;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -161,6 +161,25 @@ enum DivAccessibilityType implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivAccessibilityType(this.value);
|
||||
bool get isNone => this == none;
|
||||
|
||||
bool get isButton => this == button;
|
||||
|
||||
bool get isImage => this == image;
|
||||
|
||||
bool get isText => this == text;
|
||||
|
||||
bool get isEditText => this == editText;
|
||||
|
||||
bool get isHeader => this == header;
|
||||
|
||||
bool get isTabBar => this == tabBar;
|
||||
|
||||
bool get isList => this == list;
|
||||
|
||||
bool get isSelect => this == select;
|
||||
|
||||
bool get isAuto => this == auto;
|
||||
|
||||
T map<T>({
|
||||
required T Function() none,
|
||||
@@ -317,6 +336,11 @@ enum DivAccessibilityMode implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivAccessibilityMode(this.value);
|
||||
bool get isDefault => this == default_;
|
||||
|
||||
bool get isMerge => this == merge;
|
||||
|
||||
bool get isExclude => this == exclude;
|
||||
|
||||
T map<T>({
|
||||
required T Function() default_,
|
||||
|
||||
@@ -298,6 +298,9 @@ enum DivActionTarget implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivActionTarget(this.value);
|
||||
bool get isSelf => this == self;
|
||||
|
||||
bool get isBlank => this == blank;
|
||||
|
||||
T map<T>({
|
||||
required T Function() self,
|
||||
|
||||
@@ -65,6 +65,10 @@ class DivActionCopyToClipboardContent extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 1;
|
||||
|
||||
bool get isContentText => _index == 0;
|
||||
|
||||
bool get isContentUrl => _index == 1;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -179,6 +179,22 @@ class DivActionTyped extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 7;
|
||||
|
||||
bool get isDivActionArrayInsertValue => _index == 0;
|
||||
|
||||
bool get isDivActionArrayRemoveValue => _index == 1;
|
||||
|
||||
bool get isDivActionArraySetValue => _index == 2;
|
||||
|
||||
bool get isDivActionClearFocus => _index == 3;
|
||||
|
||||
bool get isDivActionCopyToClipboard => _index == 4;
|
||||
|
||||
bool get isDivActionDictSetValue => _index == 5;
|
||||
|
||||
bool get isDivActionFocusElement => _index == 6;
|
||||
|
||||
bool get isDivActionSetVariable => _index == 7;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -12,6 +12,15 @@ enum DivAlignmentHorizontal implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivAlignmentHorizontal(this.value);
|
||||
bool get isLeft => this == left;
|
||||
|
||||
bool get isCenter => this == center;
|
||||
|
||||
bool get isRight => this == right;
|
||||
|
||||
bool get isStart => this == start;
|
||||
|
||||
bool get isEnd => this == end;
|
||||
|
||||
T map<T>({
|
||||
required T Function() left,
|
||||
|
||||
@@ -11,6 +11,13 @@ enum DivAlignmentVertical implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivAlignmentVertical(this.value);
|
||||
bool get isTop => this == top;
|
||||
|
||||
bool get isCenter => this == center;
|
||||
|
||||
bool get isBottom => this == bottom;
|
||||
|
||||
bool get isBaseline => this == baseline;
|
||||
|
||||
T map<T>({
|
||||
required T Function() top,
|
||||
|
||||
@@ -202,6 +202,17 @@ enum DivAnimationName implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivAnimationName(this.value);
|
||||
bool get isFade => this == fade;
|
||||
|
||||
bool get isTranslate => this == translate;
|
||||
|
||||
bool get isScale => this == scale;
|
||||
|
||||
bool get isNative => this == native;
|
||||
|
||||
bool get isSet => this == set;
|
||||
|
||||
bool get isNoAnimation => this == noAnimation;
|
||||
|
||||
T map<T>({
|
||||
required T Function() fade,
|
||||
|
||||
@@ -13,6 +13,17 @@ enum DivAnimationInterpolator implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivAnimationInterpolator(this.value);
|
||||
bool get isLinear => this == linear;
|
||||
|
||||
bool get isEase => this == ease;
|
||||
|
||||
bool get isEaseIn => this == easeIn;
|
||||
|
||||
bool get isEaseOut => this == easeOut;
|
||||
|
||||
bool get isEaseInOut => this == easeInOut;
|
||||
|
||||
bool get isSpring => this == spring;
|
||||
|
||||
T map<T>({
|
||||
required T Function() linear,
|
||||
|
||||
@@ -103,6 +103,14 @@ class DivAppearanceTransition extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 3;
|
||||
|
||||
bool get isDivAppearanceSetTransition => _index == 0;
|
||||
|
||||
bool get isDivFadeTransition => _index == 1;
|
||||
|
||||
bool get isDivScaleTransition => _index == 2;
|
||||
|
||||
bool get isDivSlideTransition => _index == 3;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -122,6 +122,16 @@ class DivBackground extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 4;
|
||||
|
||||
bool get isDivImageBackground => _index == 0;
|
||||
|
||||
bool get isDivLinearGradient => _index == 1;
|
||||
|
||||
bool get isDivNinePatchBackground => _index == 2;
|
||||
|
||||
bool get isDivRadialGradient => _index == 3;
|
||||
|
||||
bool get isDivSolidBackground => _index == 4;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -13,6 +13,17 @@ enum DivBlendMode implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivBlendMode(this.value);
|
||||
bool get isSourceIn => this == sourceIn;
|
||||
|
||||
bool get isSourceAtop => this == sourceAtop;
|
||||
|
||||
bool get isDarken => this == darken;
|
||||
|
||||
bool get isLighten => this == lighten;
|
||||
|
||||
bool get isMultiply => this == multiply;
|
||||
|
||||
bool get isScreen => this == screen;
|
||||
|
||||
T map<T>({
|
||||
required T Function() sourceIn,
|
||||
|
||||
@@ -65,6 +65,10 @@ class DivChangeTransition extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 1;
|
||||
|
||||
bool get isDivChangeBoundsTransition => _index == 0;
|
||||
|
||||
bool get isDivChangeSetTransition => _index == 1;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -1094,6 +1094,11 @@ enum DivContainerOrientation implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivContainerOrientation(this.value);
|
||||
bool get isVertical => this == vertical;
|
||||
|
||||
bool get isHorizontal => this == horizontal;
|
||||
|
||||
bool get isOverlap => this == overlap;
|
||||
|
||||
T map<T>({
|
||||
required T Function() vertical,
|
||||
@@ -1179,6 +1184,9 @@ enum DivContainerLayoutMode implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivContainerLayoutMode(this.value);
|
||||
bool get isNoWrap => this == noWrap;
|
||||
|
||||
bool get isWrap => this == wrap;
|
||||
|
||||
T map<T>({
|
||||
required T Function() noWrap,
|
||||
|
||||
@@ -15,6 +15,21 @@ enum DivContentAlignmentHorizontal implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivContentAlignmentHorizontal(this.value);
|
||||
bool get isLeft => this == left;
|
||||
|
||||
bool get isCenter => this == center;
|
||||
|
||||
bool get isRight => this == right;
|
||||
|
||||
bool get isStart => this == start;
|
||||
|
||||
bool get isEnd => this == end;
|
||||
|
||||
bool get isSpaceBetween => this == spaceBetween;
|
||||
|
||||
bool get isSpaceAround => this == spaceAround;
|
||||
|
||||
bool get isSpaceEvenly => this == spaceEvenly;
|
||||
|
||||
T map<T>({
|
||||
required T Function() left,
|
||||
|
||||
@@ -14,6 +14,19 @@ enum DivContentAlignmentVertical implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivContentAlignmentVertical(this.value);
|
||||
bool get isTop => this == top;
|
||||
|
||||
bool get isCenter => this == center;
|
||||
|
||||
bool get isBottom => this == bottom;
|
||||
|
||||
bool get isBaseline => this == baseline;
|
||||
|
||||
bool get isSpaceBetween => this == spaceBetween;
|
||||
|
||||
bool get isSpaceAround => this == spaceAround;
|
||||
|
||||
bool get isSpaceEvenly => this == spaceEvenly;
|
||||
|
||||
T map<T>({
|
||||
required T Function() top,
|
||||
|
||||
@@ -65,6 +65,10 @@ class DivCount extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 1;
|
||||
|
||||
bool get isDivFixedCount => _index == 0;
|
||||
|
||||
bool get isDivInfinityCount => _index == 1;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -46,6 +46,8 @@ class DivDrawable extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 0;
|
||||
|
||||
bool get isDivShapeDrawable => _index == 0;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -65,6 +65,10 @@ class DivFilter extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 1;
|
||||
|
||||
bool get isDivBlur => _index == 0;
|
||||
|
||||
bool get isDivFilterRtlMirror => _index == 1;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -11,6 +11,13 @@ enum DivFontWeight implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivFontWeight(this.value);
|
||||
bool get isLight => this == light;
|
||||
|
||||
bool get isMedium => this == medium;
|
||||
|
||||
bool get isRegular => this == regular;
|
||||
|
||||
bool get isBold => this == bold;
|
||||
|
||||
T map<T>({
|
||||
required T Function() light,
|
||||
|
||||
@@ -840,6 +840,11 @@ enum DivGalleryCrossContentAlignment implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivGalleryCrossContentAlignment(this.value);
|
||||
bool get isStart => this == start;
|
||||
|
||||
bool get isCenter => this == center;
|
||||
|
||||
bool get isEnd => this == end;
|
||||
|
||||
T map<T>({
|
||||
required T Function() start,
|
||||
@@ -925,6 +930,9 @@ enum DivGalleryScrollMode implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivGalleryScrollMode(this.value);
|
||||
bool get isPaging => this == paging;
|
||||
|
||||
bool get isDefault => this == default_;
|
||||
|
||||
T map<T>({
|
||||
required T Function() paging,
|
||||
@@ -1000,6 +1008,9 @@ enum DivGalleryOrientation implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivGalleryOrientation(this.value);
|
||||
bool get isHorizontal => this == horizontal;
|
||||
|
||||
bool get isVertical => this == vertical;
|
||||
|
||||
T map<T>({
|
||||
required T Function() horizontal,
|
||||
@@ -1075,6 +1086,9 @@ enum DivGalleryScrollbar implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivGalleryScrollbar(this.value);
|
||||
bool get isNone => this == none;
|
||||
|
||||
bool get isAuto => this == auto;
|
||||
|
||||
T map<T>({
|
||||
required T Function() none,
|
||||
|
||||
@@ -11,6 +11,13 @@ enum DivImageScale implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivImageScale(this.value);
|
||||
bool get isFill => this == fill;
|
||||
|
||||
bool get isNoScale => this == noScale;
|
||||
|
||||
bool get isFit => this == fit;
|
||||
|
||||
bool get isStretch => this == stretch;
|
||||
|
||||
T map<T>({
|
||||
required T Function() fill,
|
||||
|
||||
@@ -857,6 +857,11 @@ enum DivIndicatorAnimation implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivIndicatorAnimation(this.value);
|
||||
bool get isScale => this == scale;
|
||||
|
||||
bool get isWorm => this == worm;
|
||||
|
||||
bool get isSlider => this == slider;
|
||||
|
||||
T map<T>({
|
||||
required T Function() scale,
|
||||
|
||||
@@ -69,6 +69,10 @@ class DivIndicatorItemPlacement extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 1;
|
||||
|
||||
bool get isDivDefaultIndicatorItemPlacement => _index == 0;
|
||||
|
||||
bool get isDivStretchIndicatorItemPlacement => _index == 1;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -1071,6 +1071,19 @@ enum DivInputKeyboardType implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivInputKeyboardType(this.value);
|
||||
bool get isSingleLineText => this == singleLineText;
|
||||
|
||||
bool get isMultiLineText => this == multiLineText;
|
||||
|
||||
bool get isPhone => this == phone;
|
||||
|
||||
bool get isNumber => this == number;
|
||||
|
||||
bool get isEmail => this == email;
|
||||
|
||||
bool get isUri => this == uri;
|
||||
|
||||
bool get isPassword => this == password;
|
||||
|
||||
T map<T>({
|
||||
required T Function() singleLineText,
|
||||
|
||||
@@ -85,6 +85,12 @@ class DivInputMask extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 2;
|
||||
|
||||
bool get isDivCurrencyInputMask => _index == 0;
|
||||
|
||||
bool get isDivFixedLengthInputMask => _index == 1;
|
||||
|
||||
bool get isDivPhoneInputMask => _index == 2;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -66,6 +66,10 @@ class DivInputValidator extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 1;
|
||||
|
||||
bool get isDivInputValidatorExpression => _index == 0;
|
||||
|
||||
bool get isDivInputValidatorRegex => _index == 1;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@ enum DivLineStyle implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivLineStyle(this.value);
|
||||
bool get isNone => this == none;
|
||||
|
||||
bool get isSingle => this == single;
|
||||
|
||||
T map<T>({
|
||||
required T Function() none,
|
||||
|
||||
@@ -66,6 +66,10 @@ class DivPageTransformation extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 1;
|
||||
|
||||
bool get isDivPageTransformationOverlap => _index == 0;
|
||||
|
||||
bool get isDivPageTransformationSlide => _index == 1;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -816,6 +816,9 @@ enum DivPagerOrientation implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivPagerOrientation(this.value);
|
||||
bool get isHorizontal => this == horizontal;
|
||||
|
||||
bool get isVertical => this == vertical;
|
||||
|
||||
T map<T>({
|
||||
required T Function() horizontal,
|
||||
|
||||
@@ -65,6 +65,10 @@ class DivPagerLayoutMode extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 1;
|
||||
|
||||
bool get isDivNeighbourPageSize => _index == 0;
|
||||
|
||||
bool get isDivPageSize => _index == 1;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -155,6 +155,9 @@ enum DivPatchMode implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivPatchMode(this.value);
|
||||
bool get isTransactional => this == transactional;
|
||||
|
||||
bool get isPartial => this == partial;
|
||||
|
||||
T map<T>({
|
||||
required T Function() transactional,
|
||||
|
||||
@@ -65,6 +65,10 @@ class DivPivot extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 1;
|
||||
|
||||
bool get isDivPivotFixed => _index == 0;
|
||||
|
||||
bool get isDivPivotPercentage => _index == 1;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -68,6 +68,10 @@ class DivRadialGradientCenter extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 1;
|
||||
|
||||
bool get isDivRadialGradientFixedCenter => _index == 0;
|
||||
|
||||
bool get isDivRadialGradientRelativeCenter => _index == 1;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -67,6 +67,10 @@ class DivRadialGradientRadius extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 1;
|
||||
|
||||
bool get isDivFixedSize => _index == 0;
|
||||
|
||||
bool get isDivRadialGradientRelativeRadius => _index == 1;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -81,6 +81,13 @@ enum DivRadialGradientRelativeRadiusValue implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivRadialGradientRelativeRadiusValue(this.value);
|
||||
bool get isNearestCorner => this == nearestCorner;
|
||||
|
||||
bool get isFarthestCorner => this == farthestCorner;
|
||||
|
||||
bool get isNearestSide => this == nearestSide;
|
||||
|
||||
bool get isFarthestSide => this == farthestSide;
|
||||
|
||||
T map<T>({
|
||||
required T Function() nearestCorner,
|
||||
|
||||
@@ -899,6 +899,9 @@ enum DivSeparatorDelimiterStyleOrientation implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivSeparatorDelimiterStyleOrientation(this.value);
|
||||
bool get isVertical => this == vertical;
|
||||
|
||||
bool get isHorizontal => this == horizontal;
|
||||
|
||||
T map<T>({
|
||||
required T Function() vertical,
|
||||
|
||||
@@ -65,6 +65,10 @@ class DivShape extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 1;
|
||||
|
||||
bool get isDivCircleShape => _index == 0;
|
||||
|
||||
bool get isDivRoundedRectangleShape => _index == 1;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -84,6 +84,12 @@ class DivSize extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 2;
|
||||
|
||||
bool get isDivFixedSize => _index == 0;
|
||||
|
||||
bool get isDivMatchParentSize => _index == 1;
|
||||
|
||||
bool get isDivWrapContentSize => _index == 2;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -10,6 +10,11 @@ enum DivSizeUnit implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivSizeUnit(this.value);
|
||||
bool get isDp => this == dp;
|
||||
|
||||
bool get isSp => this == sp;
|
||||
|
||||
bool get isPx => this == px;
|
||||
|
||||
T map<T>({
|
||||
required T Function() dp,
|
||||
|
||||
@@ -152,6 +152,13 @@ enum DivSlideTransitionEdge implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivSlideTransitionEdge(this.value);
|
||||
bool get isLeft => this == left;
|
||||
|
||||
bool get isTop => this == top;
|
||||
|
||||
bool get isRight => this == right;
|
||||
|
||||
bool get isBottom => this == bottom;
|
||||
|
||||
T map<T>({
|
||||
required T Function() left,
|
||||
|
||||
@@ -1283,6 +1283,11 @@ enum DivTabsTabTitleStyleAnimationType implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivTabsTabTitleStyleAnimationType(this.value);
|
||||
bool get isSlide => this == slide;
|
||||
|
||||
bool get isFade => this == fade;
|
||||
|
||||
bool get isNone => this == none;
|
||||
|
||||
T map<T>({
|
||||
required T Function() slide,
|
||||
|
||||
@@ -1823,6 +1823,13 @@ enum DivTextTruncate implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivTextTruncate(this.value);
|
||||
bool get isNone => this == none;
|
||||
|
||||
bool get isStart => this == start;
|
||||
|
||||
bool get isEnd => this == end;
|
||||
|
||||
bool get isMiddle => this == middle;
|
||||
|
||||
T map<T>({
|
||||
required T Function() none,
|
||||
|
||||
@@ -65,6 +65,10 @@ class DivTextGradient extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 1;
|
||||
|
||||
bool get isDivLinearGradient => _index == 0;
|
||||
|
||||
bool get isDivRadialGradient => _index == 1;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -46,6 +46,8 @@ class DivTextRangeBackground extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 0;
|
||||
|
||||
bool get isDivSolidBackground => _index == 0;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -168,6 +168,23 @@ enum DivTooltipPosition implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivTooltipPosition(this.value);
|
||||
bool get isLeft => this == left;
|
||||
|
||||
bool get isTopLeft => this == topLeft;
|
||||
|
||||
bool get isTop => this == top;
|
||||
|
||||
bool get isTopRight => this == topRight;
|
||||
|
||||
bool get isRight => this == right;
|
||||
|
||||
bool get isBottomRight => this == bottomRight;
|
||||
|
||||
bool get isBottom => this == bottom;
|
||||
|
||||
bool get isBottomLeft => this == bottomLeft;
|
||||
|
||||
bool get isCenter => this == center;
|
||||
|
||||
T map<T>({
|
||||
required T Function() left,
|
||||
|
||||
@@ -11,6 +11,13 @@ enum DivTransitionSelector implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivTransitionSelector(this.value);
|
||||
bool get isNone => this == none;
|
||||
|
||||
bool get isDataChange => this == dataChange;
|
||||
|
||||
bool get isStateChange => this == stateChange;
|
||||
|
||||
bool get isAnyChange => this == anyChange;
|
||||
|
||||
T map<T>({
|
||||
required T Function() none,
|
||||
|
||||
@@ -10,6 +10,11 @@ enum DivTransitionTrigger implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivTransitionTrigger(this.value);
|
||||
bool get isDataChange => this == dataChange;
|
||||
|
||||
bool get isStateChange => this == stateChange;
|
||||
|
||||
bool get isVisibilityChange => this == visibilityChange;
|
||||
|
||||
T map<T>({
|
||||
required T Function() dataChange,
|
||||
|
||||
@@ -117,6 +117,9 @@ enum DivTriggerMode implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivTriggerMode(this.value);
|
||||
bool get isOnCondition => this == onCondition;
|
||||
|
||||
bool get isOnVariable => this == onVariable;
|
||||
|
||||
T map<T>({
|
||||
required T Function() onCondition,
|
||||
|
||||
@@ -179,6 +179,22 @@ class DivTypedValue extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 7;
|
||||
|
||||
bool get isArrayValue => _index == 0;
|
||||
|
||||
bool get isBooleanValue => _index == 1;
|
||||
|
||||
bool get isColorValue => _index == 2;
|
||||
|
||||
bool get isDictValue => _index == 3;
|
||||
|
||||
bool get isIntegerValue => _index == 4;
|
||||
|
||||
bool get isNumberValue => _index == 5;
|
||||
|
||||
bool get isStringValue => _index == 6;
|
||||
|
||||
bool get isUrlValue => _index == 7;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -179,6 +179,22 @@ class DivVariable extends Preloadable with EquatableMixin {
|
||||
) : value = obj,
|
||||
_index = 7;
|
||||
|
||||
bool get isArrayVariable => _index == 0;
|
||||
|
||||
bool get isBooleanVariable => _index == 1;
|
||||
|
||||
bool get isColorVariable => _index == 2;
|
||||
|
||||
bool get isDictVariable => _index == 3;
|
||||
|
||||
bool get isIntegerVariable => _index == 4;
|
||||
|
||||
bool get isNumberVariable => _index == 5;
|
||||
|
||||
bool get isStringVariable => _index == 6;
|
||||
|
||||
bool get isUrlVariable => _index == 7;
|
||||
|
||||
@override
|
||||
Future<void> preload(Map<String, dynamic> context) => value.preload(context);
|
||||
|
||||
|
||||
@@ -10,6 +10,11 @@ enum DivVideoScale implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivVideoScale(this.value);
|
||||
bool get isFill => this == fill;
|
||||
|
||||
bool get isNoScale => this == noScale;
|
||||
|
||||
bool get isFit => this == fit;
|
||||
|
||||
T map<T>({
|
||||
required T Function() fill,
|
||||
|
||||
@@ -10,6 +10,11 @@ enum DivVisibility implements Preloadable {
|
||||
final String value;
|
||||
|
||||
const DivVisibility(this.value);
|
||||
bool get isVisible => this == visible;
|
||||
|
||||
bool get isInvisible => this == invisible;
|
||||
|
||||
bool get isGone => this == gone;
|
||||
|
||||
T map<T>({
|
||||
required T Function() visible,
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/// Experiments and optional features.
|
||||
class DivConfiguration {
|
||||
final bool showUnsupportedDivs;
|
||||
|
||||
const DivConfiguration({
|
||||
this.showUnsupportedDivs = false,
|
||||
});
|
||||
}
|
||||
@@ -79,22 +79,10 @@ abstract class ContentAlignment {
|
||||
const ContentAlignment();
|
||||
|
||||
T map<T>({
|
||||
required T Function(FlexContentAlignment) flex,
|
||||
required T Function(WrapContentAlignment) wrap,
|
||||
required T Function(StackContentAlignment) stack,
|
||||
}) {
|
||||
final value = this;
|
||||
if (value is FlexContentAlignment) {
|
||||
return flex(value);
|
||||
}
|
||||
if (value is WrapContentAlignment) {
|
||||
return wrap(value);
|
||||
}
|
||||
if (value is StackContentAlignment) {
|
||||
return stack(value);
|
||||
}
|
||||
throw Exception("Unsupported ContentAlignment type");
|
||||
}
|
||||
required T Function(FlexContentAlignment data) flex,
|
||||
required T Function(WrapContentAlignment data) wrap,
|
||||
required T Function(StackContentAlignment data) stack,
|
||||
});
|
||||
}
|
||||
|
||||
class FlexContentAlignment extends ContentAlignment with EquatableMixin {
|
||||
@@ -109,6 +97,14 @@ class FlexContentAlignment extends ContentAlignment with EquatableMixin {
|
||||
required this.mainAxisAlignment,
|
||||
});
|
||||
|
||||
@override
|
||||
T map<T>({
|
||||
required T Function(FlexContentAlignment data) flex,
|
||||
required T Function(WrapContentAlignment data) wrap,
|
||||
required T Function(StackContentAlignment data) stack,
|
||||
}) =>
|
||||
flex(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [direction, crossAxisAlignment, mainAxisAlignment];
|
||||
}
|
||||
@@ -125,6 +121,14 @@ class WrapContentAlignment extends ContentAlignment with EquatableMixin {
|
||||
required this.runAlignment,
|
||||
});
|
||||
|
||||
@override
|
||||
T map<T>({
|
||||
required T Function(FlexContentAlignment data) flex,
|
||||
required T Function(WrapContentAlignment data) wrap,
|
||||
required T Function(StackContentAlignment data) stack,
|
||||
}) =>
|
||||
wrap(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [direction, wrapAlignment, runAlignment];
|
||||
}
|
||||
@@ -136,6 +140,14 @@ class StackContentAlignment extends ContentAlignment with EquatableMixin {
|
||||
required this.contentAlignment,
|
||||
});
|
||||
|
||||
@override
|
||||
T map<T>({
|
||||
required T Function(FlexContentAlignment data) flex,
|
||||
required T Function(WrapContentAlignment data) wrap,
|
||||
required T Function(StackContentAlignment data) stack,
|
||||
}) =>
|
||||
stack(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [contentAlignment];
|
||||
}
|
||||
@@ -163,7 +175,6 @@ class PassDivContentAlignment {
|
||||
|
||||
final divVertical = await safeVertical.resolveValue(context: context);
|
||||
final divHorizontal = await safeHorizontal.resolveValue(context: context);
|
||||
|
||||
final isWrap = await layoutMode.resolveValue(context: context) ==
|
||||
DivContainerLayoutMode.wrap;
|
||||
|
||||
|
||||
@@ -80,15 +80,15 @@ class DivAlignment with EquatableMixin {
|
||||
);
|
||||
} else if (safeVertical != null) {
|
||||
return safeVertical.map(
|
||||
start: () => Alignment.topCenter,
|
||||
center: () => Alignment.center,
|
||||
end: () => Alignment.bottomCenter,
|
||||
start: () => Alignment.topLeft,
|
||||
center: () => Alignment.centerLeft,
|
||||
end: () => Alignment.bottomLeft,
|
||||
);
|
||||
} else if (safeHorizontal != null) {
|
||||
return safeHorizontal.map(
|
||||
start: () => Alignment.centerLeft,
|
||||
center: () => Alignment.center,
|
||||
end: () => Alignment.centerRight,
|
||||
start: () => Alignment.topLeft,
|
||||
center: () => Alignment.topCenter,
|
||||
end: () => Alignment.topRight,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
@@ -845,21 +845,6 @@ extension DivSizeUnitMultiplier on DivSizeUnit {
|
||||
}
|
||||
}
|
||||
|
||||
extension PassDivVisibility on DivVisibility {
|
||||
bool get isGone => this == DivVisibility.gone;
|
||||
|
||||
double? get asOpacity {
|
||||
switch (this) {
|
||||
case DivVisibility.visible:
|
||||
return 1;
|
||||
case DivVisibility.invisible:
|
||||
return 0;
|
||||
case DivVisibility.gone:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension PassDivImageScale on DivImageScale {
|
||||
BoxFit get asBoxFit {
|
||||
switch (this) {
|
||||
|
||||
@@ -1,566 +0,0 @@
|
||||
import 'package:divkit/divkit.dart';
|
||||
import 'package:divkit/src/utils/content_alignment_converters.dart';
|
||||
import 'package:divkit/src/utils/provider.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
abstract class PassDivSize {
|
||||
const PassDivSize();
|
||||
|
||||
T map<T>({
|
||||
required T Function(FixedDivSize) fixed,
|
||||
required T Function(FlexDivSize) flex,
|
||||
required T Function(WrapDivSize) wrapped,
|
||||
}) {
|
||||
final value = this;
|
||||
if (value is FixedDivSize) {
|
||||
return fixed(value);
|
||||
}
|
||||
if (value is FlexDivSize) {
|
||||
return flex(value);
|
||||
}
|
||||
if (value is WrapDivSize) {
|
||||
return wrapped(value);
|
||||
}
|
||||
throw Exception("Unsupported ContentAlignment type");
|
||||
}
|
||||
|
||||
double? get maxConstraint => map(
|
||||
fixed: (fixed) => fixed.size,
|
||||
flex: (_) => null,
|
||||
wrapped: (wrapped) => wrapped.maxSize?.size ?? double.infinity,
|
||||
);
|
||||
|
||||
double? get minConstraint => map(
|
||||
fixed: (fixed) => fixed.size,
|
||||
flex: (_) => null,
|
||||
wrapped: (wrapped) => wrapped.minSize?.size ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
class FixedDivSize extends PassDivSize with EquatableMixin {
|
||||
final double size;
|
||||
|
||||
const FixedDivSize(this.size);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [size];
|
||||
}
|
||||
|
||||
class FlexDivSize extends PassDivSize with EquatableMixin {
|
||||
final int? weight;
|
||||
|
||||
const FlexDivSize(this.weight);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [weight];
|
||||
}
|
||||
|
||||
class WrapDivSize extends PassDivSize with EquatableMixin {
|
||||
final bool? constrained;
|
||||
final FixedDivSize? maxSize;
|
||||
final FixedDivSize? minSize;
|
||||
|
||||
const WrapDivSize(
|
||||
this.constrained, {
|
||||
required this.maxSize,
|
||||
required this.minSize,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [constrained, maxSize, minSize];
|
||||
}
|
||||
|
||||
extension PassDivSizeImpl on DivSize {
|
||||
Future<PassDivSize> resolve({
|
||||
required DivVariableContext context,
|
||||
required double viewScale,
|
||||
double extension = 0,
|
||||
}) async =>
|
||||
map(
|
||||
divFixedSize: (fixed) async => FixedDivSize(
|
||||
await fixed.resolveDimension(
|
||||
context: context,
|
||||
viewScale: viewScale,
|
||||
) +
|
||||
extension * viewScale,
|
||||
),
|
||||
divMatchParentSize: (flex) async => FlexDivSize(
|
||||
(await flex.weight?.resolveValue(context: context))?.toInt(),
|
||||
),
|
||||
divWrapContentSize: (wrapped) async {
|
||||
final FixedDivSize? parsedMax, parsedMin;
|
||||
final maxSize = wrapped.maxSize;
|
||||
final minSize = wrapped.minSize;
|
||||
if (maxSize != null) {
|
||||
parsedMax = FixedDivSize(
|
||||
await maxSize.resolveDimension(
|
||||
context: context,
|
||||
viewScale: viewScale,
|
||||
) +
|
||||
extension * viewScale,
|
||||
);
|
||||
} else {
|
||||
parsedMax = null;
|
||||
}
|
||||
if (minSize != null) {
|
||||
parsedMin = FixedDivSize(
|
||||
await minSize.resolveDimension(
|
||||
context: context,
|
||||
viewScale: viewScale,
|
||||
) +
|
||||
extension * viewScale,
|
||||
);
|
||||
} else {
|
||||
parsedMin = null;
|
||||
}
|
||||
|
||||
return WrapDivSize(
|
||||
await wrapped.constrained?.resolveValue(context: context),
|
||||
maxSize: parsedMax,
|
||||
minSize: parsedMin,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
PassDivSize passValue({
|
||||
required double viewScale,
|
||||
double extension = 0,
|
||||
}) =>
|
||||
map(
|
||||
divFixedSize: (fixed) => FixedDivSize(
|
||||
fixed.valueDimension(
|
||||
viewScale: viewScale,
|
||||
) +
|
||||
extension * viewScale,
|
||||
),
|
||||
divMatchParentSize: (flex) => FlexDivSize(
|
||||
flex.weight?.requireValue.toInt(),
|
||||
),
|
||||
divWrapContentSize: (wrapped) {
|
||||
final FixedDivSize? parsedMax, parsedMin;
|
||||
final maxSize = wrapped.maxSize;
|
||||
final minSize = wrapped.minSize;
|
||||
if (maxSize != null) {
|
||||
parsedMax = FixedDivSize(
|
||||
maxSize.valueDimension(
|
||||
viewScale: viewScale,
|
||||
) +
|
||||
extension * viewScale,
|
||||
);
|
||||
} else {
|
||||
parsedMax = null;
|
||||
}
|
||||
if (minSize != null) {
|
||||
parsedMin = FixedDivSize(
|
||||
minSize.valueDimension(
|
||||
viewScale: viewScale,
|
||||
) +
|
||||
extension * viewScale,
|
||||
);
|
||||
} else {
|
||||
parsedMin = null;
|
||||
}
|
||||
|
||||
return WrapDivSize(
|
||||
wrapped.constrained?.requireValue,
|
||||
maxSize: parsedMax,
|
||||
minSize: parsedMin,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
abstract class _AxisWrapper extends StatelessWidget {
|
||||
Axis get primaryAxis;
|
||||
|
||||
DivAxisAlignment? get alignment;
|
||||
|
||||
ContentAlignment? get contentAlignment;
|
||||
|
||||
PassDivSize get sizeOnCrossAxis;
|
||||
|
||||
bool get canExpand {
|
||||
final contentAlignment = this.contentAlignment;
|
||||
return alignment != null &&
|
||||
(contentAlignment is! FlexContentAlignment ||
|
||||
contentAlignment.direction != primaryAxis);
|
||||
}
|
||||
|
||||
int? get flex {
|
||||
final contentAlignment = this.contentAlignment;
|
||||
if (contentAlignment is FlexContentAlignment) {
|
||||
return contentAlignment.direction == primaryAxis ||
|
||||
sizeOnCrossAxis is FixedDivSize
|
||||
? 0
|
||||
: 1;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const _AxisWrapper();
|
||||
}
|
||||
|
||||
class _HorizontalWrapper extends _AxisWrapper {
|
||||
@override
|
||||
final primaryAxis = Axis.horizontal;
|
||||
@override
|
||||
final DivAxisAlignment? alignment;
|
||||
@override
|
||||
final ContentAlignment? contentAlignment;
|
||||
@override
|
||||
final PassDivSize sizeOnCrossAxis;
|
||||
|
||||
final Widget child;
|
||||
|
||||
const _HorizontalWrapper({
|
||||
required this.child,
|
||||
required this.alignment,
|
||||
required this.contentAlignment,
|
||||
required this.sizeOnCrossAxis,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final row = Row(
|
||||
mainAxisAlignment: alignment?.asMainAxis ?? MainAxisAlignment.start,
|
||||
mainAxisSize: canExpand ? MainAxisSize.max : MainAxisSize.min,
|
||||
children: [child],
|
||||
);
|
||||
|
||||
final flex = super.flex;
|
||||
if (flex != null) {
|
||||
return Flexible(
|
||||
flex: flex,
|
||||
child: row,
|
||||
);
|
||||
}
|
||||
|
||||
return row;
|
||||
}
|
||||
}
|
||||
|
||||
class _VerticalWrapper extends _AxisWrapper {
|
||||
@override
|
||||
final primaryAxis = Axis.vertical;
|
||||
@override
|
||||
final DivAxisAlignment? alignment;
|
||||
@override
|
||||
final ContentAlignment? contentAlignment;
|
||||
@override
|
||||
final PassDivSize sizeOnCrossAxis;
|
||||
|
||||
final Widget child;
|
||||
|
||||
const _VerticalWrapper({
|
||||
required this.child,
|
||||
required this.alignment,
|
||||
required this.contentAlignment,
|
||||
required this.sizeOnCrossAxis,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final column = Column(
|
||||
mainAxisAlignment: alignment?.asMainAxis ?? MainAxisAlignment.start,
|
||||
mainAxisSize: canExpand ? MainAxisSize.max : MainAxisSize.min,
|
||||
children: [child],
|
||||
);
|
||||
|
||||
final flex = super.flex;
|
||||
if (flex != null) {
|
||||
return Flexible(
|
||||
flex: flex,
|
||||
child: column,
|
||||
);
|
||||
}
|
||||
|
||||
return column;
|
||||
}
|
||||
}
|
||||
|
||||
enum DivParentData {
|
||||
none,
|
||||
box,
|
||||
wrap,
|
||||
flex,
|
||||
stack;
|
||||
|
||||
bool get isBox => this == DivParentData.box;
|
||||
|
||||
bool get isWrap => this == DivParentData.wrap;
|
||||
|
||||
bool get isFlex => this == DivParentData.flex;
|
||||
|
||||
bool get isStack => this == DivParentData.stack;
|
||||
|
||||
static DivParentData? from(ParentData? data) {
|
||||
if (data is FlexParentData) {
|
||||
return DivParentData.flex;
|
||||
} else if (data is StackParentData) {
|
||||
return DivParentData.stack;
|
||||
} else if (data is WrapParentData) {
|
||||
return DivParentData.wrap;
|
||||
} else if (data is BoxParentData) {
|
||||
return DivParentData.box;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class DivSizeWrapper extends StatelessWidget {
|
||||
final PassDivSize width;
|
||||
final PassDivSize height;
|
||||
final Widget child;
|
||||
final DivAlignment alignment;
|
||||
final ContentAlignment? contentAlignment;
|
||||
final DivParentData? parent;
|
||||
|
||||
const DivSizeWrapper({
|
||||
required this.child,
|
||||
required this.height,
|
||||
required this.width,
|
||||
required this.alignment,
|
||||
required this.contentAlignment,
|
||||
required this.parent,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final safeWidth = width;
|
||||
final safeHeight = height;
|
||||
final safeAlignment = alignment;
|
||||
|
||||
final maxWidth = safeWidth.maxConstraint;
|
||||
final minWidth = safeWidth.minConstraint;
|
||||
final maxHeight = safeHeight.maxConstraint;
|
||||
final minHeight = safeHeight.minConstraint;
|
||||
|
||||
final safeContentAlignment = contentAlignment;
|
||||
|
||||
final isFlex = parent?.isFlex ?? false;
|
||||
final isStack = parent?.isStack ?? false;
|
||||
|
||||
final Widget wrapper;
|
||||
|
||||
/// Used for stack when layouting complicated objects (Column or Row inside stack with custom position)
|
||||
final bool dropStackLayout;
|
||||
|
||||
if (minHeight != null &&
|
||||
maxHeight != null &&
|
||||
minWidth != null &&
|
||||
maxWidth != null) {
|
||||
dropStackLayout = false;
|
||||
final canBeWrappedHorizontal = safeWidth is! WrapDivSize;
|
||||
final canBeWrappedVertical = safeHeight is! WrapDivSize;
|
||||
|
||||
final isFlexibleOnVerticalAxis =
|
||||
safeContentAlignment is FlexContentAlignment &&
|
||||
safeContentAlignment.direction == Axis.vertical;
|
||||
final isFlexibleOnHorizontalAxis =
|
||||
safeContentAlignment is FlexContentAlignment &&
|
||||
safeContentAlignment.direction == Axis.horizontal;
|
||||
|
||||
if (canBeWrappedHorizontal && canBeWrappedVertical) {
|
||||
wrapper = _VerticalWrapper(
|
||||
sizeOnCrossAxis: safeWidth,
|
||||
contentAlignment: safeContentAlignment,
|
||||
alignment: safeAlignment.vertical,
|
||||
child: _HorizontalWrapper(
|
||||
sizeOnCrossAxis: safeHeight,
|
||||
contentAlignment: safeContentAlignment,
|
||||
alignment: safeAlignment.horizontal,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minHeight: minHeight,
|
||||
maxWidth: maxWidth,
|
||||
maxHeight: maxHeight,
|
||||
minWidth: minWidth,
|
||||
),
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else if (canBeWrappedHorizontal || isFlexibleOnHorizontalAxis) {
|
||||
wrapper = _VerticalWrapper(
|
||||
sizeOnCrossAxis: safeWidth,
|
||||
contentAlignment: null,
|
||||
alignment: safeAlignment.vertical,
|
||||
child: _HorizontalWrapper(
|
||||
sizeOnCrossAxis: safeHeight,
|
||||
contentAlignment: safeContentAlignment,
|
||||
alignment: safeAlignment.horizontal,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minHeight: minHeight,
|
||||
maxWidth: maxWidth,
|
||||
maxHeight: maxHeight,
|
||||
minWidth: minWidth,
|
||||
),
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else if (canBeWrappedVertical || isFlexibleOnVerticalAxis) {
|
||||
wrapper = _VerticalWrapper(
|
||||
sizeOnCrossAxis: safeWidth,
|
||||
contentAlignment: safeContentAlignment,
|
||||
alignment: safeAlignment.vertical,
|
||||
child: _HorizontalWrapper(
|
||||
sizeOnCrossAxis: safeHeight,
|
||||
contentAlignment: null,
|
||||
alignment: safeAlignment.horizontal,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minHeight: minHeight,
|
||||
maxWidth: maxWidth,
|
||||
maxHeight: maxHeight,
|
||||
minWidth: minWidth,
|
||||
),
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
wrapper = ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minHeight: minHeight,
|
||||
maxWidth: maxWidth,
|
||||
maxHeight: maxHeight,
|
||||
minWidth: minWidth,
|
||||
),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
} else if (minHeight != null && maxHeight != null) {
|
||||
final Widget localWrapper;
|
||||
if (safeWidth is FlexDivSize) {
|
||||
localWrapper = _HorizontalWrapper(
|
||||
sizeOnCrossAxis: safeHeight,
|
||||
contentAlignment: isFlex ? safeContentAlignment : null,
|
||||
alignment: safeAlignment.horizontal,
|
||||
child: Expanded(
|
||||
flex: safeWidth.weight ?? 1,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minHeight: minHeight,
|
||||
maxHeight: maxHeight,
|
||||
),
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
localWrapper = ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minHeight: minHeight,
|
||||
maxHeight: maxHeight,
|
||||
),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
if (safeAlignment.vertical != null) {
|
||||
dropStackLayout = true;
|
||||
} else {
|
||||
dropStackLayout = false;
|
||||
}
|
||||
wrapper = _VerticalWrapper(
|
||||
sizeOnCrossAxis: safeWidth,
|
||||
contentAlignment: isFlex ? safeContentAlignment : null,
|
||||
alignment: safeAlignment.vertical,
|
||||
child: localWrapper,
|
||||
);
|
||||
} else if (minWidth != null && maxWidth != null) {
|
||||
final Widget localWrapper;
|
||||
if (safeHeight is FlexDivSize) {
|
||||
localWrapper = _VerticalWrapper(
|
||||
sizeOnCrossAxis: safeWidth,
|
||||
contentAlignment: isFlex ? safeContentAlignment : null,
|
||||
alignment: safeAlignment.vertical,
|
||||
child: Expanded(
|
||||
flex: safeHeight.weight ?? 1,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: maxWidth,
|
||||
minWidth: minWidth,
|
||||
),
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
localWrapper = ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: maxWidth,
|
||||
minWidth: minWidth,
|
||||
),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
if (safeAlignment.horizontal != null) {
|
||||
dropStackLayout = true;
|
||||
} else {
|
||||
dropStackLayout = false;
|
||||
}
|
||||
wrapper = _HorizontalWrapper(
|
||||
sizeOnCrossAxis: safeHeight,
|
||||
contentAlignment: isFlex ? safeContentAlignment : null,
|
||||
alignment: safeAlignment.horizontal,
|
||||
child: localWrapper,
|
||||
);
|
||||
} else if (safeHeight is FlexDivSize &&
|
||||
safeWidth is FlexDivSize &&
|
||||
(isFlex || isStack)) {
|
||||
dropStackLayout = false;
|
||||
if (isFlex) {
|
||||
wrapper = Expanded(
|
||||
flex: safeHeight.weight ?? safeWidth.weight ?? 1,
|
||||
child: SizedBox(
|
||||
height: double.infinity,
|
||||
width: double.infinity,
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
wrapper = SizedBox(
|
||||
height: double.infinity,
|
||||
width: double.infinity,
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
dropStackLayout = false;
|
||||
wrapper = child;
|
||||
}
|
||||
|
||||
if (isStack) {
|
||||
if (dropStackLayout) {
|
||||
return Positioned.fill(
|
||||
child: Align(
|
||||
alignment: safeAlignment.asAlignment ?? Alignment.center,
|
||||
child: wrapper,
|
||||
),
|
||||
);
|
||||
}
|
||||
final alignment = safeAlignment.asAlignment;
|
||||
return Positioned.fill(
|
||||
left: safeAlignment.horizontal == DivAxisAlignment.start ? 0 : null,
|
||||
right: safeAlignment.horizontal == DivAxisAlignment.end ? 0 : null,
|
||||
top: safeAlignment.vertical == DivAxisAlignment.start ? 0 : null,
|
||||
bottom: safeAlignment.vertical == DivAxisAlignment.end ? 0 : null,
|
||||
child: alignment != null
|
||||
? Align(
|
||||
alignment: alignment,
|
||||
child: wrapper,
|
||||
)
|
||||
: wrapper,
|
||||
);
|
||||
}
|
||||
return provide(
|
||||
DivParentData.none,
|
||||
child: wrapper,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ name: divkit
|
||||
description: Open source SDUI framework for server-driven app updates, rapid UI prototyping, and cross-platform layouts.
|
||||
homepage: https://github.com/divkit/divkit
|
||||
repository: https://github.com/divkit/divkit
|
||||
version: 0.3.1-rc.1
|
||||
version: 0.4.0-rc.1
|
||||
|
||||
environment:
|
||||
sdk: '>=2.17.0 <4.0.0'
|
||||
|
||||
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 19 KiB |