letsar / flutter_slidable

A Flutter implementation of slidable list item with directional slide actions.
MIT License
2.73k stars 591 forks source link

controller open to manage the state. #442

Closed alex-melnyk closed 8 months ago

alex-melnyk commented 1 year ago

This PR adds the ability to use the controller for the programmatically state management.

alex-melnyk commented 8 months ago

@letsar please merge the PR and roll out the new version, this will help me use your plugin from https://pub.dev instead of the git forked version.

letsar commented 8 months ago

Hi, thank you for the PR and sorry for the delay. I'll do this today.

letsar commented 8 months ago

We can already get the SlidableController from the callback since we have the BuildContext, by using Slidable.of(context) :

SlidableAction(
  flex: 2,
  onPressed: (context) {
    Slidable.of(context)?.openEndActionPane();
  },
  backgroundColor: Color(0xFF7BC043),
  foregroundColor: Colors.white,
  icon: Icons.archive,
  label: 'Archive',
),

Is there other use-cases where it would be useful to pass a controller to the Slidable?

alex-melnyk commented 8 months ago

We can already get the SlidableController from the callback since we have the BuildContext, by using Slidable.of(context) :

SlidableAction(
  flex: 2,
  onPressed: (context) {
    Slidable.of(context)?.openEndActionPane();
  },
  backgroundColor: Color(0xFF7BC043),
  foregroundColor: Colors.white,
  icon: Icons.archive,
  label: 'Archive',
),

Is there other use-cases where it would be useful to pass a controller to the Slidable?

You are right, but this adds complexity to managing this controller from the parent widgets. BTW I did find out how to get a controller in another way:

final _slidableKey = GlobalKey();
// some code...
return GestureDetector(
          onSecondaryTap: widget.swipeable && !widget.selectable
              ? () => _slidableController.openEndActionPane()
              : null,
          onLongPress: () => _slidableController.openEndActionPane(),
          child: Slidable(
            key: _slidableKey,
            enabled: widget.swipeable && !widget.selectable,
            endActionPane: ActionPane(
              extentRatio: extentRatio,
              motion: const DrawerMotion(),
              children: [
                if (widget.conversation.contactType.isUnknown)
                  ChatListSlidableAction(
                    label: FlutterI18n.translate(context, 'cta.delete'),
                    backgroundColor: theme.colorScheme.error,
                    onPressed: widget.onDeletePressed,
                    icon: QliqIcons.delete,
                  )
                else ...[
                  ChatListSlidableAction(
                    onPressed: widget.onMutePressed,
                    backgroundColor: AppColors.darkGrey,
                    icon: widget.conversation.isMuted
                        ? QliqIcons.muteConversation
                        : QliqIcons.muteConversation,
                    label: widget.conversation.isMuted
                        ? FlutterI18n.translate(context, 'cta.unmute')
                        : FlutterI18n.translate(context, 'cta.mute'),
                  ),
                  ChatListSlidableAction(
                    onPressed: widget.onStarPressed,
                    backgroundColor: theme.primaryColor,
                    icon: widget.conversation.isStarred
                        ? Icons.star
                        : Icons.star_border,
                    label: widget.conversation.isStarred
                        ? FlutterI18n.translate(context, 'cta.unstar')
                        : FlutterI18n.translate(context, 'cta.star'),
                  ),
                ],
                ChatListSlidableAction(
                  onPressed: widget.onArchivePressed,
                  backgroundColor: AppColors.darkGrey,
                  icon: QliqIcons.archiveConversation,
                  label: FlutterI18n.translate(context, 'cta.archive'),
                ),
              ],
            ),
            child: conversationWidget,
          ),
        );
  /// Since the [Slidable] widget state is private, we need access
  /// to its controller for the ability to open the action pane.
  ///
  /// Returns [SlidableController] from [Slidable] widget state.
  SlidableController get _slidableController =>
      (_slidableKey.currentState as dynamic).controller; // SO HERE is the not-so-good way to get controller, but...

So it will be very helpful if the SlidableState is not private then the global key can be typed properly to access the members such as controller.

letsar commented 8 months ago

Ok I'll merge this then ;-)

letsar commented 8 months ago

Published in 3.1.0