Skip to content

Commit daf1b5f

Browse files
committed
fix: 🔨Fixed PR comments
1 parent 1aa080d commit daf1b5f

File tree

3 files changed

+111
-79
lines changed

3 files changed

+111
-79
lines changed

lib/src/showcase/showcase.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -559,8 +559,8 @@ class Showcase extends StatefulWidget {
559559
class _ShowcaseState extends State<Showcase> {
560560
ShowcaseController get _controller =>
561561
_showCaseWidgetState.getControllerForShowcase(
562-
widget.showcaseKey,
563-
_uniqueId,
562+
key: widget.showcaseKey,
563+
showcaseId: _uniqueId,
564564
);
565565

566566
late var _showCaseWidgetState = ShowCaseWidget.of(context);

lib/src/showcase/showcase_controller.dart

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -283,40 +283,33 @@ class ShowcaseController {
283283
///
284284
/// @return List of tooltip action widgets
285285
List<Widget> _getTooltipActions() {
286-
final actionData = (config.tooltipActions?.isNotEmpty ?? false)
286+
final doesHaveLocalActions = config.tooltipActions?.isNotEmpty ?? false;
287+
final actionData = doesHaveLocalActions
287288
? config.tooltipActions!
288289
: showCaseWidgetState.globalTooltipActions ?? [];
289-
290-
final actionWidgets = <Widget>[];
291290
final actionDataLength = actionData.length;
292-
for (var i = 0; i < actionDataLength; i++) {
293-
final action = actionData[i];
294-
295-
// Skip actions that should be hidden for this specific showcase key
296-
// when no local actions are defined (using global actions)
297-
if (action.hideActionWidgetForShowcase.contains(config.showcaseKey) &&
298-
(config.tooltipActions?.isEmpty ?? true)) {
299-
continue;
300-
}
301-
302-
actionWidgets.add(
303-
Padding(
304-
padding: EdgeInsetsDirectional.only(
305-
end: action == actionData.last
306-
? 0
307-
: _getTooltipActionConfig().actionGap,
308-
),
309-
child: TooltipActionButtonWidget(
310-
config: action,
311-
// We have to pass showcaseState from here because
312-
// [TooltipActionButtonWidget] is not direct child of showcaseWidget
313-
// so it won't be able to get the state by using it's context
314-
showCaseState: showCaseWidgetState,
291+
292+
return [
293+
for (var i = 0; i < actionDataLength; i++)
294+
if (doesHaveLocalActions ||
295+
!actionData[i]
296+
.hideActionWidgetForShowcase
297+
.contains(config.showcaseKey))
298+
Padding(
299+
padding: EdgeInsetsDirectional.only(
300+
end: actionData[i] == actionData.last
301+
? 0
302+
: _getTooltipActionConfig().actionGap,
303+
),
304+
child: TooltipActionButtonWidget(
305+
config: actionData[i],
306+
// We have to pass showcaseState from here because
307+
// [TooltipActionButtonWidget] is not direct child of showcaseWidget
308+
// so it won't be able to get the state by using it's context
309+
showCaseState: showCaseWidgetState,
310+
),
315311
),
316-
),
317-
);
318-
}
319-
return actionWidgets;
312+
];
320313
}
321314

322315
/// Gets the tooltip action configuration

lib/src/showcase_widget.dart

Lines changed: 86 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ class ShowCaseWidget extends StatefulWidget {
170170
this.hideFloatingActionWidgetForShowcase = const [],
171171
});
172172

173+
static GlobalKey? activeTargetWidget(BuildContext context) => context
174+
.findAncestorStateOfType<ShowCaseWidgetState>()
175+
?.getCurrentActiveShowcaseKey;
176+
173177
static ShowCaseWidgetState of(BuildContext context) {
174178
final state = context.findAncestorStateOfType<ShowCaseWidgetState>();
175179
if (state != null) {
@@ -270,7 +274,7 @@ class ShowCaseWidgetState extends State<ShowCaseWidget> {
270274
super.initState();
271275
globalTooltipActions = widget.globalTooltipActions;
272276
globalTooltipActionConfig = widget.globalTooltipActionConfig;
273-
initRootWidget();
277+
_initRootWidget();
274278
}
275279

276280
@override
@@ -369,7 +373,7 @@ class ShowCaseWidgetState extends State<ShowCaseWidget> {
369373
next();
370374
}
371375

372-
void initRootWidget() {
376+
void _initRootWidget() {
373377
WidgetsBinding.instance.addPostFrameCallback((_) {
374378
if (!mounted) return;
375379
final rootWidget = context.findRootAncestorStateOfType<State<Overlay>>();
@@ -383,34 +387,50 @@ class ShowCaseWidgetState extends State<ShowCaseWidget> {
383387
/// Starts Showcase view from the beginning of specified list of widget ids.
384388
/// If this function is used when showcase has been disabled then it will
385389
/// throw an exception.
386-
void startShowCase(List<GlobalKey> widgetIds) {
390+
///
391+
/// [delay] is optional and it will be used to delay the start of showcase
392+
/// which is useful when animation may take some time to complete.
393+
///
394+
/// Refer this issue https://github.com/SimformSolutionsPvtLtd/flutter_showcaseview/issues/378
395+
void startShowCase(
396+
List<GlobalKey> widgetIds, {
397+
Duration delay = Duration.zero,
398+
}) {
387399
if (!enableShowcase) {
388400
throw Exception(
389401
"You are trying to start Showcase while it has been disabled with "
390402
"`enableShowcase` parameter to false from ShowCaseWidget",
391403
);
392404
}
393-
if (!mounted) return;
394-
ids = widgetIds;
395-
activeWidgetId = 0;
396-
_onStart();
397-
updateOverlay?.call(isShowcaseRunning);
405+
Future.delayed(
406+
delay,
407+
() {
408+
if (!mounted) return;
409+
ids = widgetIds;
410+
activeWidgetId = 0;
411+
_onStart();
412+
updateOverlay?.call(isShowcaseRunning);
413+
},
414+
);
398415
}
399416

400417
/// Completes showcase of given key and starts next one
401418
/// otherwise will finish the entire showcase view
402-
Future<void> completed(GlobalKey? key) async {
419+
void completed(GlobalKey? key) {
403420
if (ids != null && ids![activeWidgetId!] == key && mounted) {
404-
await _onComplete();
405-
if (!mounted) return;
406-
activeWidgetId = activeWidgetId! + 1;
407-
_onStart();
421+
_onComplete().then(
422+
(_) {
423+
if (!mounted) return;
424+
activeWidgetId = activeWidgetId! + 1;
425+
_onStart();
408426

409-
if (activeWidgetId! >= ids!.length) {
410-
_cleanupAfterSteps();
411-
widget.onFinish?.call();
412-
}
413-
updateOverlay?.call(isShowcaseRunning);
427+
if (activeWidgetId! >= ids!.length) {
428+
_cleanupAfterSteps();
429+
widget.onFinish?.call();
430+
}
431+
updateOverlay?.call(isShowcaseRunning);
432+
},
433+
);
414434
}
415435
}
416436

@@ -446,18 +466,21 @@ class ShowCaseWidgetState extends State<ShowCaseWidget> {
446466

447467
/// Completes current active showcase and starts previous one
448468
/// otherwise will finish the entire showcase view
449-
Future<void> previous() async {
469+
void previous() {
450470
if (ids != null && ((activeWidgetId ?? 0) - 1) >= 0 && mounted) {
451-
await _onComplete();
452-
if (!mounted) return;
471+
_onComplete().then(
472+
(_) {
473+
if (!mounted) return;
453474

454-
activeWidgetId = activeWidgetId! - 1;
455-
_onStart();
456-
if (activeWidgetId! >= ids!.length) {
457-
_cleanupAfterSteps();
458-
widget.onFinish?.call();
459-
}
460-
updateOverlay?.call(isShowcaseRunning);
475+
activeWidgetId = activeWidgetId! - 1;
476+
_onStart();
477+
if (activeWidgetId! >= ids!.length) {
478+
_cleanupAfterSteps();
479+
widget.onFinish?.call();
480+
}
481+
updateOverlay?.call(isShowcaseRunning);
482+
},
483+
);
461484
}
462485
}
463486

@@ -502,24 +525,18 @@ class ShowCaseWidgetState extends State<ShowCaseWidget> {
502525
}
503526

504527
Future<void> _onComplete() async {
505-
final futures = <Future>[];
506528
final currentControllers = _getCurrentActiveControllers;
507529
final controllerLength = currentControllers.length;
508530

509-
for (var i = 0; i < controllerLength; i++) {
510-
final controller = currentControllers[i];
511-
if ((controller.config.disableScaleAnimation ??
512-
widget.disableScaleAnimation) ||
513-
controller.reverseAnimationCallback == null) {
514-
continue;
515-
}
516-
futures.add(controller.reverseAnimationCallback!.call());
517-
}
518-
await Future.wait(futures);
531+
await Future.wait([
532+
for (var i = 0; i < controllerLength; i++)
533+
if (!(currentControllers[i].config.disableScaleAnimation ??
534+
widget.disableScaleAnimation) &&
535+
currentControllers[i].reverseAnimationCallback != null)
536+
currentControllers[i].reverseAnimationCallback!.call(),
537+
]);
519538
widget.onComplete?.call(activeWidgetId, ids![activeWidgetId!]);
520-
if (widget.autoPlay) {
521-
_cancelTimer();
522-
}
539+
if (widget.autoPlay) _cancelTimer();
523540
}
524541

525542
void _cancelTimer() {
@@ -550,6 +567,13 @@ class ShowCaseWidgetState extends State<ShowCaseWidget> {
550567
required ShowcaseController controller,
551568
required int showcaseId,
552569
}) {
570+
assert(
571+
() {
572+
final stackTrace = StackTrace.current.toString();
573+
return stackTrace.contains('_ShowcaseState');
574+
}(),
575+
'This method should only be called from Showcase class',
576+
);
553577
_showcaseControllers
554578
.putIfAbsent(
555579
key,
@@ -566,16 +590,31 @@ class ShowCaseWidgetState extends State<ShowCaseWidget> {
566590
required GlobalKey key,
567591
required int uniqueShowcaseKey,
568592
}) {
593+
assert(
594+
() {
595+
final stackTrace = StackTrace.current.toString();
596+
return stackTrace.contains('_ShowcaseState');
597+
}(),
598+
'This method should only be called from Showcase class',
599+
);
569600
_showcaseControllers[key]?.remove(uniqueShowcaseKey);
570601
}
571602

572-
ShowcaseController getControllerForShowcase(
573-
GlobalKey key,
574-
int showcaseId,
575-
) {
603+
ShowcaseController getControllerForShowcase({
604+
required GlobalKey key,
605+
required int showcaseId,
606+
}) {
607+
assert(
608+
() {
609+
final stackTrace = StackTrace.current.toString();
610+
return stackTrace.contains('_ShowcaseState');
611+
}(),
612+
'This method should only be called from Showcase class',
613+
);
576614
assert(
577615
_showcaseControllers[key]?[showcaseId] != null,
578-
'Please register showcase controller first',
616+
'Please register showcase controller first by calling '
617+
'registerShowcaseController',
579618
);
580619
return _showcaseControllers[key]![showcaseId]!;
581620
}

0 commit comments

Comments
 (0)