Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions lib/new-ui/pages/receive_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -271,20 +271,19 @@ class _NewReceivePageState extends State<NewReceivePage> {
largeQrMode: _largeQrMode,
showAccountsButton: widget.addressListViewModel.hasAddressList,
showLabelButton: widget.addressListViewModel.hasAddressList && !hasLabel,
copyData: widget.addressListViewModel.hasPayjoin
? null
: ClipboardData(
text: widget.addressListViewModel.displayAmount.isEmpty
? widget.addressListViewModel.uri.address
: widget.addressListViewModel.uri.toString()),
onCopyButtonPressed: () {
if (widget.addressListViewModel.hasPayjoin) {
showModalBottomSheet(
isScrollControlled: true,
context: context,
builder: (context) =>
PayjoinCopyModal(uri: widget.addressListViewModel.uri));
} else {
Clipboard.setData(
ClipboardData(
text: widget.addressListViewModel.displayAmount.isEmpty
? widget.addressListViewModel.uri.address
: widget.addressListViewModel.uri.toString()),
);
}
},
onAmountButtonPressed: () {
Expand Down
1 change: 1 addition & 0 deletions lib/new-ui/widgets/copy_wrapper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class _CopyWrapperState extends State<CopyWrapper> {
void handleCopy() async {
if (widget.data == null) return;
ClipboardUtil.setSensitiveDataToClipboard(widget.data!, isSensitive: widget.isSensitive);
HapticFeedback.mediumImpact();
if (await shouldShowCopied()) {
setState(() => copied = true);
Future.delayed(widget.duration, () {
Expand Down
77 changes: 33 additions & 44 deletions lib/new-ui/widgets/receive_page/receive_bottom_buttons.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import 'dart:io';

import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/new-ui/widgets/copy_wrapper.dart';
import 'package:cake_wallet/new-ui/widgets/modern_button.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class ReceiveBottomButtons extends StatefulWidget {
final bool largeQrMode;
final ClipboardData? copyData;
final VoidCallback onCopyButtonPressed;
final VoidCallback onAmountButtonPressed;
final VoidCallback onLabelButtonPressed;
Expand All @@ -17,6 +17,7 @@ class ReceiveBottomButtons extends StatefulWidget {
const ReceiveBottomButtons({
super.key,
required this.largeQrMode,
required this.copyData,
required this.onCopyButtonPressed,
required this.onAccountsButtonPressed,
required this.onAmountButtonPressed,
Expand All @@ -30,18 +31,6 @@ class ReceiveBottomButtons extends StatefulWidget {
}

class _ReceiveBottomButtonsState extends State<ReceiveBottomButtons> {
bool copied = false;

void handleCopy() async {
widget.onCopyButtonPressed();
if (await shouldShowCopied()) {
setState(() => copied = true);
Future.delayed(const Duration(milliseconds: 1200), () {
if (mounted) setState(() => copied = false);
});
}
}

@override
Widget build(BuildContext context) {
final double targetOpacity = widget.largeQrMode ? 0 : 1;
Expand All @@ -63,17 +52,35 @@ class _ReceiveBottomButtonsState extends State<ReceiveBottomButtons> {
mainAxisAlignment: MainAxisAlignment.center,
spacing: 16,
children: [
AnimatedSwitcher(
duration: Duration(milliseconds: 200),
child: ModernButton.svg(
key: ValueKey(copied),
size: 60,
iconSize: 32,
svgPath: "assets/new-ui/copy.svg",
onPressed: handleCopy,
label: copied ? S.of(context).copied : S.of(context).copy,
iconColor: copied ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.surfaceContainer,
backgroundColor: copied ? Theme.of(context).colorScheme.surfaceContainerHighest : Theme.of(context).colorScheme.primary,
// In the payjoin case (copyData == null), CopyWrapper's internal
// GestureDetector still claims the gesture arena even though
// handleCopy() no-ops on null data. Ignoring pointers on the
// CopyWrapper lets the outer GestureDetector receive the tap and
// open the payjoin modal instead. When there is copy data,
// ignoring is false and onTap is null so CopyWrapper copies as
// usual with no competing recognizer.
GestureDetector(
onTap: widget.copyData == null ? widget.onCopyButtonPressed : null,
child: IgnorePointer(
ignoring: widget.copyData == null,
child: CopyWrapper(
data: widget.copyData,
builder: (context, copied) => AnimatedSwitcher(
duration: Duration(milliseconds: 200),
child: IgnorePointer(
child: ModernButton.svg(
key: ValueKey(copied),
size: 60,
iconSize: 32,
svgPath: "assets/new-ui/copy.svg",
onPressed: () {},
label: copied ? S.of(context).copied : S.of(context).copy,
iconColor: copied ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.surfaceContainer,
backgroundColor: copied ? Theme.of(context).colorScheme.surfaceContainerHighest : Theme.of(context).colorScheme.primary,
),
),
),
),
),
),
ModernButton.svg(
Expand Down Expand Up @@ -103,22 +110,4 @@ class _ReceiveBottomButtonsState extends State<ReceiveBottomButtons> {
),
);
}



// android 13 (sdk 33) added a built-in "text was copied to clipboard" ui element
// older android and iphone still needs an indicator though
Future<bool> shouldShowCopied() async {
if (!Platform.isAndroid) return true;

try {
final deviceInfo = DeviceInfoPlugin();
final androidInfo = await deviceInfo.androidInfo;
final sdk = androidInfo.version.sdkInt;

return sdk < 33;
} catch (_) {
return true;
}
}
}
Loading