show<T> static method

Future<T?> show<T>(
  1. BuildContext context, {
  2. required String title,
  3. required String? message,
  4. bool useHtmlMessage = false,
  5. required String cancelText,
  6. required String confirmText,
  7. T? initialValue,
  8. List<T> values = const [],
  9. required String itemLabelBuilder(
    1. T
    ),
  10. String barrierLabel = 'Dismiss',
})

Implementation

static Future<T?> show<T>(
  BuildContext context, {
  required String title,
  required String? message,
  bool useHtmlMessage = false,
  required String cancelText,
  required String confirmText,
  T? initialValue,
  List<T> values = const [],
  required String Function(T) itemLabelBuilder,
  String barrierLabel = 'Dismiss',
}) async {
  final ValueNotifier<T?> notifier = ValueNotifier(initialValue);
  final fluffyTheme = context.fluffyTheme;
  try {
    final result = await showGeneralDialog(
      context: context,
      barrierDismissible: true,
      barrierLabel: barrierLabel,
      barrierColor: FluffyColors.barrier,
      transitionDuration: FluffyDurations.dialogTransition,
      transitionBuilder: (context, anim1, anim2, child) {
        return FadeTransition(
          opacity: anim1,
          child: ScaleTransition(
            scale: Tween<double>(begin: 0.95, end: 1.0).animate(
              CurvedAnimation(parent: anim1, curve: Curves.easeOutCubic),
            ),
            child: child,
          ),
        );
      },
      pageBuilder: (BuildContext context, anim1, anim2) {
        final isDark = fluffyTheme.isDark;
        final onSurfaceColor = isDark
            ? fluffyTheme.colors.neutral1
            : fluffyTheme.colors.neutral7;

        void confirmSelected() {
          final value = notifier.value;
          if (value == null) return;
          context.navigator.pop(value);
        }

        void moveSelection(int delta) {
          if (values.isEmpty) return;

          final current = notifier.value;
          final currentIndex = current == null ? -1 : values.indexOf(current);
          final startIndex = switch (currentIndex) {
            >= 0 => currentIndex,
            _ when delta > 0 => -1,
            _ => 0,
          };
          notifier.value = values[(startIndex + delta) % values.length];
        }

        final targetPlatform = fluffyTheme.platform ?? defaultTargetPlatform;
        final isDesktop = switch (targetPlatform) {
          TargetPlatform.macOS ||
          TargetPlatform.windows ||
          TargetPlatform.linux => true,
          _ => false,
        };

        final dialog = DialogCard(
          title: Text(title),
          contentPadding: EdgeInsets.zero,
          content: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              if (message case String message when message.isNotEmpty) ...[
                Padding(
                  padding: EdgeInsets.only(bottom: Spacing.d16),
                  child: switch (useHtmlMessage) {
                    true => HtmlWidget(
                      message,
                      textStyle: TextStyle(
                        color: onSurfaceColor,
                      ),
                    ),
                    false => Text(
                      message,
                      style: TextStyle(
                        color: onSurfaceColor,
                      ),
                    ),
                  },
                ),
              ],
              ValueListenableBuilder(
                valueListenable: notifier,
                builder: (context, groupValue, child) {
                  return SingleChildScrollView(
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        for (final value in values)
                          RadioIconListTile<T>(
                            style: RadioIconListTileStyle.compact,
                            expanded: true,
                            value: value,
                            groupValue: groupValue,
                            onChanged: (value) {
                              notifier.value = value;
                            },
                            title: itemLabelBuilder(value),
                          ),
                      ],
                    ),
                  );
                },
              ),
            ],
          ),
          actions: [
            ValueListenableBuilder(
              valueListenable: notifier,
              builder: (context, groupValue, child) {
                return Row(
                  mainAxisAlignment: switch (isDesktop) {
                    true => MainAxisAlignment.end,
                    false => MainAxisAlignment.center,
                  },
                  children: switch (isDesktop) {
                    true => [
                      Button(
                        variant: ButtonVariant.ghost,
                        tooltip: cancelText,
                        label: cancelText,
                        mainAxisSize: MainAxisSize.min,
                        padding: EdgeInsets.symmetric(
                          horizontal: Spacing.d16,
                          vertical: Spacing.d8,
                        ),
                        onPressed: () {
                          context.navigator.pop();
                        },
                      ),
                      Spacing.h8,
                      Button(
                        enable: groupValue != null,
                        variant: ButtonVariant.primary,
                        tooltip: confirmText,
                        label: confirmText,
                        mainAxisSize: MainAxisSize.min,
                        padding: EdgeInsets.symmetric(
                          horizontal: Spacing.d16,
                          vertical: Spacing.d8,
                        ),
                        onPressed: () {
                          confirmSelected();
                        },
                      ),
                    ],
                    false => [
                      Expanded(
                        child: Button(
                          variant: ButtonVariant.ghost,
                          tooltip: cancelText,
                          label: cancelText,
                          titleExpand: ButtonTitleExpand.shrink,
                          onPressed: () {
                            context.navigator.pop();
                          },
                        ),
                      ),
                      Spacing.h8,
                      Expanded(
                        child: Button(
                          enable: groupValue != null,
                          variant: ButtonVariant.primary,
                          tooltip: confirmText,
                          label: confirmText,
                          titleExpand: ButtonTitleExpand.shrink,
                          onPressed: () {
                            confirmSelected();
                          },
                        ),
                      ),
                    ],
                  },
                );
              },
            ),
          ],
        );

        return FluffyTheme(
          data: fluffyTheme,
          child: CallbackShortcuts(
            bindings: {
              const SingleActivator(LogicalKeyboardKey.enter):
                  confirmSelected,
              const SingleActivator(LogicalKeyboardKey.numpadEnter):
                  confirmSelected,
              const SingleActivator(LogicalKeyboardKey.arrowUp): () {
                moveSelection(-1);
              },
              const SingleActivator(LogicalKeyboardKey.arrowDown): () {
                moveSelection(1);
              },
            },
            child: Focus(
              autofocus: true,
              child: dialog,
            ),
          ),
        );
      },
    );

    if (result is! T) {
      return null;
    }

    return result;
  } finally {
    notifier.dispose();
  }
}