fluttercommunity / plus_plugins

Flutter Community Plus Plugins
BSD 3-Clause "New" or "Revised" License
1.59k stars 958 forks source link

[Bug]: Share not working on web #1320

Closed carotkut94 closed 1 year ago

carotkut94 commented 1 year ago

Platform

Web (Chrome(Mac), Safari(Mac), Mobile Safari/Chrome)

Plugin

share_plus

Version

6.2.0

Flutter SDK

3.3.7

Steps to reproduce

  1. open the app in the chrome
  2. tab on the button with below code snippet

Code Sample

ElevatedButton(onPressed: () async {
              var data = await http.get(Uri.parse("https://cdn.pixabay.com/photo/2016/02/28/12/55/boy-1226964_1280.jpg"));
              XFile xfile = XFile.fromData(data.bodyBytes, mimeType: "image/jpeg");
              await Share.shareXFiles([xfile]);
            }, child: const Text("Share Photo"),)

add this to you widget tree, and tap on this button to share

Instruction share_plus readme, are ambiguous for web there is no way to have a code like

"On web you can use SharePlus.shareXFiles() "

Logs

Waiting for connection from debug service on Chrome...
Restarted application in 91ms.
TypeError: this.share is not a function
dart-sdk/lib/html/dart2js/html_dart2js.dart 22913:49                              share]
packages/share_plus/src/share_plus_web.dart 103:22                                shareXFiles
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 45:50                <fn>
dart-sdk/lib/async/zone.dart 1653:54                                              runUnary
dart-sdk/lib/async/future_impl.dart 147:18                                        handleValue
dart-sdk/lib/async/future_impl.dart 766:44                                        handleValueCallback
dart-sdk/lib/async/future_impl.dart 795:13                                        _propagateToListeners
dart-sdk/lib/async/future_impl.dart 557: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 334:14  _checkAndCall
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 339:39  dcall
dart-sdk/lib/html/dart2js/html_dart2js.dart 37341:58

Flutter Doctor

[✓] Flutter (Channel stable, 3.3.7, on macOS 13.1 22C5033e darwin-arm, locale en-IN)
[!] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
    ✗ cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.
[✓] Xcode - develop for iOS and macOS (Xcode 14.1)
[✓] Chrome - develop for the web
[!] Android Studio
    ✗ Unable to find bundled Java version.
[✓] Android Studio (version 2021.2)
[!] Android Studio
    ✗ Unable to find bundled Java version.
[✓] IntelliJ IDEA Ultimate Edition (version 2022.2.3)
[✓] VS Code (version 1.73.0)
[✓] Connected device (3 available)
[✓] HTTP Host Availability

Checklist before submitting a bug

miquelbeltran commented 1 year ago

I guess we should add this to the package README:

  /// 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.

So, according to https://caniuse.com/web-share, is your browser supported?

miquelbeltran commented 1 year ago

According to that site, Share on web is only supported on Chrome on Windows, and you are on a Mac.

Leaving this open because this needs to be documented in the package README.md

carotkut94 commented 1 year ago

Oh, But I see safari as supported browser, but it doesn't work there as well.

carotkut94 commented 1 year ago

Also hosted it locally, and tried to access the same on mobile browsers, safari on iOS, chrome on android, doesn't work on those as well

miquelbeltran commented 1 year ago

Oh, But I see safari as supported browser, but it doesn't work there as well.

That would be a different issue then. Can you paste logs and console logs from the browser here when running on Safari?

miquelbeltran commented 1 year ago

I tried to reproduce on Safari, but I am not able to set up a dev environment there, so I am waiting for your logs.

carotkut94 commented 1 year ago

same here, the logs are not available from safari, maybe because of the unavailability of dev tools, but does tapping on share works on safari instance of yours?

miquelbeltran commented 1 year ago

When I run the site there, I saw an error in the Safari console that didn't seem related to the plugin. You can enable console logs on it, but I'd like to see debug logs from a supported browser/OS to know exactly that the problem is.

carotkut94 commented 1 year ago

