plus_plugins icon indicating copy to clipboard operation
plus_plugins copied to clipboard

[Bug]: share_plus Share.shareXFiles() is not working on web

Open ekuleshov opened this issue 1 year ago • 18 comments

Platform

Chrome web browser on MacOS

Plugin

share_plus

Version

latest from the main

Flutter SDK

3.7.8

Steps to reproduce

  1. Checkout latetst sources from main
  2. Open project in Android Studio
  3. Select Chrome (web) as target and launch share_plus/example app
  4. Click on the "Share XFile from Assets" button
  5. The following exception is thrown but the plugin readme says "it falls back to downloading the shared files" when Web Share API is not available.

Code Sample

The `share_plus/example` app from https://github.com/fluttercommunity/plus_plugins/tree/main/packages/share_plus/share_plus

Logs

Debug service listening on ws://127.0.0.1:50601/BFGEsW3RKXM=/ws
TypeError: this.share is not a function
dart-sdk/lib/html/dart2js/html_dart2js.dart 22933:49                              share]
packages/share_plus/src/share_plus_web.dart 105:22                                shareXFiles
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 45:50                <fn>
dart-sdk/lib/async/zone.dart 1660:54                                              runUnary
dart-sdk/lib/async/future_impl.dart 147:18                                        handleValue
dart-sdk/lib/async/future_impl.dart 767:44                                        handleValueCallback
dart-sdk/lib/async/future_impl.dart 796:13                                        _propagateToListeners
dart-sdk/lib/async/future_impl.dart 558:7                                         [_complete]
dart-sdk/lib/async/stream_pipe.dart 61:11                                         _cancelAndValue
dart-sdk/lib/async/stream.dart 1587:7                                             <fn>
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 367:37  _checkAndCall
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 372:39  dcall
dart-sdk/lib/html/dart2js/html_dart2js.dart 37367:58                              <fn>

Flutter Doctor

.../flutter doctor --verbose
[✓] Flutter (Channel stable, 3.7.8, on macOS 12.6.1 21G217 darwin-arm64, locale en-CA)
    • Flutter version 3.7.8 on channel stable at .../flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 90c64ed42b (5 days ago), 2023-03-21 11:27:08 -0500
    • Engine revision 9aa7816315
    • Dart version 2.19.5
    • DevTools version 2.20.1

[✓] Xcode - develop for iOS and macOS (Xcode 14.2)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14C18
    • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2022.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301)

Checklist before submitting a bug

  • [X] I Google'd a solution and I couldn't find it
  • [X] I searched on StackOverflow for a solution and I couldn't find it
  • [X] I read the README.md file of the plugin
  • [X] I'm using the latest version of the plugin
  • [X] All dependencies are up to date with flutter pub upgrade
  • [X] I did a flutter clean
  • [X] I tried running the example project

ekuleshov avatar Mar 26 '23 20:03 ekuleshov

I got the same error message when I create a XFile with image data, and then share it by 'shareXFiles' function

cyrilhl avatar Apr 01 '23 19:04 cyrilhl

I got the same error message when I create a XFile with image data, and then share it by 'shareXFiles' function

I got the same error message on Chrome 113 on iOS 16.4.1 (iPhone):

TypeError: this.share is not a function. (In 'this.share(data_dict)', 'this.share' is undefined)

TechAurelian2 avatar May 03 '23 07:05 TechAurelian2

Same here! I am using XFile.fromData(/* some image byte Uint8List */) if that helps finding the cause.

xonaman avatar Jun 10 '23 15:06 xonaman

Same issue here!

Sample code that uses PictureRecorder to generate a png from canvas

ui.PictureRecorder recorder = ui.PictureRecorder();
Canvas canvas = Canvas(recorder);

Size exportSize = Size.square(size);
paint!.painter!.paint(canvas, exportSize);
ui.Image renderedImage = await recorder
    .endRecording()
    .toImage(exportSize.width.floor(), exportSize.height.floor());
