Skip to content

Add "Copy to clipboard" button to message action sheet #213

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Aug 1, 2023

Conversation

chrisbobbe
Copy link
Collaborator

This leaves some TODOs in the tests, for testing code that calls into a Flutter plugin. Greg is working on a good way to do that; see #204 (comment).

Empirically, the relevant calls here return Futures that never resolve, which will be fine until we want to stub out the native-code functionality.

Fixes: #132

@chrisbobbe chrisbobbe added the a-msglist The message-list screen, except what's label:a-content label Jul 5, 2023
@chrisbobbe chrisbobbe requested a review from gnprice July 5, 2023 23:54
Copy link
Member

@gnprice gnprice left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Small comments below. Let's also try adding tests of the copyWithPopup calls, atop those first few commits of #204 (which I think we're likely to merge soon.)

Comment on lines 220 to 222
if (rawContent == null) {
return;
}

if (!messageListContext.mounted) return;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: the non-parallelism looks a bit odd:

Suggested change
if (rawContent == null) {
return;
}
if (!messageListContext.mounted) return;
if (rawContent == null) return;
if (!messageListContext.mounted) return;


@override get icon => Icons.copy;

@override get label => 'Copy to clipboard';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a bit clearer about what it's going to do, I think — there are several things one might imagine being copied.

Perhaps "Copy message text"?

@chrisbobbe chrisbobbe force-pushed the pr-copy-to-clipboard branch from d28aaa8 to a383afe Compare July 19, 2023 19:07
@chrisbobbe
Copy link
Collaborator Author

Thanks for the review! Revision pushed, with:

  • tests of copyWithPopup
  • clipboard checks in the message-action-sheet tests for "Copy message text"

@chrisbobbe chrisbobbe force-pushed the pr-copy-to-clipboard branch from a383afe to 020fb80 Compare July 19, 2023 19:09
Copy link
Member

@gnprice gnprice left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool! Glad to have tests for this. Various small comments below.

/// Provides device and operating system information,
/// via package:device_info_plus.
///
/// This wraps [DeviceInfoPlugin.deviceInfo].
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// This wraps [DeviceInfoPlugin.deviceInfo].
/// This wraps [device_info_plus.DeviceInfoPlugin.deviceInfo].

Comment on lines 91 to 93
/// The user-visible SDK version of the framework.
///
/// Possible values are defined in: https://developer.android.com/reference/android/os/Build.VERSION_CODES.html
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// The user-visible SDK version of the framework.
///
/// Possible values are defined in: https://developer.android.com/reference/android/os/Build.VERSION_CODES.html
```suggestion
/// The Android SDK version.
///
/// Possible values are defined in: https://developer.android.com/reference/android/os/Build.VERSION_CODES.html

I wouldn't call it "user-visible" — one never sees this number as an Android user, only as an Android developer.

(I guess the Android docs on the related field https://developer.android.com/reference/android/os/Build.VERSION#SDK calls it that. Looks like that text dates at least to the dawn of Android's public Git history in 2008. It's possible it made sense then, but it hasn't in a long time.)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yeah, this was copied from the plugin. Will remove that.

Comment on lines 101 to 102
/// The current operating system version.
/// https://developer.apple.com/documentation/uikit/uidevice/1620043-systemversion
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// The current operating system version.
/// https://developer.apple.com/documentation/uikit/uidevice/1620043-systemversion
/// The current operating system version.
///
/// See: https://developer.apple.com/documentation/uikit/uidevice/1620043-systemversion


@override
Future<BaseDeviceInfo> deviceInfo() async {
return switch (await device_info_plus.DeviceInfoPlugin().deviceInfo) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't super matter in this instance, but in general I like making awaits conspicuous — they're a key part of the control flow, after all — by putting them at the head of either a whole statement or an initializer:

Suggested change
return switch (await device_info_plus.DeviceInfoPlugin().deviceInfo) {
final deviceInfo = await device_info_plus.DeviceInfoPlugin().deviceInfo;
return switch (deviceInfo) {

}

final _defaultDeviceInfoResult = IosDeviceInfo(systemVersion: '16.0');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make this a static on the class — that way it can be grouped right next to the rest of the device-info stuff, even while this binding continues to grow more features.

Also let's make it an Android version, because that's what Flutter elsewhere defaults to in tests:
https://api.flutter.dev/flutter/foundation/defaultTargetPlatform.html

Comment on lines 139 to 140
/// This returns a list of the arguments to all calls made
/// to `ZulipBinding.instance.deviceInfo()` since the last call to
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  /// This returns a list of the arguments to all calls made

List<()>

😆

I think I'm actually inclined to leave out this "take" method, and the log it consumes, entirely, though. Because the underlying method doesn't (or anyway isn't meant to) have any side effects, I don't think it's ever going to really be a caller's or a test's business whether the implementation of some feature calls this method, or in particular when or how many times it does so. What is a caller's or test's business is whether the implementation successfully does the appropriate things on different platforms; and the test tests that by having several variants of itself that manipulate deviceInfoResult differently.

If we later wrap some method that does have side effects (so a test inspecting a call log is appropriate) but takes no arguments, though, I'd be fine with this type for the corresponding "take" method. I'm not sure the formal parallelism with takeLaunchUrlCalls (and future methods like it) is ultimately helpful, but maybe it will be.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haha, makes sense.


dynamic clipboardData;

Future<Object?> handleMethodCall(MethodCall methodCall) async {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is based on some piece of test code in the Flutter tree, right? Worth a brief comment pointing to there — the code is pretty gnarly-looking with all those dynamics, and that's helpful context for understanding it.

case 'Clipboard.setData':
clipboardData = methodCall.arguments;
default:
if (methodCall.method.startsWith('Clipboard')) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (methodCall.method.startsWith('Clipboard')) {
if (methodCall.method.startsWith('Clipboard.')) {

unless you intend to match things like "ClipboardPlus.getFancyData" too.

Comment on lines 12 to 15
void main() {
setUp(() async {
TestZulipBinding.ensureInitialized();
TestWidgetsFlutterBinding.ensureInitialized();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
void main() {
setUp(() async {
TestZulipBinding.ensureInitialized();
TestWidgetsFlutterBinding.ensureInitialized();
void main() {
TestZulipBinding.ensureInitialized();
TestWidgetsFlutterBinding.ensureInitialized();
setUp(() async {

That's the usual idiom for these, because they only have effect once.

Comment on lines +16 to +19
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(
SystemChannels.platform,
MockClipboard().handleMethodCall,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is good to do in the per-test setup, though, because it resets the clipboard's data.

@chrisbobbe chrisbobbe force-pushed the pr-copy-to-clipboard branch from 020fb80 to fe719c2 Compare July 20, 2023 19:45
@chrisbobbe
Copy link
Collaborator Author

Thanks for the review! Revision pushed.

@gnprice
Copy link
Member

gnprice commented Aug 1, 2023

Thanks for the revision! Sorry for the delayed review. All looks good; merging.

@gnprice gnprice force-pushed the pr-copy-to-clipboard branch from fe719c2 to 9a06553 Compare August 1, 2023 00:18
@gnprice gnprice merged commit 9a06553 into zulip:main Aug 1, 2023
@chrisbobbe chrisbobbe deleted the pr-copy-to-clipboard branch August 1, 2023 00:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a-msglist The message-list screen, except what's label:a-content
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Copy message text to clipboard
2 participants