So I tried getting logs from terminal, no logs maybe because of debug services are only available on Chrome, and on safari console, whenever I tap on the said button to share an xFile, it just gives this.

SCR-20221109-nrp

carotkut94 commented 1 year ago

here are browser logs from Edge and Chrome on windows which is supported as per https://caniuse.com/web-share

Screenshot 2022-11-09 171624

ueman commented 1 year ago

Sharing on web must be initiated via click, see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/share#security

It also has a couple of other limitations as mentioned in https://w3c.github.io/web-share/#share-method

miquelbeltran commented 1 year ago

Can you elaborate @ueman, does it mean that the native web share method cannot be called from Flutter?

miquelbeltran commented 1 year ago

Also ping to @ThexXTURBOXx who implemented the web share

ueman commented 1 year ago

Can you elaborate @ueman, does it mean that the native web share method cannot be called from Flutter?

It can, but it can't be called without any user interaction. The links do explain it better than I can, though.

I just thought it would be nice to have that mentioned in the docs somewhere, because it's kinda quirky compared to what we know from Android and iOS.

ThexXTURBOXx commented 1 year ago

I tested the web share on Edge and Chrome on Windows - in addition to some other ones. The library worked on both of them back then. However, there have been some updates since then, maybe one of them broke it? I will test functionality again in a few minutes.

ThexXTURBOXx commented 1 year ago

The example implementation has been broken since https://github.com/fluttercommunity/plus_plugins/commit/e1d3553b69a0156701613b2fc1cbb9cad1e3fa0c After fixing it, I tested it again on Chrome, Edge, and Firefox. As alreaddy stated before, sharing files on Firefox is not supported in any way. However, sharing simple text is still working. Chrome and Edge are still working completely fine when sharing text and/or files. I am using latest main branch share_plus and Flutter 3.3.8 in the example web (with a tiny fix in the example which I will PR soon).

Thus, it must be something on your end. Please try out the example and see if that one also does not work for you (after I fixed it).

Firefox: grafik

Chrome: grafik

Edge: grafik

miquelbeltran commented 1 year ago

After fixing it, I tested it again on Chrome, Edge, and Firefox.

Can you submit a PR with the example fix? I'd like to understand what broke it.

ThexXTURBOXx commented 1 year ago

@miquelbeltran PR has been submitted! :)

miquelbeltran commented 1 year ago

Thanks! I see that the issue with the example is unrelated to the problem @carotkut94 has, but at least they can use now the example to check if it works at all.

carotkut94 commented 1 year ago

@ueman if you see the the code which I proposed, it has a click action attached to a button, also., the sample app from the source, also doesn't work on the said browsers, and fails with the same error. the error which you see in the browser, are coming only when I am tapping in the button.

ThexXTURBOXx commented 1 year ago

@carotkut94 You can find in-browser examples here: https://developer.mozilla.org/en-US/docs/Web/API/Navigator/share#examples What happens if you use the files example?

Firefox (as expected, does not work): grafik

Chrome (works): grafik

carotkut94 commented 1 year ago

@ueman it works fine on safari, here is the snap SCR-20221122-vpz

ThexXTURBOXx commented 1 year ago

@nilsreichardt and @carotkut94 I have done some more digging and still cannot reproduce this issue. In order to properly test this, I have deployed a build of the example at https://femtopedia.de/shareplustest/ Please try if that one works for you. If it does, there is some error in your Flutter project. If it does not work, your browser is misconfigured or does not support sharing for some reason.

Here, I have added a picture using the "Add image" button and clicked on "Share": grafik

ponderMuse commented 1 year ago

Hi,

I am in the process of testing a share button on a flutter app which is built for both mobile devices as native Flutter Mob app as well as for web browsers as a Flutter Web app.

In my tests so far, the share button (currently using share_plus-6.3.0, share_plus_platform_interface-3.2.0) works on the native mobile app build but not on web browser using the Flutter Web js built app.

I understand that the Web Share API is currently only supported on some browsers and not all of them.

So when I test on Chrome web browser on Linux I get: TypeError: this.share is not a function and, indeed, in caniuse it shows that on Linux web browsers the Web Share API is not currently supported.

