[FEAT] Add Context menu to desktop right click (#1247)

## Description


![image](https://github.com/ente-io/ente/assets/41370460/099a90d9-3fb7-48cc-8177-79ea81c3edfc)
This commit is contained in:
Prateek Sunal 2024-03-29 16:24:19 +05:30 committed by GitHub
commit 45f9b47f24
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 130 additions and 99 deletions

View file

@ -17,8 +17,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';
@ -86,108 +86,122 @@ 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(
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) {
return 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,
child: Builder(
builder: (context) {
if (PlatformUtil.isDesktop()) {
return ContextMenuRegion(
contextMenu: ContextMenu(
entries: <ContextMenuEntry>[
MenuItem(
label: 'QR',
icon: Icons.qr_code_2_outlined,
onSelected: () => _onShowQrPressed(null),
),
(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),
),
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),
);
},
}
return Slidable(
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) => _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),
),
),
),
);

View file

@ -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:

View file

@ -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