ByteData? pngBytes =
    await renderedImage.toByteData(format: ui.ImageByteFormat.png);

Share.shareXFiles(
  [
    XFile.fromData(
      pngBytes!.buffer
          .asUint8List(pngBytes.offsetInBytes, pngBytes.lengthInBytes),
      name: 'qr-code.png',
      mimeType: 'image/png',
    )
  ],
);

followed the example https://github.com/fluttercommunity/plus_plugins/blob/b6888edcf224b9d5a1dc15716881b6e1a7114ef5/packages/share_plus/share_plus/example/lib/main.dart#L243-L252

still getting

Uncaught (in promise) TypeError: this.share is not a function
    at [dartx.share] (html_dart2js.dart:22933:49)
    at share_plus_web.SharePlusWebPlugin.new.shareXFiles (share_plus_web.dart:105:22)
    at shareXFiles.next (<anonymous>)
    at async_patch.dart:45:50
    at _RootZone.runUnary (zone.dart:1660:54)
    at _FutureListener.thenAwait.handleValue (future_impl.dart:147:18)
    at handleValueCallback (future_impl.dart:767:44)
    at _Future._propagateToListeners (future_impl.dart:796:13)
    at [_complete] (future_impl.dart:558:7)
    at Object._cancelAndValue (stream_pipe.dart:61:11)
    at stream.dart:1587:7
    at Object._checkAndCall (operations.dart:367:37)
    at Object.dcall (operations.dart:372:39)

c-seeger avatar Jul 11 '23 08:07 c-seeger

Tried on Safari and Edge also, none worked.

pixnbit avatar Aug 22 '23 04:08 pixnbit

Seconding this is an issue for me.

My code sample:

var shareButton = TextButton( style: TextButton.styleFrom( backgroundColor: FauraColors().babiOrange(), padding: const EdgeInsets.all(5.0), ), onPressed: () async { Share.shareXFiles( [ await XFile.fromData(await pdfLogic.returnActionItemPDF( widget.actionItems, PdfPageFormat.letter)), ], subject: "Home Wildfire Mitigation Plan", ); }, child: Text( "Share PDF.", style: FauraTheme().fauraTextTheme().bodySmall, ));

Any plans for fixing or workarounds?

codingiswhyicry avatar Oct 08 '23 22:10 codingiswhyicry

I have the same problem, has anyone solved it?

mengqutaoyuan avatar Dec 07 '23 07:12 mengqutaoyuan

I think the issue is that web browsers do not have a native share menu like mobile devices have. However, you can download single files. Here is an example:

await XFile.fromData(
  Uint8List.fromList(/* some mp3 data */),
  mimeType: 'audio/mpeg',
).saveTo('my-file-name.mp3');

xonaman avatar Dec 11 '23 11:12 xonaman

Does anyone knows how to fix it ?

  • Tried on Desktop browser -> got error, NoSuchMethodError: tried to call a non-function, such as null: 'this.share'.
  • Tried on Mobile browser (Safari) -> got this white UI pop up image

dongnqdev avatar Mar 08 '24 09:03 dongnqdev

@dongnqdev would you mind sharing your implementation?

xonaman avatar Mar 08 '24 09:03 xonaman

@xonaman Yes, This is my code. If you wonder where is the bytes came from. It was data converted from Widget to Image. And it works well on android and iOS.

Btw, I have a question doesn't relates to this topic. But does ShareResult.raw provides us any information about the option that user have chosen? For example, save to device or name of the selected application (twitter x,....).

Thanks

Future<void> saveAndShare(
      Uint8List bytes, WidgetRef ref, bool? isFirstShared) async {
    late final XFile file;
    if (kIsWeb) {
      file = XFile.fromData(bytes);
    } else {
      final directory = await getApplicationDocumentsDirectory();
      final image = File('${directory.path}/xlp.png');
      image.writeAsBytesSync(bytes);
      file = XFile(image.path);
    }

    final result = await Share.shareXFiles([file],
        subject: BStrings.current.welcomeToBlockx,
        text: BStrings.current.welcomeToBlockx);
  }