But then, I am also testing on Chrome on Android 13 mobile device with Chrome version 107.0.5304.105 which, according to caniuse, Web Share API is supposed to be currently supported on Android Chrome 107 but, when I run the web app on that browser I still get the same: TypeError: this.share is not a function?

Just for ref, my code attempts to share an image as well as text with following code:

try {
    XFile xFile = XFile.fromData(_imageBytes!, mimeType: 'image/png');
    await Share.shareXFiles([xFile],
        text: '#LettrCollectr #DailyCollection #${daily.number}', sharePositionOrigin: rect);
} catch(error) {
    rethrow;
}

Probably out of the scope of this thread but, while Web Share API support for web browsers moves forward, are there any existing alternative methods for sharing images with text to social media apps within Flutter Web apps?

Thanks for any help on this.

ThexXTURBOXx commented 1 year ago

@ponderMuse Please try my build of the example if that works for you on mobile: https://femtopedia.de/shareplustest/

ponderMuse commented 1 year ago

@ponderMuse Please try my build of the example if that works for you on mobile: https://femtopedia.de/shareplustest/

@ThexXTURBOXx , yes. Your example worked okay on Android 13 mobile with Chrome version 107.0.5304.105.

Is your code using Share.shareXFiles(...) too?

ThexXTURBOXx commented 1 year ago

@ponderMuse Thanks for confirming! My code is the compiled example without any changes (except for changing the path base).

ponderMuse commented 1 year ago

@ThexXTURBOXx the only obvious difference I can see so far is that my code is building the XFile using Uint8List byte data instead of an image path?

ThexXTURBOXx commented 1 year ago

@ponderMuse You can also try the Uint8List approach in the compiled example by clicking Share XFile from Assets: grafik

ThexXTURBOXx commented 1 year ago

I can see a difference between the example and your code: You and @carotkut94 are not passing a name to XFile. Maybe that is causing the problem? Please try the following code in your app:

try {
    XFile xFile = XFile.fromData(_imageBytes!, name: 'somename.png', mimeType: 'image/png');
    await Share.shareXFiles([xFile],
        text: '#LettrCollectr #DailyCollection #${daily.number}', sharePositionOrigin: rect);
} catch(error) {
    rethrow;
}
ponderMuse commented 1 year ago

@ThexXTURBOXx , the Share XFile from assets example works too.

I have added in a name: somename.png parameter but still shows same error.

Worth also pointing out that the image bytes I am trying to share are only held in memory and not in any file on the device anywhere. The Image data is generated using:

await pictureRecorder.endRecording().toImage(w.toInt(), h.toInt());

and the image is created and displayed okay in a Widget which you can then optionally share using the share button.

I will next save the image to a temp file and share it from the file data to see if that makes a difference?

ponderMuse commented 1 year ago

@ThexXTURBOXx actually, I don't think it is possible to save data to a temp file in web browser so not sure if I can do what I thought of in my last comment :o/

ponderMuse commented 1 year ago

@ThexXTURBOXx when I download your example code directly and run it in my environment. The app loads up fine on my Android 13 Chrome web browser but when I try share an image the same way as with your live version on femtopedia.de I get the error the same as in my own code.

What Flutter version does your app run on live?

My Flutter version is Flutter (Channel stable, 3.3.9)

ThexXTURBOXx commented 1 year ago

I was using Flutter stable 3.3.8. However, I have also tried 3.3.9 a few hours ago and it worked exactly the same. The bug report above was about 3.3.7. Sadly, there is still no way for me to reproduce the issue and it seems like some flutter systems are "broken"?

ponderMuse commented 1 year ago

@ThexXTURBOXx I'll have another look tomorrow see if I can figure out what else the issue might be 🧐

ponderMuse commented 1 year ago

The TypeError: this.share is not a function error occurs in html_dart2js.dart and my guess is that the build done on a Linux x64 system is prob different to a build done on a macos system resulting in slightly different compiled js code.

