How to add conditional imports across Flutter mobile,web and window?
Asked Answered
M

8

28

I have flutter application which uses different webview plugin for each platform(mobile, web, window).
Though I am able to import platform base on web and mobile, I am not able to import for windows.

I have tried adding else condition if it is not mobile or web, but it is taking mobile plugin.

  1. This is how I import package for web and mobile (Working).
import 'package:eam_flutter/form/mobileui.dart'
    if (dart.library.html) 'package:eam_flutter/form/webui.dart'
    as multiPlatform;   
  1. This is how I import package for web, mobile and windows (Not Working, it is showing mobile webview exception since it doesn't support desktop).
import 'package:eam_flutter/form/windowui.dart'
    if (dart.library.html) 'package:eam_flutter/form/webui.dart'
    if (dart.library.io) 'package:eam_flutter/form/mobileui.dart'
    as multiPlatform;

How can I specify conditional imports for windows?

Manuel answered 11/6, 2021 at 12:58 Comment(5)
You cannot; see #62725298Papillose
@Papillose is there any workaround to this?Pentangular
@codingwithtashi Workaround for what? This question doesn't state a problem to be solved, only a desired solution, and that particular solution is impossible. There are probably other solutions to the underlying problem.Papillose
@Papillose I meant, how to make it work without platform error, but never mind I got it working. ThanksPentangular
I just did the code above and am having a breakpoint here: completer.complete(files.map((html.File file)Scharaga
P
26

For anyone else finding this, note that the accepted answer is not an answer to the question that was asked. The answer to the question that was asked is that you cannot. There is no way to use conditional imports to get different behavior between mobile and desktop; see this comment from the Dart team.

Papillose answered 14/6, 2021 at 18:3 Comment(2)
How to use the same code for mobile/web if no conditional imports are available?Decorator
@NazariiKahaniak You're asking a different question. You can have conditional imports based on VM vs. web (as demonstrated in the question); you cannot have conditional imports based on different VM platforms (e.g. mobile vs. desktop).Lurk
P
12

Since there is no conditional import support for window since it comes under dart io. I have this workaround and found it working.
I end up creating file for each platform with different package import.

import 'package:flutter/foundation.dart' show kIsWeb;
import 'dart:io' as io;
if(kIsWeb){
{
     return WebPage();  //your web page with web package import in it
}
else if (!kIsWeb && io.Platform.isWindows) {
     return WindowsPage(); //your window page with window package import in it
    } 
else if(!kIsWeb && io.Platform.isAndroid) {
     return AndroidPage();  //your android page with android package import in it
    } 
//you can add others condition...
Pentangular answered 14/6, 2021 at 12:45 Comment(3)
Note that this is an answer to a different question than was asked. The question was about having different compile-time behavior; this gives different runtime behavior. For cases where you want the latter this isn't really a workaround, it's the normal way of doing it. For the former (if for some reason that is actually needed), it doesn't help so isn't a workaround at all.Papillose
@smorgan, thanks. With given codes I can avoid the issue which I am getting. I think I should go with this since there is no conditional import for windowsManuel
@Manuel This is why it's usually much better to ask questions about the problem you are trying to solve, rather than how to implement one specific solution that you think is the solution to the problem. If you'd asked how to run different code on different platforms, this would be a good answer answer. Instead there's now a SO question with an incorrect accepted answer that will likely confused other people in the future.Papillose
L
4

Instead use that package.

universal_html
Leisha answered 14/6, 2023 at 16:18 Comment(0)
R
3

Maybe we no longer need conditional import. Look at the code below:

import 'package:package1/package1.dart';
import 'package:package2/package2.dart';

const keepFunc1 = bool.fromEnvironment('KEEP_FUNC1');
dynamic result2;

void main() {
  if (keepFunc1) {
    result2 = Calculator1()..addOne(1);
  } else {
    result2 = Calculator2()..addOne(1);
  }
  runApp(const MyApp());
}

If KEEP_FUNC1 environment variable is not specified to true. The package1 and the class Caculator1 won't be packaged into apk or ipa.

For more details, see the answer I wrote here.

So we can import all packages and use a const environment value to decide what packages to import. The tree-shaking mechanism is smart enough to remove unused parts.

Reiterate answered 7/11, 2022 at 6:50 Comment(0)
R
3

Platform-conditional imports are possible, but they are tricky.

First you have to check, if a platform-specific library (that you might want to use) exists on compile time:

my_widget.dart:

export 'my_widget/stub.dart'
    if (dart.library.js_util) 'my_widget/web.dart'
    if (dart.library.io) 'my_widget/mobile.dart';

Then define a "stub" (think "interface"), that defines the available methods, but can be compiled directly:

my_widget/stub.dart:

import 'package:flutter/material.dart';

typedef HandleEventFn = Future<void> Function();

Widget buildMyWidget({required BuildContext context, HandleEventFn? onEvent}) {
  throw UnimplementedError("This is not implemented for the current platform");
}

Now you can define an actual implementation, that is used, if dart.library.js_util exists (e.g. on web):

my_widget/web.dart:


import 'package:flutter/material.dart';

import 'stub.dart';

Widget buildMyWidget({required BuildContext context, HandleEventFn? onEvent}) {
  return TextButton(onPressed: onEvent, child: const Text("Push me (WEB)"));
}

and an actual implementation, that is used when dart.library.io exists (e.g. on mobile):

my_widget/mobile.dart:


import 'package:flutter/material.dart';

import 'stub.dart';

Widget buildMyWidget({required BuildContext context, HandleEventFn? onEvent}) {
  return TextButton(onPressed: onEvent, child: const Text("Push me (MOBILE)"));
}

Note that the type of onEvent is defined as HandleEventFn in the stub, so that you can easily adjust this without having to change multiple files (DRY principle).

Riocard answered 8/2, 2024 at 14:28 Comment(0)
D
2

Check this example you need to create 2 files one for web & another for os and use condition on import

Deduct answered 6/11, 2022 at 21:14 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Polyurethane
G
1

For me the solution was to use a universal html package:

https://pub.dev/packages/universal_html

dependencies:
  universal_html: ^2.2.4
import 'package:universal_html/html.dart' as html;

String getCurrentUrl() {
  // Access the 'window.location' object from JavaScript
  var url = html.window.location.href;
  if (url.split(":").length > 1) {
    return url;
  }
  return defaultUrl;
}

this will return the URL that is in your browser bar. And for android per default it will be http://localhost/

Gastrocnemius answered 19/2, 2024 at 0:14 Comment(0)
D
1

Flutter docs for conditional imports: https://dart.dev/guides/libraries/create-packages#conditionally-importing-and-exporting-library-files

That includes latest js_interop imports.

For example,

export 'src/hw_none.dart' // Stub implementation
    if (dart.library.io) 'src/hw_io.dart' // dart:io implementation
    if (dart.library.js_interop) 'src/hw_web.dart'; // package:web implementation
Dusen answered 3/7, 2024 at 14:6 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.