This is my doctor -v, and I'm using share_plus: ^7.2.1

[!] Flutter (Channel [user-branch], 3.13.9, on macOS 13.6.3 22G436
    darwin-x64, locale en-US)
    ! Flutter version 3.13.9 on channel [user-branch] at
      /Users/developerblockx/Documents/development/flutter
      Currently on an unknown channel. Run `flutter channel` to
      switch to an official channel.
      If that doesn't fix the issue, reinstall Flutter by following
      instructions at https://flutter.dev/docs/get-started/install.
    ! Upstream repository unknown source is not a standard remote.
      Set environment variable "FLUTTER_GIT_URL" to unknown source
      to dismiss this error.
    • Framework revision d211f42860 (5 months ago), 2023-10-25
      13:42:25 -0700
    • Engine revision 0545f8705d
    • Dart version 3.1.5
    • DevTools version 2.25.0
    • If those were intentional, you can disregard the above
      warnings; however it is recommended to use "git" directly to
      perform update checks and upgrades.

[✓] Android toolchain - develop for Android devices (Android SDK
    version 34.0.0)
    • Android SDK at /Users/developerblockx/Library/Android/sdk
    • Platform android-34, build-tools 34.0.0
    • Java binary at: /Applications/Android
      Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build
      17.0.7+0-17.0.7b1000.6-10550314)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 15.2)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 15C500b
    • CocoaPods version 1.14.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google
      Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2023.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build
      17.0.7+0-17.0.7b1000.6-10550314)

[✓] VS Code (version 1.85.1)
    • VS Code at /Users/developerblockx/Downloads/Visual Studio
      Code.app/Contents
    • Flutter extension version 3.84.0

[✓] Connected device (2 available)
    • macOS (desktop) • macos  • darwin-x64     • macOS 13.6.3 22G436 darwin-x64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 122.0.6261.112

[✓] Network resources
    • All expected network resources are available.

dongnqdev avatar Mar 08 '24 09:03 dongnqdev

The documentation mentions the following:

  /// Share [XFile] objects.
  ///
  /// Remarks for the web implementation:
  /// This uses the [Web Share API](https://web.dev/web-share/) if it's
  /// available. Otherwise, uncaught Errors will be thrown.
  /// See [Can I Use - Web Share API](https://caniuse.com/web-share) to
  /// understand which browsers are supported. This builds on the
  /// [`cross_file`](https://pub.dev/packages/cross_file) package.
  • https://web.dev/web-share/
  • https://caniuse.com/web-share

The code essentially all does is to call to dart:html share method with a list of "web" files.

https://github.com/fluttercommunity/plus_plugins/blob/main/packages/share_plus/share_plus/lib/src/share_plus_web.dart#L105

One improvement that could be done is using the canShare method from the Navigator to check if those files are "shareable": https://web.dev/articles/web-share#sharing_files as it looks like not all types of files are supported

One thing you can try as well is setting the mimeType for all files, just in case that helps the browser.

miquelbeltran avatar Mar 08 '24 09:03 miquelbeltran

@miquelbeltran Thank for your response. I did check the version of safari before posting my issue. My iPhone is running 17.3.1, so the safari on my phone is supported.

  • I will try your suggestion and post the result here. Thanks for your help

dongnqdev avatar Mar 08 '24 11:03 dongnqdev

@miquelbeltran Hi Miquelbentran I have tried to specify the mimeType, but still got the same problem. This is my code. About Navigator class, I couldn't find canShare method.