I had a case with Flutter web before where code functionality in a build using Flutter 3.3.6 on a x64 Linux system worked okay on web browsers whereas the same code built using Flutter 3.3.6 on a Raspberry Pi aarch64 Linux system did not work okay on web browsers. It turned out however that building the same code on the Raspberry pi using Flutter channel master (which was on a 3.6.0 version instead of 3.3.6) did work okay on web browsers.

So I think that a specific Flutter version on one architecture system can produce different js code to what the same Flutter version on a different architecture system might produce.

ThexXTURBOXx commented 1 year ago

That might be a good guess. However, I have deployed another build: https://femtopedia.de/shareplustestl/ This one was done through WSL Ubuntu 22.04 and it works fine in my browsers. Which system do you use for your builds?

ponderMuse commented 1 year ago

My system is also Ubuntu 22.04 but on x86_64 bare metal and not through WSL.

Do you know which Flutter version specifically your WSL version was built with? I can try and pull that version and give it a go

ThexXTURBOXx commented 1 year ago

flutter doctor -v gives me

[✓] Flutter (Channel stable, 3.3.9, on Ubuntu 22.04.1 LTS 5.15.74.2-microsoft-standard-WSL2, locale C.UTF-8)
    • Flutter version 3.3.9 on channel stable at /root/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision b8f7f1f986 (8 days ago), 2022-11-23 06:43:51 +0900
    • Engine revision 8f2221fbef
    • Dart version 2.18.5
    • DevTools version 2.15.0
ponderMuse commented 1 year ago

Same version as me. That's really odd. I've downloaded your example code as is and only commented out the ImagePreviews widget as I don't have it downloaded but otherwise its the same code and yet. on my mobile browser it still fails with the error described in this thread.

flutter doctor -v:

[✓] Flutter (Channel stable, 3.3.9, on Ubuntu 22.04.1 LTS 5.15.0-53-generic, locale en_GB.UTF-8) • Flutter version 3.3.9 on channel stable at /mnt/sdk/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision b8f7f1f986 (8 days ago), 2022-11-23 06:43:51 +0900 • Engine revision 8f2221fbef • Dart version 2.18.5 • DevTools version 2.15.0

Package versions:

ponderMuse commented 1 year ago

One difference I notice in your example code is in web/index.html.

Your index.html body is:

<body>
  <!-- This script installs service_worker.js to provide PWA functionality to
       application. For more information, see:
       https://developers.google.com/web/fundamentals/primers/service-workers -->
  <script>
    if ('serviceWorker' in navigator) {
      window.addEventListener('flutter-first-frame', function () {
        navigator.serviceWorker.register('flutter_service_worker.js');
      });
    }
  </script>
  <script src="main.dart.js" type="application/javascript"></script>
</body>

Whereas on my project, index.html body is:

  <script src="main.dart.js" type="application/javascript"></script>
  <script>
    window.addEventListener('load', function(ev) {
      // Download main.dart.js
      _flutter.loader.loadEntrypoint({
        serviceWorker: {
          serviceWorkerVersion: serviceWorkerVersion,
        }
      }).then(function(engineInitializer) {
        return engineInitializer.initializeEngine();
      }).then(function(appRunner) {
        return appRunner.runApp();
      });
    });
  </script>

If I try to run your example code on my project with your index.html then the app doesn't load up at all and I get error:

Flutter Web Bootstrap: Programmatic
Do not call didCreateEngineInitializer by hand. Start with loadEntrypoint instead.
TypeError: this._didCreateEngineInitializerResolve is not a function

I don't know enough about serviceWorkers and navigators to understand what is going on there though...

--- UPDATE ---

I have pulled down the whole index.html from your example and run it with it intact and the example now loads okay but the share function still fails with: TypeError: this.share is not a function

ponderMuse commented 1 year ago

I've gone as far as cloning this share_plus plugin project on my dev machine:

git clone https://github.com/fluttercommunity/plus_plugins.git

Then cding into:

cd /mnt/data/git/www.github.com/fluttercommunity/plus_plugins/packages/share_plus/share_plus/example/lib

