Bladeren bron

fix: use context menu on desktop

Prateek Sunal 1 jaar geleden
bovenliggende
commit
f8fbedfe10
3 gewijzigde bestanden met toevoegingen van 128 en 194 verwijderingen
  1. 111 194
      auth/lib/ui/code_widget.dart
  2. 16 0
      auth/pubspec.lock
  3. 1 0
      auth/pubspec.yaml

+ 111 - 194
auth/lib/ui/code_widget.dart

@@ -18,8 +18,8 @@ import 'package:ente_auth/utils/dialog_util.dart';
 import 'package:ente_auth/utils/platform_util.dart';
 import 'package:ente_auth/utils/toast_util.dart';
 import 'package:ente_auth/utils/totp_util.dart';
-import 'package:flutter/gestures.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter_context_menu/flutter_context_menu.dart';
 import 'package:flutter_slidable/flutter_slidable.dart';
 import 'package:logging/logging.dart';
 import 'package:move_to_background/move_to_background.dart';
@@ -87,147 +87,46 @@ class _CodeWidgetState extends State<CodeWidget> {
     final l10n = context.l10n;
     return Container(
       margin: const EdgeInsets.only(left: 16, right: 16, bottom: 8, top: 8),
-      child: Slidable(
-        enabled: PlatformUtil.isMobile(),
-        key: ValueKey(widget.code.hashCode),
-        endActionPane: ActionPane(
-          extentRatio: 0.60,
-          motion: const ScrollMotion(),
-          children: [
-            const SizedBox(
-              width: 4,
-            ),
-            SlidableAction(
-              onPressed: _onShowQrPressed,
-              backgroundColor: Colors.grey.withOpacity(0.1),
-              borderRadius: const BorderRadius.all(Radius.circular(12.0)),
-              foregroundColor:
-                  Theme.of(context).colorScheme.inverseBackgroundColor,
-              icon: Icons.qr_code_2_outlined,
-              label: "QR",
-              padding: const EdgeInsets.only(left: 4, right: 0),
-              spacing: 8,
-            ),
-            const SizedBox(
-              width: 4,
-            ),
-            SlidableAction(
-              onPressed: _onEditPressed,
-              backgroundColor: Colors.grey.withOpacity(0.1),
-              borderRadius: const BorderRadius.all(Radius.circular(12.0)),
-              foregroundColor:
-                  Theme.of(context).colorScheme.inverseBackgroundColor,
-              icon: Icons.edit_outlined,
-              label: l10n.edit,
-              padding: const EdgeInsets.only(left: 4, right: 0),
-              spacing: 8,
-            ),
-            const SizedBox(
-              width: 4,
-            ),
-            SlidableAction(
-              onPressed: _onDeletePressed,
-              backgroundColor: Colors.grey.withOpacity(0.1),
-              borderRadius: const BorderRadius.all(Radius.circular(12.0)),
-              foregroundColor: const Color(0xFFFE4A49),
-              icon: Icons.delete,
-              label: l10n.delete,
-              padding: const EdgeInsets.only(left: 0, right: 0),
-              spacing: 8,
-            ),
-          ],
-        ),
-        child: Builder(
-          builder: (context) => RawGestureDetector(
-            gestures: {
-              PanGestureRecognizer:
-                  GestureRecognizerFactoryWithHandlers<PanGestureRecognizer>(
-                () => PanGestureRecognizer(
-                  debugOwner: this,
-                  // This recognizer accepts any button press made with a secondary button.
-                  allowedButtonsFilter: (int buttons) =>
-                      buttons & kSecondaryButton != 0,
-                ),
-                (PanGestureRecognizer instance) {
-                  instance
-                    ..dragStartBehavior = DragStartBehavior.down
-                    ..onEnd = (DragEndDetails details) {
-                      Slidable.of(context)?.openEndActionPane();
-                    };
-                },
-              ),
-            },
-            child: ClipRRect(
-              borderRadius: BorderRadius.circular(8),
-              child: Container(
-                color: Theme.of(context).colorScheme.codeCardBackgroundColor,
-                child: Material(
-                  color: Colors.transparent,
-                  child: InkWell(
-                    customBorder: RoundedRectangleBorder(
-                      borderRadius: BorderRadius.circular(10),
-                    ),
-                    onTap: () {
-                      _copyCurrentOTPToClipboard();
-                    },
-                    onDoubleTap: isMaskingEnabled
-                        ? () {
-                            setState(
-                              () {
-                                _hideCode = !_hideCode;
-                              },
-                            );
-                          }
-                        : null,
-                    onLongPress: () {
-                      _copyCurrentOTPToClipboard();
-                    },
-                    child: _getCardContents(l10n),
+      child: Builder(
+        builder: (context) {
+          if (PlatformUtil.isDesktop()) {
+            return ContextMenuRegion(
+              contextMenu: ContextMenu(
+                entries: <ContextMenuEntry>[
+                  MenuItem(
+                    label: 'QR',
+                    icon: Icons.qr_code,
+                    onSelected: () => _onShowQrPressed(null),
                   ),
-                ),
+                  MenuItem(
+                    label: 'Edit',
+                    icon: Icons.edit,
+                    onSelected: () => _onEditPressed(null),
+                  ),
+                  const MenuDivider(),
+                  MenuItem(
+                    label: 'Delete',
+                    value: "Delete",
+                    icon: Icons.delete,
+                    onSelected: () => _onDeletePressed(null),
+                  ),
+                ],
+                padding: const EdgeInsets.all(8.0),
               ),
-            ),
-          ),
-        ),
-      ),
-    );
-  }
+              child: _clippedCard(l10n),
+            );
+          }
 
-  Widget _getCardContents(AppLocalizations l10n) {
-    return SizedBox(
-      child: Column(
-        crossAxisAlignment: CrossAxisAlignment.start,
-        mainAxisAlignment: MainAxisAlignment.center,
-        children: [
-          if (widget.code.type == Type.totp)
-            CodeTimerProgress(
-              period: widget.code.period,
-            ),
-          const SizedBox(
-            height: 16,
-          ),
-          Row(
-            children: [
-              _shouldShowLargeIcon ? _getIcon() : const SizedBox.shrink(),
-              Expanded(
-                child: Column(
-                  children: [
-                    _getTopRow(),
-                    const SizedBox(height: 4),
-                    _getBottomRow(l10n),
-                  ],
-                ),
-              ),
-            ],
-          ),
-          const SizedBox(
-            height: 20,
-          ),
-          if (PlatformUtil.isDesktop())
-            Row(
-              mainAxisAlignment: MainAxisAlignment.end,
+          return Slidable(
+            key: ValueKey(widget.code.hashCode),
+            endActionPane: ActionPane(
+              extentRatio: 0.60,
+              motion: const ScrollMotion(),
               children: [
-                SlideAction(
+                const SizedBox(
+                  width: 4,
+                ),
+                SlidableAction(
                   onPressed: _onShowQrPressed,
                   backgroundColor: Colors.grey.withOpacity(0.1),
                   borderRadius: const BorderRadius.all(Radius.circular(12.0)),
@@ -241,7 +140,7 @@ class _CodeWidgetState extends State<CodeWidget> {
                 const SizedBox(
                   width: 4,
                 ),
-                SlideAction(
+                SlidableAction(
                   onPressed: _onEditPressed,
                   backgroundColor: Colors.grey.withOpacity(0.1),
                   borderRadius: const BorderRadius.all(Radius.circular(12.0)),
@@ -255,7 +154,7 @@ class _CodeWidgetState extends State<CodeWidget> {
                 const SizedBox(
                   width: 4,
                 ),
-                SlideAction(
+                SlidableAction(
                   onPressed: _onDeletePressed,
                   backgroundColor: Colors.grey.withOpacity(0.1),
                   borderRadius: const BorderRadius.all(Radius.circular(12.0)),
@@ -267,6 +166,78 @@ class _CodeWidgetState extends State<CodeWidget> {
                 ),
               ],
             ),
+            child: Builder(
+              builder: (context) => _clippedCard(l10n),
+            ),
+          );
+        },
+      ),
+    );
+  }
+
+  Widget _clippedCard(AppLocalizations l10n) {
+    return ClipRRect(
+      borderRadius: BorderRadius.circular(8),
+      child: Container(
+        color: Theme.of(context).colorScheme.codeCardBackgroundColor,
+        child: Material(
+          color: Colors.transparent,
+          child: InkWell(
+            customBorder: RoundedRectangleBorder(
+              borderRadius: BorderRadius.circular(10),
+            ),
+            onTap: () {
+              _copyCurrentOTPToClipboard();
+            },
+            onDoubleTap: isMaskingEnabled
+                ? () {
+                    setState(
+                      () {
+                        _hideCode = !_hideCode;
+                      },
+                    );
+                  }
+                : null,
+            onLongPress: () {
+              _copyCurrentOTPToClipboard();
+            },
+            child: _getCardContents(l10n),
+          ),
+        ),
+      ),
+    );
+  }
+
+  Widget _getCardContents(AppLocalizations l10n) {
+    return SizedBox(
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        mainAxisAlignment: MainAxisAlignment.center,
+        children: [
+          if (widget.code.type == Type.totp)
+            CodeTimerProgress(
+              period: widget.code.period,
+            ),
+          const SizedBox(
+            height: 16,
+          ),
+          Row(
+            children: [
+              _shouldShowLargeIcon ? _getIcon() : const SizedBox.shrink(),
+              Expanded(
+                child: Column(
+                  children: [
+                    _getTopRow(),
+                    const SizedBox(height: 4),
+                    _getBottomRow(l10n),
+                  ],
+                ),
+              ),
+            ],
+          ),
+          const SizedBox(
+            height: 20,
+          ),
         ],
       ),
     );
@@ -529,57 +500,3 @@ class _CodeWidgetState extends State<CodeWidget> {
     return code;
   }
 }
-
-class SlideAction extends StatelessWidget {
-  const SlideAction({
-    super.key,
-    required this.onPressed,
-    required this.backgroundColor,
-    required this.borderRadius,
-    required this.foregroundColor,
-    required this.icon,
-    required this.label,
-    required this.padding,
-    required this.spacing,
-  });
-
-  final void Function(dynamic) onPressed;
-  final Color backgroundColor;
-  final BorderRadius borderRadius;
-  final Color foregroundColor;
-  final IconData icon;
-  final String label;
-  final EdgeInsets padding;
-  final double spacing;
-
-  @override
-  Widget build(BuildContext context) {
-    return InkWell(
-      onTap: () => onPressed(0),
-      child: Container(
-        color: backgroundColor,
-        height: 52,
-        width: 52,
-        child: Column(
-          mainAxisAlignment: MainAxisAlignment.center,
-          children: [
-            Icon(
-              icon,
-              size: 16,
-              color: foregroundColor,
-            ),
-            const SizedBox(
-              height: 4,
-            ),
-            Text(
-              label,
-              style: Theme.of(context).textTheme.bodySmall?.copyWith(
-                    color: foregroundColor,
-                  ),
-            ),
-          ],
-        ),
-      ),
-    );
-  }
-}

+ 16 - 0
auth/pubspec.lock

@@ -347,6 +347,14 @@ packages:
       url: "https://github.com/ente-io/ente_crypto_dart.git"
     source: git
     version: "1.0.0"
+  equatable:
+    dependency: transitive
+    description:
+      name: equatable
+      sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.0.5"
   event_bus:
     dependency: "direct main"
     description:
@@ -440,6 +448,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "8.1.5"
+  flutter_context_menu:
+    dependency: "direct main"
+    description:
+      name: flutter_context_menu
+      sha256: "9f220a8fa0290c68e38000d6d62a0dc4555d490c15a5bd856a6e6d255d81b8dc"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.1.3"
   flutter_displaymode:
     dependency: "direct main"
     description:

+ 1 - 0
auth/pubspec.yaml

@@ -41,6 +41,7 @@ dependencies:
   flutter:
     sdk: flutter
   flutter_bloc: ^8.0.1
+  flutter_context_menu: ^0.1.3
   flutter_displaymode: ^0.6.0
   flutter_email_sender: ^6.0.2
   flutter_inappwebview: ^6.0.0