Open ekuleshov opened 1 year ago
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 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)
Same here! I am using XFile.fromData(/* some image byte Uint8List */)
if that helps finding the cause.
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)
Tried on Safari and Edge also, none worked.
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?
I have the same problem, has anyone solved it?
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');
Does anyone knows how to fix it ?
@dongnqdev would you mind sharing your implementation?
@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.
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.
The code essentially all does is to call to dart:html
share
method with a list of "web" files.
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 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.
@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>
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 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.
same issue, flutter: 3.16.9
You can use MemoryFileSystem for web and LocalFileSystem for mobile from https://pub.dev/packages/file.
final FileSystem _fileSystem = kIsWeb ? MemoryFileSystem() : const LocalFileSystem();
See their example to create a file https://github.com/google/file.dart/blob/master/packages/file/example/main.dart.
You can than pass this file's path and basename into an XFile.
XFile(
file.path,
name: file.basename,
)
But for now the Share sheet for me is only shown in Safari (not Chrome, not Firefox).
So as a fallback you can have a download action.
import 'package:universal_html/html.dart' as html;
final result = await Share.shareXFiles(
[
XFile(
file.path,
name: file.basename,
),
],
subject: "Subject",
text:
"Text",
// required for iPads, see https://pub.dev/packages/share_plus
sharePositionOrigin: (context.findRenderObject() as RenderBox?)!
.localToGlobal(Offset.zero) &
(context.findRenderObject() as RenderBox?)!.size,
);
// Web fallback if Share API is not available
if (result.status == ShareResultStatus.unavailable && kIsWeb) {
final url =
"data:application/pdf;base64,${base64Encode(await file.readAsBytes())}";
try {
final html.AnchorElement anchorElement =
html.AnchorElement(href: url);
anchorElement.download = model.fetchedPDFFile!.basename;
anchorElement.click();
anchorElement.remove();
} catch (e) {
await launchUrl(
Uri.parse(
url,
),
);
}
}
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
The documentation states On web, this uses the [Web Share API](https://web.dev/web-share/) if it's available. Otherwise it falls back to downloading the shared files.
However, this fallback does not seem to be working, which in my opinion is a bug. It can also be easily fixed with proper fallback handling.
Below is some code that works great for me, using the universal html package.
Future<void> _downloadWeb(XFile file) async {
final bytes = await file.readAsBytes();
final blob = html.Blob([bytes]);
final url = html.Url.createObjectUrlFromBlob(blob);
final anchor = html.document.createElement('a') as html.AnchorElement
..href = url
..style.display = 'none'
..download = file.name;
html.document.body!.children.add(anchor);
anchor.click();
html.document.body!.children.remove(anchor);
html.Url.revokeObjectUrl(url);
}
However, this fallback does not seem to be working, which in my opinion is a bug.
Yeah, looking at the code seems that it was removed (or even never implemented?).
Anyway, if you want, you can submit a PR with the change... Or the README should be corrected.
Platform
Chrome web browser on MacOS
Plugin
share_plus
Version
latest from the main
Flutter SDK
3.7.8
Steps to reproduce
Code Sample
Logs
Flutter Doctor
Checklist before submitting a bug
flutter pub upgrade
flutter clean