MixinNetwork / MixinNetwork/flutter-plugins

[desktop_drop] The function of `onDrag*` would execute multiple times when current widget is not root route

Open
#389 3 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C
Stars
512
Forks
292
Avg merge
15h 8m
Merged PRs (30d)
7

Description

When using Navigator.of(context).push(...) to another route, desktop_drop would execute multiple times. Here is my test code

import 'package:flutter/material.dart';
import 'package:desktop_drop/desktop_drop.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        useMaterial3: true,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Home Page"),
      ),
      body: MyDragWidget(
        title: "home",
        child: Center(
          child: TextButton(
            onPressed: () {
              Navigator.of(context).push(
                MaterialPageRoute(builder: (context) => const MySecondPage()),
              );
            },
            child: Text("to second page"),
          ),
        ),
      ),
    );
  }
}

class MySecondPage extends StatelessWidget {
  const MySecondPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Page"),
      ),
      body: MyDragWidget(
        title: "second",
        child: Center(
          child: TextButton(
            onPressed: () {
              Navigator.of(context).push(
                MaterialPageRoute(builder: (context) => const MyThirdPage()),
              );
            },
            child: Text("to third page"),
          ),
        ),
      ),
    );
  }
}

class MyThirdPage extends StatelessWidget {
  const MyThirdPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Third Page"),
      ),
      body: MyDragWidget(
        title: "third",
        child: Center(
          child: Text("third page"),
        ),
      ),
    );
  }
}

class MyDragWidget extends StatefulWidget {
  const MyDragWidget({super.key, required this.title, required this.child});

  final String title;
  final Widget child;

  @override
  State<MyDragWidget> createState() => _MyDragWidgetState();
}

class _MyDragWidgetState extends State<MyDragWidget> {
  bool _dragging = false;

  @override
  Widget build(BuildContext context) {
    return DropTarget(
      onDragDone: (detail) async {
        print("${widget.title} done");
      },
      onDragEntered: (detail) {
        setState(() {
          _dragging = true;
        });

        print("${widget.title} entered");
      },
      onDragExited: (detail) {
        setState(() {
          _dragging = false;
        });

        print("${widget.title} exited");
      },
      child: _dragging
          ? Container(
              width: double.infinity,
              height: double.infinity,
              color: Colors.black.withOpacity(0.2),
              child: Center(
                child: Text("Drag Files"),
              ),
            )
          : widget.child,
    );
  }
}

Reproduce Steps

When in MyHomePage,the output is

flutter: home entered
flutter: home exited
flutter: home done

When in MySecondPage,the output is

flutter: home entered
flutter: second entered
flutter: home exited
flutter: home done
flutter: second exited
flutter: second done

When in MyThirdPage,the output is

flutter: home entered
flutter: second entered
flutter: third entered
flutter: home exited
flutter: home done
flutter: second exited
flutter: second done
flutter: third exited
flutter: third done

Expected behavior

The function of onDrag* only execute once whatever current widget is root route or not.

Version (please complete the following information):

  • Flutter Version: 3.27.3
  • OS: MacOS
  • plugin: desktop_drop: ^0.5.0

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the issue with the provided Flutter example using desktop_drop's DropTarget and nested Navigator routes. Inspect how DropTarget handles onDragEntered, onDragExited, and onDragDone across stacked routes. Done means each drag callback executes only once for the currently visible route, including when it is not the root route.

Written by the indexing model from the issue text.

Assessment

Tech stack
dart, flutter
Domain
desktop
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.