Future<void> saveAndShare(
      Uint8List bytes, WidgetRef ref, bool? isFirstShared) async {
    late final XFile file;
    if (kIsWeb) {
      file = XFile.fromData(bytes, mimeType: 'mage/png');<==== HERE
    } else {
      final directory = await getApplicationDocumentsDirectory();
      final image = File('${directory.path}/xlp.png');
      image.writeAsBytesSync(bytes);
      file = XFile(image.path); 
    }

    final result = await Share.shareXFiles([file],
        subject: BStrings.current.welcomeToBlockx,
        text: BStrings.current.welcomeToBlockx);
 
  }

This is StackTrace

TRACE 1: dart-sdk/lib/html/dart2js/html_dart2js.dart 22831:49                              share]
packages/share_plus/src/share_plus_web.dart 105:22                                shareXFiles
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 45:50                <fn>
dart-sdk/lib/async/zone.dart 1407:47                                              _rootRunUnary
dart-sdk/lib/async/zone.dart 1308:19                                              runUnary
dart-sdk/lib/async/future_impl.dart 156:18                                        handleValue
dart-sdk/lib/async/future_impl.dart 840:44                                        handleValueCallback
dart-sdk/lib/async/future_impl.dart 869:13                                        _propagateToListeners
dart-sdk/lib/async/future_impl.dart 632:7                                         [_complete]
dart-sdk/lib/async/stream_pipe.dart 61:11                                         _cancelAndValue
dart-sdk/lib/async/stream.dart 1581:7                                             <fn>
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 574:37  _checkAndCall
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 579:39  dcall
dart-sdk/lib/html/dart2js/html_dart2js.dart 37263:58                              <fn>
dart-sdk/lib/async/zone.dart 1415:13                                              _rootRunUnary
dart-sdk/lib/async/zone.dart 1308:19                                              runUnary
dart-sdk/lib/async/zone.dart 1217:7                                               runUnaryGuarded
dart-sdk/lib/async/zone.dart 1254:26                                              <fn>

dart-sdk/lib/html/dart2js/html_dart2js.dart 22831:49                              share]
packages/share_plus/src/share_plus_web.dart 105:22                                shareXFiles
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 45:50                <fn>
dart-sdk/lib/async/zone.dart 1407:47                                              _rootRunUnary
dart-sdk/lib/async/zone.dart 1308:19                                              runUnary
dart-sdk/lib/async/future_impl.dart 156:18                                        handleValue
dart-sdk/lib/async/future_impl.dart 840:44                                        handleValueCallback
dart-sdk/lib/async/future_impl.dart 869:13                                        _propagateToListeners
dart-sdk/lib/async/future_impl.dart 632:7                                         [_complete]
dart-sdk/lib/async/stream_pipe.dart 61:11                                         _cancelAndValue
dart-sdk/lib/async/stream.dart 1581:7                                             <fn>
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 574:37  _checkAndCall
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 579:39  dcall
dart-sdk/lib/html/dart2js/html_dart2js.dart 37263:58                              <fn>
dart-sdk/lib/async/zone.dart 1415:13                                              _rootRunUnary
dart-sdk/lib/async/zone.dart 1308:19                                              runUnary
dart-sdk/lib/async/zone.dart 1217:7                                               runUnaryGuarded
dart-sdk/lib/async/zone.dart 1254:26                                              <fn>

dongnqdev avatar Mar 09 '24 07:03 dongnqdev

That doesn't look correct --> 'mage/png' it should be 'image/png' but anyway, this looks like an issue with the underlying browser/js rather than something the plugin can fix

miquelbeltran avatar Mar 09 '24 12:03 miquelbeltran

@miquelbeltran Yes, I tried the 'image/png', i missed the letter 'I' when copy the code. Thank you for clarifying. I have tried on safari (Desktop), chrome (Desktop), chome (IOS), Safari (IOS), chrome (Android). They all got the same problem, the pop up is white.

dongnqdev avatar Mar 09 '24 15:03 dongnqdev

same issue, flutter: 3.16.9

junixapp avatar Mar 20 '24 09:03 junixapp