Skip to content

Commit 721e823

Browse files
aditya-chavdaSahil-Simform
authored andcommitted
fix: 🐛 Showcase stuck when animation is disabled on web
- Fix detailscreen to use cached version of the scope to avoid race conditions.
1 parent dabdbcd commit 721e823

File tree

2 files changed

+22
-8
lines changed

2 files changed

+22
-8
lines changed

example/lib/detailscreen.dart

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@ class Detail extends StatefulWidget {
1111
class _DetailState extends State<Detail> {
1212
final GlobalKey _one = GlobalKey();
1313
BuildContext? myContext;
14-
final scopeName = "_detailsScreen";
14+
15+
// This is optional but if you need different configuration in
16+
// ShowcaseView then you can register new ShowcaseView
17+
final showcaseDetailScope = ShowcaseView.register(scope: "_detailsScreen");
1518

1619
@override
1720
void initState() {
1821
super.initState();
19-
// This is optional but if you need different configuration in
20-
// ShowcaseView then you can register new ShowcaseView
21-
ShowcaseView.register(scope: scopeName);
2222
WidgetsBinding.instance.addPostFrameCallback(
23-
(_) => ShowcaseView.getNamed(scopeName)
23+
(_) => showcaseDetailScope
2424
..startShowCase([_one], delay: const Duration(milliseconds: 200))
2525
..addOnFinishCallback(_onShowcaseFinished)
2626
..addOnDismissCallback(_onShowcaseDismissed),
@@ -29,7 +29,7 @@ class _DetailState extends State<Detail> {
2929

3030
@override
3131
void dispose() {
32-
ShowcaseView.getNamed(scopeName)
32+
showcaseDetailScope
3333
..removeOnFinishCallback(_onShowcaseFinished)
3434
..removeOnDismissCallback(_onShowcaseDismissed);
3535
super.dispose();
@@ -76,7 +76,7 @@ class _DetailState extends State<Detail> {
7676
style: ElevatedButton.styleFrom(
7777
backgroundColor: const Color(0xffEE5366),
7878
),
79-
onPressed: ShowcaseView.getNamed(scopeName).dismiss,
79+
onPressed: showcaseDetailScope.dismiss,
8080
child: const Text(
8181
'Close Showcase',
8282
style: TextStyle(

lib/src/showcase/showcase_controller.dart

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@
1919
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2020
* SOFTWARE.
2121
*/
22+
import 'dart:async';
2223
import 'dart:math';
2324

2425
import 'package:flutter/foundation.dart';
26+
import 'package:flutter/scheduler.dart';
2527
import 'package:flutter/widgets.dart';
2628

2729
import '../models/flutter_inherited_data.dart';
@@ -210,7 +212,7 @@ class ShowcaseController {
210212
bool shouldUpdateOverlay = true,
211213
}) {
212214
if (!showcaseView.enableShowcase || !showcaseView.isShowcaseRunning) return;
213-
WidgetsBinding.instance.addPostFrameCallback((_) {
215+
_runLater(() {
214216
if (!context.mounted ||
215217
!showcaseView.enableShowcase ||
216218
!showcaseView.isShowcaseRunning) {
@@ -443,6 +445,18 @@ class ShowcaseController {
443445
FloatingActionWidget? get _getFloatingActionWidget =>
444446
config.floatingActionWidget ?? globalFloatingActionWidget;
445447

448+
/// Schedules a callback to run after the current frame with guarantee.
449+
void _runLater(VoidCallback process) {
450+
final scheduler = SchedulerBinding.instance;
451+
// Schedule a frame if none is scheduled to ensure the callback runs.
452+
// This is useful particularly when [disableMovingAnimation] is true and so
453+
// flutter doesn't another frame on web.
454+
if (!scheduler.hasScheduledFrame) {
455+
scheduler.scheduleFrame();
456+
}
457+
scheduler.addPostFrameCallback((_) => process());
458+
}
459+
446460
@override
447461
int get hashCode => Object.hash(id, key);
448462

0 commit comments

Comments
 (0)