@@ -6,7 +6,94 @@ import '../models.dart';
66
77part 'show_dialog_action.g.dart' ;
88
9- /// An action that navigates to a new page.
9+ /// Where a [ShowDialogAction] shows its canvas.
10+ enum DialogAnchor {
11+ /// Centered on the screen.
12+ none,
13+
14+ /// Next to the node that ran the action, like a popover or menu, at the
15+ /// action's [ShowDialogAction.placement] .
16+ trigger;
17+
18+ /// Displayable name.
19+ String get prettify => switch (this ) {
20+ DialogAnchor .none => 'Center of screen' ,
21+ DialogAnchor .trigger => 'Anchor to trigger' ,
22+ };
23+ }
24+
25+ /// The side of the trigger an anchored [ShowDialogAction] opens on, and how
26+ /// it lines up with the trigger along that side.
27+ ///
28+ /// Start and end follow the reading direction for [below] and [above]
29+ /// placements (start is the left edge in a left-to-right app) and are the top
30+ /// and bottom edges for [right] and [left] placements. When the dialog does
31+ /// not fit on its side, it opens on the opposite side if there is more room
32+ /// there.
33+ enum DialogPlacement {
34+ /// Below the trigger, start edges lined up.
35+ belowStart,
36+
37+ /// Below the trigger, centered on it.
38+ belowCenter,
39+
40+ /// Below the trigger, end edges lined up.
41+ belowEnd,
42+
43+ /// Above the trigger, start edges lined up.
44+ aboveStart,
45+
46+ /// Above the trigger, centered on it.
47+ aboveCenter,
48+
49+ /// Above the trigger, end edges lined up.
50+ aboveEnd,
51+
52+ /// Right of the trigger, top edges lined up.
53+ rightStart,
54+
55+ /// Right of the trigger, centered on it.
56+ rightCenter,
57+
58+ /// Right of the trigger, bottom edges lined up.
59+ rightEnd,
60+
61+ /// Left of the trigger, top edges lined up.
62+ leftStart,
63+
64+ /// Left of the trigger, centered on it.
65+ leftCenter,
66+
67+ /// Left of the trigger, bottom edges lined up.
68+ leftEnd;
69+
70+ /// Whether the dialog opens below or above the trigger, rather than beside
71+ /// it.
72+ bool get isVertical => index <= DialogPlacement .aboveEnd.index;
73+
74+ /// Displayable name.
75+ String get prettify => switch (this ) {
76+ DialogPlacement .belowStart => 'Below, start' ,
77+ DialogPlacement .belowCenter => 'Below, center' ,
78+ DialogPlacement .belowEnd => 'Below, end' ,
79+ DialogPlacement .aboveStart => 'Above, start' ,
80+ DialogPlacement .aboveCenter => 'Above, center' ,
81+ DialogPlacement .aboveEnd => 'Above, end' ,
82+ DialogPlacement .rightStart => 'Right, top' ,
83+ DialogPlacement .rightCenter => 'Right, center' ,
84+ DialogPlacement .rightEnd => 'Right, bottom' ,
85+ DialogPlacement .leftStart => 'Left, top' ,
86+ DialogPlacement .leftCenter => 'Left, center' ,
87+ DialogPlacement .leftEnd => 'Left, bottom' ,
88+ };
89+ }
90+
91+ /// An action that shows a canvas as a dialog: centered on the screen, or,
92+ /// with [anchor] set to [DialogAnchor.trigger] , as a popover next to the node
93+ /// that ran it (an account menu under an avatar, for example).
94+ ///
95+ /// The dialog closes when its barrier is tapped (if [barrierDismissible] ) or
96+ /// with a "Navigate back" action inside it.
1097@JsonSerializable ()
1198class ShowDialogAction extends ActionModel with Equatable , SerializableMixin {
1299 /// Destination canvas node's ID.
@@ -24,13 +111,36 @@ class ShowDialogAction extends ActionModel with Equatable, SerializableMixin {
24111 /// Whether to show a close button on the dialog.
25112 final bool showCloseButton;
26113
114+ /// Where the dialog shows: centered, or next to the node that ran the
115+ /// action.
116+ @JsonKey (unknownEnumValue: DialogAnchor .none)
117+ final DialogAnchor anchor;
118+
119+ /// The side of the trigger an anchored dialog opens on. Only used when
120+ /// [anchor] is [DialogAnchor.trigger] .
121+ @JsonKey (unknownEnumValue: DialogPlacement .belowStart)
122+ final DialogPlacement placement;
123+
124+ /// The space between the trigger and an anchored dialog, in logical
125+ /// pixels.
126+ final double anchorGap;
127+
128+ /// How far an anchored dialog is shifted along the trigger's edge, in
129+ /// logical pixels: toward the end for [DialogPlacement.isVertical]
130+ /// placements (right in a left-to-right app), down for the others.
131+ final double anchorOffset;
132+
27133 /// Creates a new [ShowDialogAction] .
28134 ShowDialogAction ({
29135 required this .destinationId,
30136 Map <String , String >? params,
31137 this .barrierColor = ColorRGBA .black54,
32138 this .barrierDismissible = true ,
33139 this .showCloseButton = false ,
140+ this .anchor = DialogAnchor .none,
141+ this .placement = DialogPlacement .belowStart,
142+ this .anchorGap = 4 ,
143+ this .anchorOffset = 0 ,
34144 super .nonBlocking,
35145 super .enabled,
36146 }) : params = {...params ?? {}},
@@ -43,21 +153,38 @@ class ShowDialogAction extends ActionModel with Equatable, SerializableMixin {
43153 barrierDismissible,
44154 barrierColor,
45155 showCloseButton,
156+ anchor,
157+ placement,
158+ anchorGap,
159+ anchorOffset,
46160 ];
47161
162+ /// Whether the dialog opens next to the node that ran the action.
163+ bool get isAnchored => anchor == DialogAnchor .trigger;
164+
48165 /// Duplicates this [ShowDialogAction] with given data overrides.
49166 ShowDialogAction copyWith ({
50167 String ? destinationId,
51168 Map <String , String >? params,
52169 bool ? barrierDismissible,
53170 ColorRGBA ? barrierColor,
54171 bool ? showCloseButton,
172+ DialogAnchor ? anchor,
173+ DialogPlacement ? placement,
174+ double ? anchorGap,
175+ double ? anchorOffset,
55176 }) => ShowDialogAction (
56177 destinationId: destinationId ?? this .destinationId,
57178 params: {...this .params, ...params ?? {}},
58179 barrierDismissible: barrierDismissible ?? this .barrierDismissible,
59180 barrierColor: barrierColor ?? this .barrierColor,
60181 showCloseButton: showCloseButton ?? this .showCloseButton,
182+ anchor: anchor ?? this .anchor,
183+ placement: placement ?? this .placement,
184+ anchorGap: anchorGap ?? this .anchorGap,
185+ anchorOffset: anchorOffset ?? this .anchorOffset,
186+ nonBlocking: nonBlocking,
187+ enabled: enabled,
61188 );
62189
63190 /// Creates a new [ShowDialogAction] instance from a JSON data.
0 commit comments