Skip to content

Commit 3f659aa

Browse files
authored
fix: detect drag cancelled on desktop while waiting for data (#377)
Fixes #377
1 parent 15b2966 commit 3f659aa

File tree

4 files changed

+59
-7
lines changed

4 files changed

+59
-7
lines changed

super_drag_and_drop/lib/src/drag_internal.dart

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,23 @@ class _DragContextDelegate implements raw.DragContextDelegate {
123123
}
124124
}
125125

126+
class _Drag implements Drag {
127+
bool _ended = false;
128+
129+
@override
130+
void cancel() {
131+
_ended = true;
132+
}
133+
134+
@override
135+
void end(DragEndDetails details) {
136+
_ended = true;
137+
}
138+
139+
@override
140+
void update(DragUpdateDetails details) {}
141+
}
142+
126143
abstract class _DragDetector extends StatelessWidget {
127144
final Widget child;
128145
final DragConfigurationProvider dragConfiguration;
@@ -158,14 +175,16 @@ abstract class _DragDetector extends StatelessWidget {
158175
}
159176
});
160177
}
178+
final drag = _Drag();
161179
_maybeStartDragWithSession(
162180
dragContext,
163181
buildContext,
164182
position,
165183
session,
166184
devicePixelRatio,
185+
drag,
167186
);
168-
return null;
187+
return drag;
169188
} else {
170189
return null;
171190
}
@@ -177,8 +196,14 @@ abstract class _DragDetector extends StatelessWidget {
177196
Offset position,
178197
raw.DragSession session,
179198
double devicePixelRatio,
199+
_Drag drag,
180200
) async {
181201
final dragConfiguration = await this.dragConfiguration(position, session);
202+
// User ended the drag gesture before the data is available.
203+
if (drag._ended) {
204+
_dragContext!.cancelSession(session);
205+
return;
206+
}
182207
if (dragConfiguration != null) {
183208
final rawConfiguration =
184209
await dragConfiguration.intoRaw(devicePixelRatio);

super_native_extensions/lib/src/drag.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ abstract class DragContext {
146146
}
147147

148148
DragSession newSession({int? pointer});
149+
void cancelSession(DragSession session);
149150

150151
Future<void> startDrag({
151152
required BuildContext buildContext,

super_native_extensions/lib/src/native/drag.dart

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ class DragSessionImpl extends DragSession {
7070
}
7171
}
7272

73+
void dispose() {
74+
_dragging.dispose();
75+
_dragCompleted.dispose();
76+
_lastScreenLocation.dispose();
77+
}
78+
7379
final _dragging = ValueNotifier<bool>(false);
7480
final _dragCompleted = ValueNotifier<DropOperation?>(null);
7581
final _lastScreenLocation = ValueNotifier<ui.Offset?>(null);
@@ -182,9 +188,7 @@ class DragContextImpl extends DragContext {
182188
if (session != null) {
183189
session._dragging.value = false;
184190
session._dragCompleted.value = dropOperation;
185-
session._dragging.dispose();
186-
session._dragCompleted.dispose();
187-
session._lastScreenLocation.dispose();
191+
session.dispose();
188192
}
189193
}, () => null);
190194
} else {
@@ -199,6 +203,15 @@ class DragContextImpl extends DragContext {
199203
return DragSessionImpl(dragContext: this);
200204
}
201205

206+
@override
207+
void cancelSession(DragSession session) {
208+
final sessionImpl = session as DragSessionImpl;
209+
assert(sessionImpl.dragCompleted.value == null);
210+
assert(sessionImpl.dragging.value == false);
211+
sessionImpl._dragCompleted.value = DropOperation.userCancelled;
212+
session.dispose();
213+
}
214+
202215
Future<List<Object?>?> getLocalData(int sessionId) async {
203216
return _channel.invokeMethod('getLocalData', {
204217
'sessionId': sessionId,

super_native_extensions/lib/src/web/drag.dart

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,7 @@ class DragSessionImpl extends DragSession implements DragDriverDelegate {
8989
_dragging.value = false;
9090
_state = null;
9191
Future.microtask(() {
92-
_dragCompleted.dispose();
93-
_dragging.dispose();
94-
_lastScreenLocation.dispose();
92+
dispose();
9593
for (final item in configuration.items) {
9694
item.dataProvider.dispose();
9795
}
@@ -102,6 +100,12 @@ class DragSessionImpl extends DragSession implements DragDriverDelegate {
102100
}
103101
}
104102

103+
void dispose() {
104+
_dragCompleted.dispose();
105+
_dragging.dispose();
106+
_lastScreenLocation.dispose();
107+
}
108+
105109
_SessionState? _state;
106110
}
107111

@@ -264,6 +268,15 @@ class DragContextImpl extends DragContext {
264268
DragSession newSession({int? pointer}) =>
265269
DragSessionImpl(pointer: pointer ?? -1);
266270

271+
@override
272+
void cancelSession(DragSession session) {
273+
final sessionImpl = session as DragSessionImpl;
274+
assert(sessionImpl.dragCompleted.value == null);
275+
assert(sessionImpl.dragging.value == false);
276+
sessionImpl._dragCompleted.value = DropOperation.userCancelled;
277+
session.dispose();
278+
}
279+
267280
@override
268281
Future<void> startDrag({
269282
required BuildContext buildContext,

0 commit comments

Comments
 (0)