Then Running:

flutter run --web-hostname 192.168.1.55 --web-port 42000
Changing current working directory to: /mnt/data/git/www.github.com/fluttercommunity/plus_plugins/packages/share_plus/share_plus/example
Multiple devices found:
Linux (desktop) • linux  • linux-x64      • Ubuntu 22.04.1 LTS 5.15.0-53-generic
Chrome (web)    • chrome • web-javascript • Google Chrome 108.0.5359.71
[1]: Linux (linux)
[2]: Chrome (chrome)
Please choose one (To quit, press "q/Q"): 2
Launching lib/main.dart on Chrome in debug mode...
Waiting for connection from debug service on Chrome...             13.7s
This app is linked to the debug service: ws://127.0.0.1:46873/mntd9Y3Lnhk=/ws
Debug service listening on ws://127.0.0.1:46873/mntd9Y3Lnhk=/ws

💪 Running with sound null safety 💪

🔥  To hot restart changes while running, press "r" or "R".
For a more detailed help message, press "h". To quit, press "q".

An Observatory debugger and profiler on Chrome is available at: http://127.0.0.1:46873/mntd9Y3Lnhk=
Flutter Web Bootstrap: Auto
The Flutter DevTools debugger and profiler on Chrome is available at: http://127.0.0.1:9100?uri=http://127.0.0.1:46873/mntd9Y3Lnhk=

I connect up my physical Android 13 mobile to my dev machine using usb cable and allow USB debugging on it.

I then load up the page on my physical Android 13 mobile using its Chrome browser (version 107.xxx).

But the share functionality still fails. See screenshot taken from my dev machine's Chrome browser's chrome://inspect/#devices:

share-plus-plugin-demo

This is as far as I got with testing this functionality which now has no modifications from my end of things.

I will have to leave things as is for now but I am happy to try any other suggestions if anyone has any.

ueman commented 1 year ago

Did you try http vs https? There are also headers which disallow the web share api: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy/web-share

ponderMuse commented 1 year ago

@ueman I haven't packaged up the app yet as it is still in dev. The live version will however run over https 100%.

Would the error described above be the one shown if the web share api was being disallowed by the browser?

I can run Chrome on my dev machine with --disable-web-security but I am not sure how I can do that on an Android device's Chrome web browser.

ThexXTURBOXx commented 1 year ago

I am unsure about this issue, but I think, it is pretty safe to say that share_plus is not the cuplrit here. Maybe, it is better to report this bug over at flutter itself?

ponderMuse commented 1 year ago

For now I will wrap the share functionality in my code with a safeguard mechanism to let users know that share functionality is not currently available on their device if and when the error ever occurs. This way I will be able to merge the share functionality into my project's stable branch and ship it to live with the safeguard mechanism in place. Then I can test it fully deployed over https.

I will see how that goes and report the issue over at flutter if by that point the problem still exists.

gramster commented 1 year ago

I'm experiencing this issue too ("this.share is not a function") with MacOS/Chrome; sharing works fine on iOS native. So I thought I'd just switch to shareFiles on the web, but then I get "'shareFiles' is deprecated and shouldn't be used. Use shareXFiles instead.." - why deprecate something in favor of something else that is known to not work on multiple platforms?

ThexXTURBOXx commented 1 year ago

@gramster shareFiles was never working on web and using it is discouraged as shareXFiles does exactly the same procedure in a platform-independent way. Hence, I don't exactly know why deprecating a non-working/platform-dependent function should be a bad thing?

github-actions[bot] commented 1 year ago

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 15 days

TechAurelian2 commented 1 year ago

I get the error 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)

    final XFile xFile = XFile.fromData(pngBytes, name: 'sharer.png', mimeType: 'image/png');
    int xFileLength = await xFile.length();
    debugHelper('XFile length: $xFileLength');
    if (kIsWeb) {
      debugHelper('Sharing on web');
      Share.shareXFiles(
        [
          xFile,
        ],
        text: userText,
      ).catchError((onError) {
        debugHelper('Error sharing: $onError');
      });
    } else {