fluttercandies / extended_image_library

package library for extended_image, extended_text and extended_text_field,provide common base class.

Home Page:https://pub.dev/packages/extended_image_library

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Bug report] Cannot compile `ExtendedImage.file` on the web

maRci002 opened this issue · comments

Version

7.0.2

Platforms

Web

Device Model

web compiler

flutter info

[√] Flutter (Channel stable, 3.7.11, on Microsoft Windows [Version 10.0.19045.2846], locale hu-HU)
    • Flutter version 3.7.11 on channel stable at C:\flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision f72efea43c (11 days ago), 2023-04-11 11:57:21 -0700
    • Engine revision 1a65d409c7
    • Dart version 2.19.6
    • DevTools version 2.20.1

[√] Windows Version (Installed version of Windows is version 10 or higher)

[√] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
    • Android SDK at C:\Users\maRci002\AppData\Local\Android\sdk
    • Platform android-33, build-tools 33.0.0
    • Java binary at: C:\Program Files\Android\Android Studio\jbr\bin\java
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-b2043.56-9586694)
    • All Android licenses accepted.

[√] Chrome - develop for the web
    • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe

[√] Visual Studio - develop for Windows (Visual Studio Community 2022 17.4.5)
    • Visual Studio at C:\Program Files\Microsoft Visual Studio\2022\Community
    • Visual Studio Community 2022 version 17.4.33403.182
    • Windows 10 SDK version 10.0.20348.0

[√] Android Studio (version 2022.2)
    • Android Studio at C:\Program Files\Android\Android Studio
    • 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.6+0-b2043.56-9586694)

[√] VS Code (version 1.77.2)
    • VS Code at C:\Users\maRci002\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.44.0

[√] Connected device (3 available)
    • Windows (desktop) • windows • windows-x64    • Microsoft Windows [Version 10.0.19045.2846]
    • Chrome (web)      • chrome  • web-javascript • Google Chrome 112.0.5615.138
    • Edge (web)        • edge    • web-javascript • Microsoft Edge 112.0.1722.39

[√] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!

How to reproduce?

Try to compile the following code:

import 'dart:io';

import 'package:extended_image/extended_image.dart';
import 'package:flutter/foundation.dart';

void main() {
  if (kIsWeb) {
    ExtendedImage.network('');
  } else {
    ExtendedImage.file(File(''));
  }
}

Log

Launching lib\main.dart on Chrome in debug mode...
Waiting for connection from debug service on Chrome...
lib/main.dart:10:24: Error: The argument type 'File/*1*/' can't be assigned to the parameter type 'File/*2*/'.
 - 'File/*1*/' is from 'dart:io'.
 - 'File/*2*/' is from 'package:extended_image_library/src/_platform_web.dart' ('../../AppData/Local/Pub/Cache/hosted/pub.dev/extended_image_library-3.4.1/lib/src/_platform_web.dart').
    ExtendedImage.file(File(''));
                       ^
Failed to compile application.

When I want to try import File from extended_image_library the program won't compile too:

import 'package:extended_image/extended_image.dart';
import 'package:extended_image_library/extended_image_library.dart' show File;
import 'package:flutter/foundation.dart';

void main() {
  if (kIsWeb) {
    ExtendedImage.network('');
  } else {
    ExtendedImage.file(File(''));
  }
}

Log

Launching lib\main.dart on Chrome in debug mode...
Waiting for connection from debug service on Chrome...
lib/main.dart:9:24: Error: The class 'File' is abstract and can't be instantiated.
    ExtendedImage.file(File(''));
                       ^^^^
Failed to compile application.

Logs

No response

Example code (optional)

No response

Contact

No response

In real world the network path and file path are represented as XFile.path, which is returned by ImagePicker.

@zmtzawqlp this is not a question this is a bug.

Keep in mind that image_picker uses the same technique as the one in my example code.

...
if (kIsWeb) {
  Image.network(pickedFile.path);
} else {
  Image.file(File(pickedFile.path));
}
...

This workaround doesn't work:
dint-dev/universal_io#19 (comment)

Current workarounds include creating a conditional export for the ExtendedImage.file constructor in my project, which throws an UnimplementedError on the web, to keep both the runtime and compile time happy.
Another option is to use the ExtendedImage.memory constructor, but it may not be necessary to read image bytes into memory since on the web, the blob might already be present in the browser cache, such as disk cache on the VM side it is also unecessary to read bytes into memory.

fluttercandies/extended_image#531

do not import 'dart:io' directly.

fluttercandies/extended_image#531

do not import 'dart:io' directly.

This is called workaround rather than fix fixing the bug. If you want to maintain the mock File class for web, check out the #50 pull request's first commit.

37bbeb1 plz check this

import 'package:extended_image/extended_image.dart';
import 'package:extended_image_library/extended_image_library.dart' show File;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      // This call to setState tells the Flutter framework that something has
      // changed in this State, which causes it to rerun the build method below
      // so that the display can reflect the updated values. If we changed
      // _counter without calling setState(), then the build method would not be
      // called again, and so nothing would appear to happen.
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: Center(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: kIsWeb
            ? ExtendedImage.network(
                'https://t7.baidu.com/it/u=1595072465,3644073269&fm=193&f=GIF')
            : ExtendedImage.file(File('')),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

@zmtzawqlp thank you very much it solves the problem. (I'm on phone but that changes seems fine)

One note: I still need to import File from extended_image_library

import 'package:extended_image_library/extended_image_library.dart' show File;

I can live with that but the perfect solution would be if extended_image exports that, currently it hides it:

https://github.com/fluttercandies/extended_image/blob/7a8d5781819a81842a1a72cb753ec26695703699/lib/extended_image.dart#L4

extended_image hide them, because other packages use extended_image and they are not use dart.library.html.
they will failed due to File from dart:io and File from extended_image_library, and i don't want to make a breaking change for other user.

Mock File and FileImage can be removed, as their constructor/methods already throw errors when called on the web. For instance, if you instantiate the dart:io File on the web and call any of its methods, Flutter throws an error that it is not available on the web. This is not a breaking change, as seen in issue #50. However, I can live with mock File and FileImage, but they are unnecessary and should not maintained.

Mock File and FileImage can be removed, as their constructor/methods already throw errors when called on the web. For instance, if you instantiate the dart:io File on the web and call any of its methods, Flutter throws an error that it is not available on the web. This is not a breaking change, as seen in issue #50. However, I can live with mock File and FileImage, but they are unnecessary and should not maintained.

mock it due to Web support flag.

mock it due to Web support flag.

You won't lose the web support flag. You can only lose the web support flag if you depend on a plugin that doesn't handle the web.

In the case of plugins in pubspec.yaml, it is defined which platforms can handle them. For instance:

flutter:
  plugin:
    platforms:
      android:
      ios:
      web:

In the case of a package which is pure Dart code (like extended_image / extended_image_library), it will support every platform, regardless of whether you are importing dart:html or dart:io, unless you are importing a plugin that doesn't handle the web platform or a package that has a transitive dependency on a plugin that doesn't handle the web.

For instance, you can check out https://pub.dev/packages/image_size_getter package. It imports dart:io and still got the web support flag, as shown here: https://github.com/CaiJingLong/dart_image_size_getter/blob/master/library/lib/file_input.dart

if your project use dart:io before, it will failed in web. This is only latest change of pub.dev and dart. This package is stable, there are not much reasons to change.

When I tried to import dart:html on VM it could not compile the other way around works when importing dart:io on web. I got your idea, thanks for your changes 37bbeb1 it works.

Error: Dart library 'dart:html' is not available on this platform.