Add Expanded/Collapsed State for Semantics (#131233)
This commit is contained in:
parent
e0b6b6c451
commit
71d96ddf9c
@ -1079,7 +1079,7 @@ class _MenuItemButtonState extends State<MenuItemButton> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return child;
|
return MergeSemantics(child: child);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleFocusChange() {
|
void _handleFocusChange() {
|
||||||
@ -1904,8 +1904,10 @@ class _SubmenuButtonState extends State<SubmenuButton> {
|
|||||||
controller._anchor!._focusButton();
|
controller._anchor!._focusButton();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
child = MergeSemantics(
|
||||||
child = TextButton(
|
child: Semantics(
|
||||||
|
expanded: controller.isOpen,
|
||||||
|
child: TextButton(
|
||||||
style: mergedStyle,
|
style: mergedStyle,
|
||||||
focusNode: _buttonFocusNode,
|
focusNode: _buttonFocusNode,
|
||||||
onHover: _enabled ? (bool hovering) => handleHover(hovering, context) : null,
|
onHover: _enabled ? (bool hovering) => handleHover(hovering, context) : null,
|
||||||
@ -1918,6 +1920,8 @@ class _SubmenuButtonState extends State<SubmenuButton> {
|
|||||||
showDecoration: (controller._anchor!._parent?._orientation ?? Axis.horizontal) == Axis.vertical,
|
showDecoration: (controller._anchor!._parent?._orientation ?? Axis.horizontal) == Axis.vertical,
|
||||||
child: child ?? const SizedBox(),
|
child: child ?? const SizedBox(),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (_enabled && _platformSupportsAccelerators) {
|
if (_enabled && _platformSupportsAccelerators) {
|
||||||
|
@ -900,6 +900,9 @@ class RenderCustomPaint extends RenderProxyBox {
|
|||||||
if (properties.button != null) {
|
if (properties.button != null) {
|
||||||
config.isButton = properties.button!;
|
config.isButton = properties.button!;
|
||||||
}
|
}
|
||||||
|
if (properties.expanded != null) {
|
||||||
|
config.isExpanded = properties.expanded;
|
||||||
|
}
|
||||||
if (properties.link != null) {
|
if (properties.link != null) {
|
||||||
config.isLink = properties.link!;
|
config.isLink = properties.link!;
|
||||||
}
|
}
|
||||||
|
@ -4319,6 +4319,9 @@ class RenderSemanticsAnnotations extends RenderProxyBox {
|
|||||||
if (_properties.button != null) {
|
if (_properties.button != null) {
|
||||||
config.isButton = _properties.button!;
|
config.isButton = _properties.button!;
|
||||||
}
|
}
|
||||||
|
if (_properties.expanded != null) {
|
||||||
|
config.isExpanded = _properties.expanded;
|
||||||
|
}
|
||||||
if (_properties.link != null) {
|
if (_properties.link != null) {
|
||||||
config.isLink = _properties.link!;
|
config.isLink = _properties.link!;
|
||||||
}
|
}
|
||||||
|
@ -870,6 +870,7 @@ class SemanticsProperties extends DiagnosticableTree {
|
|||||||
this.enabled,
|
this.enabled,
|
||||||
this.checked,
|
this.checked,
|
||||||
this.mixed,
|
this.mixed,
|
||||||
|
this.expanded,
|
||||||
this.selected,
|
this.selected,
|
||||||
this.toggled,
|
this.toggled,
|
||||||
this.button,
|
this.button,
|
||||||
@ -964,6 +965,14 @@ class SemanticsProperties extends DiagnosticableTree {
|
|||||||
/// This is mutually exclusive with [checked] and [toggled].
|
/// This is mutually exclusive with [checked] and [toggled].
|
||||||
final bool? mixed;
|
final bool? mixed;
|
||||||
|
|
||||||
|
/// If non-null, indicates that this subtree represents something
|
||||||
|
/// that can be in an "expanded" or "collapsed" state.
|
||||||
|
///
|
||||||
|
/// For example, if a [SubmenuButton] is opened, this property
|
||||||
|
/// should be set to true; otherwise, this property should be
|
||||||
|
/// false.
|
||||||
|
final bool? expanded;
|
||||||
|
|
||||||
/// If non-null, indicates that this subtree represents a toggle switch
|
/// If non-null, indicates that this subtree represents a toggle switch
|
||||||
/// or similar widget with an "on" state, and what its current
|
/// or similar widget with an "on" state, and what its current
|
||||||
/// state is.
|
/// state is.
|
||||||
@ -1612,6 +1621,7 @@ class SemanticsProperties extends DiagnosticableTree {
|
|||||||
super.debugFillProperties(properties);
|
super.debugFillProperties(properties);
|
||||||
properties.add(DiagnosticsProperty<bool>('checked', checked, defaultValue: null));
|
properties.add(DiagnosticsProperty<bool>('checked', checked, defaultValue: null));
|
||||||
properties.add(DiagnosticsProperty<bool>('mixed', mixed, defaultValue: null));
|
properties.add(DiagnosticsProperty<bool>('mixed', mixed, defaultValue: null));
|
||||||
|
properties.add(DiagnosticsProperty<bool>('expanded', expanded, defaultValue: null));
|
||||||
properties.add(DiagnosticsProperty<bool>('selected', selected, defaultValue: null));
|
properties.add(DiagnosticsProperty<bool>('selected', selected, defaultValue: null));
|
||||||
properties.add(StringProperty('label', label, defaultValue: null));
|
properties.add(StringProperty('label', label, defaultValue: null));
|
||||||
properties.add(AttributedStringProperty('attributedLabel', attributedLabel, defaultValue: null));
|
properties.add(AttributedStringProperty('attributedLabel', attributedLabel, defaultValue: null));
|
||||||
@ -4398,6 +4408,20 @@ class SemanticsConfiguration {
|
|||||||
_setFlag(SemanticsFlag.isSelected, value);
|
_setFlag(SemanticsFlag.isSelected, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If this node has Boolean state that can be controlled by the user, whether
|
||||||
|
/// that state is expanded or collapsed, corresponding to true and false, respectively.
|
||||||
|
///
|
||||||
|
/// Do not call the setter for this field if the owning [RenderObject] doesn't
|
||||||
|
/// have expanded/collapsed state that can be controlled by the user.
|
||||||
|
///
|
||||||
|
/// The getter returns null if the owning [RenderObject] does not have
|
||||||
|
/// expanded/collapsed state.
|
||||||
|
bool? get isExpanded => _hasFlag(SemanticsFlag.hasExpandedState) ? _hasFlag(SemanticsFlag.isExpanded) : null;
|
||||||
|
set isExpanded(bool? value) {
|
||||||
|
_setFlag(SemanticsFlag.hasExpandedState, true);
|
||||||
|
_setFlag(SemanticsFlag.isExpanded, value!);
|
||||||
|
}
|
||||||
|
|
||||||
/// Whether the owning [RenderObject] is currently enabled.
|
/// Whether the owning [RenderObject] is currently enabled.
|
||||||
///
|
///
|
||||||
/// A disabled object does not respond to user interactions. Only objects that
|
/// A disabled object does not respond to user interactions. Only objects that
|
||||||
|
@ -7138,6 +7138,7 @@ class Semantics extends SingleChildRenderObjectWidget {
|
|||||||
bool? hidden,
|
bool? hidden,
|
||||||
bool? image,
|
bool? image,
|
||||||
bool? liveRegion,
|
bool? liveRegion,
|
||||||
|
bool? expanded,
|
||||||
int? maxValueLength,
|
int? maxValueLength,
|
||||||
int? currentValueLength,
|
int? currentValueLength,
|
||||||
String? label,
|
String? label,
|
||||||
@ -7186,6 +7187,7 @@ class Semantics extends SingleChildRenderObjectWidget {
|
|||||||
enabled: enabled,
|
enabled: enabled,
|
||||||
checked: checked,
|
checked: checked,
|
||||||
mixed: mixed,
|
mixed: mixed,
|
||||||
|
expanded: expanded,
|
||||||
toggled: toggled,
|
toggled: toggled,
|
||||||
selected: selected,
|
selected: selected,
|
||||||
button: button,
|
button: button,
|
||||||
|
@ -3181,7 +3181,8 @@ void main() {
|
|||||||
children: <TestSemantics>[
|
children: <TestSemantics>[
|
||||||
TestSemantics(
|
TestSemantics(
|
||||||
rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0),
|
rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0),
|
||||||
flags: <SemanticsFlag>[SemanticsFlag.hasEnabledState],
|
flags: <SemanticsFlag>[SemanticsFlag.hasEnabledState,
|
||||||
|
SemanticsFlag.hasExpandedState],
|
||||||
label: 'ABC',
|
label: 'ABC',
|
||||||
textDirection: TextDirection.ltr,
|
textDirection: TextDirection.ltr,
|
||||||
),
|
),
|
||||||
@ -3194,6 +3195,131 @@ void main() {
|
|||||||
|
|
||||||
semantics.dispose();
|
semantics.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('SubmenuButton expanded/collapsed state', (WidgetTester tester) async {
|
||||||
|
final SemanticsTester semantics = SemanticsTester(tester);
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Center(
|
||||||
|
child: SubmenuButton(
|
||||||
|
onHover: (bool value) {},
|
||||||
|
style: SubmenuButton.styleFrom(fixedSize: const Size(88.0, 36.0)),
|
||||||
|
menuChildren: <Widget>[
|
||||||
|
MenuItemButton(
|
||||||
|
child: const Text('Item 0'),
|
||||||
|
onPressed: () {},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
child: const Text('ABC'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test expanded state.
|
||||||
|
await tester.tap(find.text('ABC'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
semantics,
|
||||||
|
hasSemantics(
|
||||||
|
TestSemantics.root(
|
||||||
|
children: <TestSemantics>[
|
||||||
|
TestSemantics(
|
||||||
|
id: 1,
|
||||||
|
rect: const Rect.fromLTRB(0.0, 0.0, 800.0, 600.0),
|
||||||
|
children: <TestSemantics> [
|
||||||
|
TestSemantics(
|
||||||
|
id: 2,
|
||||||
|
rect: const Rect.fromLTRB(0.0, 0.0, 800.0, 600.0),
|
||||||
|
children: <TestSemantics> [
|
||||||
|
TestSemantics(
|
||||||
|
id: 3,
|
||||||
|
rect: const Rect.fromLTRB(0.0, 0.0, 800.0, 600.0),
|
||||||
|
flags: <SemanticsFlag> [SemanticsFlag.scopesRoute],
|
||||||
|
children: <TestSemantics> [
|
||||||
|
TestSemantics(
|
||||||
|
id: 4,
|
||||||
|
flags: <SemanticsFlag>[SemanticsFlag.hasExpandedState, SemanticsFlag.isExpanded, SemanticsFlag.isFocused, SemanticsFlag.hasEnabledState, SemanticsFlag.isEnabled,
|
||||||
|
SemanticsFlag.isFocusable],
|
||||||
|
actions: <SemanticsAction>[SemanticsAction.tap],
|
||||||
|
label: 'ABC',
|
||||||
|
rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
TestSemantics(
|
||||||
|
id: 6,
|
||||||
|
rect: const Rect.fromLTRB(0.0, 0.0, 123.0, 64.0),
|
||||||
|
children: <TestSemantics> [
|
||||||
|
TestSemantics(
|
||||||
|
id: 7,
|
||||||
|
rect: const Rect.fromLTRB(0.0, 0.0, 123.0, 48.0),
|
||||||
|
flags: <SemanticsFlag> [SemanticsFlag.hasImplicitScrolling],
|
||||||
|
children: <TestSemantics> [
|
||||||
|
TestSemantics(
|
||||||
|
id: 8,
|
||||||
|
label: 'Item 0',
|
||||||
|
rect: const Rect.fromLTRB(0.0, 0.0, 123.0, 48.0),
|
||||||
|
flags: <SemanticsFlag>[SemanticsFlag.hasEnabledState, SemanticsFlag.isEnabled, SemanticsFlag.isFocusable],
|
||||||
|
actions: <SemanticsAction>[SemanticsAction.tap],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
ignoreTransform: true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test collapsed state.
|
||||||
|
await tester.tap(find.text('ABC'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(
|
||||||
|
semantics,
|
||||||
|
hasSemantics(
|
||||||
|
TestSemantics.root(
|
||||||
|
children: <TestSemantics>[
|
||||||
|
TestSemantics(
|
||||||
|
id: 1,
|
||||||
|
rect: const Rect.fromLTRB(0.0, 0.0, 800.0, 600.0),
|
||||||
|
children: <TestSemantics> [
|
||||||
|
TestSemantics(
|
||||||
|
id: 2,
|
||||||
|
rect: const Rect.fromLTRB(0.0, 0.0, 800.0, 600.0),
|
||||||
|
children: <TestSemantics> [
|
||||||
|
TestSemantics(
|
||||||
|
id: 3,
|
||||||
|
rect: const Rect.fromLTRB(0.0, 0.0, 800.0, 600.0),
|
||||||
|
flags: <SemanticsFlag> [SemanticsFlag.scopesRoute],
|
||||||
|
children: <TestSemantics> [
|
||||||
|
TestSemantics(
|
||||||
|
id: 4,
|
||||||
|
flags: <SemanticsFlag>[SemanticsFlag.hasExpandedState, SemanticsFlag.isFocused, SemanticsFlag.hasEnabledState, SemanticsFlag.isEnabled,
|
||||||
|
SemanticsFlag.isFocusable],
|
||||||
|
actions: <SemanticsAction>[SemanticsAction.tap],
|
||||||
|
label: 'ABC',
|
||||||
|
rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
ignoreTransform: true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
semantics.dispose();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,6 +440,7 @@ void _defineTests() {
|
|||||||
image: true,
|
image: true,
|
||||||
liveRegion: true,
|
liveRegion: true,
|
||||||
toggled: true,
|
toggled: true,
|
||||||
|
expanded: true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -494,6 +495,7 @@ void _defineTests() {
|
|||||||
namesRoute: true,
|
namesRoute: true,
|
||||||
image: true,
|
image: true,
|
||||||
liveRegion: true,
|
liveRegion: true,
|
||||||
|
expanded: true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -520,7 +522,7 @@ void _defineTests() {
|
|||||||
);
|
);
|
||||||
expect(semantics, hasSemantics(expectedSemantics, ignoreRect: true, ignoreTransform: true));
|
expect(semantics, hasSemantics(expectedSemantics, ignoreRect: true, ignoreTransform: true));
|
||||||
semantics.dispose();
|
semantics.dispose();
|
||||||
}, skip: true); // https://github.com/flutter/flutter/issues/127617
|
});
|
||||||
|
|
||||||
group('diffing', () {
|
group('diffing', () {
|
||||||
testWidgets('complains about duplicate keys', (WidgetTester tester) async {
|
testWidgets('complains about duplicate keys', (WidgetTester tester) async {
|
||||||
|
@ -609,6 +609,7 @@ void main() {
|
|||||||
namesRoute: true,
|
namesRoute: true,
|
||||||
image: true,
|
image: true,
|
||||||
liveRegion: true,
|
liveRegion: true,
|
||||||
|
expanded: true,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
final List<SemanticsFlag> flags = SemanticsFlag.values.toList();
|
final List<SemanticsFlag> flags = SemanticsFlag.values.toList();
|
||||||
@ -691,6 +692,7 @@ void main() {
|
|||||||
namesRoute: true,
|
namesRoute: true,
|
||||||
image: true,
|
image: true,
|
||||||
liveRegion: true,
|
liveRegion: true,
|
||||||
|
expanded: true,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
flags
|
flags
|
||||||
@ -706,7 +708,7 @@ void main() {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
expect(semantics, hasSemantics(expectedSemantics, ignoreId: true));
|
expect(semantics, hasSemantics(expectedSemantics, ignoreId: true));
|
||||||
}, skip: true); // https://github.com/flutter/flutter/issues/127617
|
});
|
||||||
|
|
||||||
testWidgets('Actions can be replaced without triggering semantics update', (WidgetTester tester) async {
|
testWidgets('Actions can be replaced without triggering semantics update', (WidgetTester tester) async {
|
||||||
final SemanticsTester semantics = SemanticsTester(tester);
|
final SemanticsTester semantics = SemanticsTester(tester);
|
||||||
|
@ -564,6 +564,8 @@ Matcher matchesSemantics({
|
|||||||
bool hasToggledState = false,
|
bool hasToggledState = false,
|
||||||
bool isToggled = false,
|
bool isToggled = false,
|
||||||
bool hasImplicitScrolling = false,
|
bool hasImplicitScrolling = false,
|
||||||
|
bool hasExpandedState = false,
|
||||||
|
bool isExpanded = false,
|
||||||
// Actions //
|
// Actions //
|
||||||
bool hasTapAction = false,
|
bool hasTapAction = false,
|
||||||
bool hasLongPressAction = false,
|
bool hasLongPressAction = false,
|
||||||
@ -640,6 +642,8 @@ Matcher matchesSemantics({
|
|||||||
hasToggledState: hasToggledState,
|
hasToggledState: hasToggledState,
|
||||||
isToggled: isToggled,
|
isToggled: isToggled,
|
||||||
hasImplicitScrolling: hasImplicitScrolling,
|
hasImplicitScrolling: hasImplicitScrolling,
|
||||||
|
hasExpandedState: hasExpandedState,
|
||||||
|
isExpanded: isExpanded,
|
||||||
// Actions
|
// Actions
|
||||||
hasTapAction: hasTapAction,
|
hasTapAction: hasTapAction,
|
||||||
hasLongPressAction: hasLongPressAction,
|
hasLongPressAction: hasLongPressAction,
|
||||||
@ -737,6 +741,8 @@ Matcher containsSemantics({
|
|||||||
bool? hasToggledState,
|
bool? hasToggledState,
|
||||||
bool? isToggled,
|
bool? isToggled,
|
||||||
bool? hasImplicitScrolling,
|
bool? hasImplicitScrolling,
|
||||||
|
bool? hasExpandedState,
|
||||||
|
bool? isExpanded,
|
||||||
// Actions
|
// Actions
|
||||||
bool? hasTapAction,
|
bool? hasTapAction,
|
||||||
bool? hasLongPressAction,
|
bool? hasLongPressAction,
|
||||||
@ -813,6 +819,8 @@ Matcher containsSemantics({
|
|||||||
hasToggledState: hasToggledState,
|
hasToggledState: hasToggledState,
|
||||||
isToggled: isToggled,
|
isToggled: isToggled,
|
||||||
hasImplicitScrolling: hasImplicitScrolling,
|
hasImplicitScrolling: hasImplicitScrolling,
|
||||||
|
hasExpandedState: hasExpandedState,
|
||||||
|
isExpanded: isExpanded,
|
||||||
// Actions
|
// Actions
|
||||||
hasTapAction: hasTapAction,
|
hasTapAction: hasTapAction,
|
||||||
hasLongPressAction: hasLongPressAction,
|
hasLongPressAction: hasLongPressAction,
|
||||||
@ -2111,6 +2119,8 @@ class _MatchesSemanticsData extends Matcher {
|
|||||||
required bool? hasToggledState,
|
required bool? hasToggledState,
|
||||||
required bool? isToggled,
|
required bool? isToggled,
|
||||||
required bool? hasImplicitScrolling,
|
required bool? hasImplicitScrolling,
|
||||||
|
required bool? hasExpandedState,
|
||||||
|
required bool? isExpanded,
|
||||||
// Actions
|
// Actions
|
||||||
required bool? hasTapAction,
|
required bool? hasTapAction,
|
||||||
required bool? hasLongPressAction,
|
required bool? hasLongPressAction,
|
||||||
@ -2166,6 +2176,8 @@ class _MatchesSemanticsData extends Matcher {
|
|||||||
if (isToggled != null) SemanticsFlag.isToggled: isToggled,
|
if (isToggled != null) SemanticsFlag.isToggled: isToggled,
|
||||||
if (hasImplicitScrolling != null) SemanticsFlag.hasImplicitScrolling: hasImplicitScrolling,
|
if (hasImplicitScrolling != null) SemanticsFlag.hasImplicitScrolling: hasImplicitScrolling,
|
||||||
if (isSlider != null) SemanticsFlag.isSlider: isSlider,
|
if (isSlider != null) SemanticsFlag.isSlider: isSlider,
|
||||||
|
if (hasExpandedState != null) SemanticsFlag.hasExpandedState: hasExpandedState,
|
||||||
|
if (isExpanded != null) SemanticsFlag.isExpanded: isExpanded,
|
||||||
},
|
},
|
||||||
actions = <SemanticsAction, bool>{
|
actions = <SemanticsAction, bool>{
|
||||||
if (hasTapAction != null) SemanticsAction.tap: hasTapAction,
|
if (hasTapAction != null) SemanticsAction.tap: hasTapAction,
|
||||||
|
@ -683,6 +683,8 @@ void main() {
|
|||||||
hasToggledState: true,
|
hasToggledState: true,
|
||||||
isToggled: true,
|
isToggled: true,
|
||||||
hasImplicitScrolling: true,
|
hasImplicitScrolling: true,
|
||||||
|
hasExpandedState: true,
|
||||||
|
isExpanded: true,
|
||||||
/* Actions */
|
/* Actions */
|
||||||
hasTapAction: true,
|
hasTapAction: true,
|
||||||
hasLongPressAction: true,
|
hasLongPressAction: true,
|
||||||
@ -966,6 +968,8 @@ void main() {
|
|||||||
hasToggledState: true,
|
hasToggledState: true,
|
||||||
isToggled: true,
|
isToggled: true,
|
||||||
hasImplicitScrolling: true,
|
hasImplicitScrolling: true,
|
||||||
|
hasExpandedState: true,
|
||||||
|
isExpanded: true,
|
||||||
/* Actions */
|
/* Actions */
|
||||||
hasTapAction: true,
|
hasTapAction: true,
|
||||||
hasLongPressAction: true,
|
hasLongPressAction: true,
|
||||||
@ -1055,6 +1059,8 @@ void main() {
|
|||||||
hasToggledState: false,
|
hasToggledState: false,
|
||||||
isToggled: false,
|
isToggled: false,
|
||||||
hasImplicitScrolling: false,
|
hasImplicitScrolling: false,
|
||||||
|
hasExpandedState: false,
|
||||||
|
isExpanded: false,
|
||||||
/* Actions */
|
/* Actions */
|
||||||
hasTapAction: false,
|
hasTapAction: false,
|
||||||
hasLongPressAction: false,
|
hasLongPressAction: false,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user